JavaScript中this用法学习笔记


Posted in Javascript onMarch 17, 2019

JavaScript这门语言中,最令人迷惑的地方有三个,闭包、this、原型。针对大多数人,可以利用词法作用域等避开this的坑,但是我们不能一直生活在舒适区,要敢于打破砂锅问到底,对我们来说也是一种提升。

一、一般对this关键字的误解:

1、this指向函数自身

2、this指向函数词法作用域

我们可以看以下一段代码:

function test() {
test.a = 1;
this.a = 2;
console.log(test.a);
console.log(this.a);
console.log(test.a === this.a);
}

test();
console.dir(test);

在上面这段代码中,我们在全局声明一个方法test,给test中的a属性赋值1,当前方法中的this中的a属性赋值2,加入this指向函数自身,那么test.a === this,a并且都等于2.

下面我们来看下这段代码的运行结果:

JavaScript中this用法学习笔记

JavaScript中this用法学习笔记

从上可以看出,scopes为全局作用域window,this也指向这里,虽然函数本身也是一个对象,但是this并不指向这里。

有一点我们一定要记住,this是在运行时进行绑定的,并不是在编写时绑定的,它的上下文取决于函数调用时的各种条件。this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。

既然this是在运行时绑定的,那我们有没有办法改变当前this的绑定,使其不指向window,而指向方法test呢?答案是肯定的,我们可以借助一些强制绑定方法,如call、apply、bind来改变this的指向,我们可以将代码改成下面这种方式:

function test() {
 test.a = 1;
 this.a = 2;
 console.log(test.a);
 console.log(this.a);
 console.log(test.a === this.a);
 }
 
 test.call(test);
console.dir(test);

运行结果如下:

JavaScript中this用法学习笔记

JavaScript中this用法学习笔记

接下来我们看下this是否指向函数的词法作用域,以下有段比较有意思的代码:

function parent() {
 var a = 2;
 
 function child() {
 console.log(this.a)
 }
 child();
 
 }
parent();

假如this指向函数的词法作用域,那么child方法中的this.a应该是存在,实际上的执行结果如下:

JavaScript中this用法学习笔记

实际上,在JavaScript内部,作用域确实和对象类似,可见的标识符都是它的属性。但是作用域“对象”无法通过JavaScript代码访问,它存在JavaScript引擎内部。所以每当你想要把this和词法作用域的查找混合使用时,一定要提醒自己,这是无法实现的。

二、this的绑定规则

this的绑定规则大致分为以下几类:

2.1 默认绑定

2.2 隐式绑定

2.3 显式绑定

2.4 new绑定

2.1 默认绑定

上述示例中this的指向是指向window的,他们都有一个共同的特征,不带任何修饰的函数引用进行调用的,因此只能使用默认绑定,无法应用其他规则

2.2 隐式绑定

隐式绑定首先需要考虑的规则就是调用位置是否有上下文对象,或者说是否被某个对象拥有或包含,例如:

JavaScript中this用法学习笔记

这里的this就是指向对象obj。还有类似一些DOM事件的绑定,document.getElementById('xxx').addEventListener('click', function(){xxx});回调方法中的this是指向选择器选中的元素的。这种情况下可以简单的理解为this指向调用方法.前面的那个对象。

JavaScript中this用法学习笔记

2.3 显式绑定

显示绑定在开发过程中运用的比较多,借助于这些显式绑定方法,可以直接改变当前方法的this指向,使得js语言非常的灵活。主要有call、apply和bind三种,基本使用如下:

function sum() {
 console.log(this.a + this.b);
 }
 var obj1 = {
 a: 1,
 b: 2
 };
 var test = sum.bind(obj1);
 sum.call(obj1); //3
sum.apply(obj1); //3
test(); //3

注意事项:

call && apply第一个参数接受的是this对象,call第二个参数以后可以接受字符串形式的参数,apply接受的是一个类数组/数组参数

将null || undefined作为this的绑定对象传入call/apply/bind时,这些值在调用时会被忽略,实际应用的是默认绑定规则

2.4 new绑定

JavaScript语言中的new操作符和其他面向对象语言中的new操作符不大一样,因为在JavaScript中没有对象的概念。所有的函数都可以使用new来调用,new的调用又称为构造函数调用。在构造函数调用过程中,会自动执行下面的操作。

1、创建(或者说构造)一个全新的对象

2、这个对象会被执行[[Prototype]]连接

3、这个新对象会绑定到函数调用的this

4、如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象

构造函数也是js中常用的一种设计模式,如以下代码:

function Test(a, b) {
       this.a = a;
       this.b = b;
       this.add = function() {
         debugger;
        console.log(this.a + this.b);
       }
    }
    var cc = new Test(1, 2);
    cc.add();
    console.log(cc);

在new调用过程中,返回了一个新对象,并且该对象的this指向Test;

JavaScript中this用法学习笔记

Javascript 相关文章推荐
js 动态文字滚动的例子
Jan 17 Javascript
js去空格技巧分别去字符串前后、左右空格
Oct 21 Javascript
jQuery数据类型小结(14个)
Jan 08 Javascript
Javascript实现汉字和拼音互转的终极方案
Oct 19 Javascript
ionic中列表项增加和删除的实现方法
Jan 22 Javascript
jQuery实现jQuery-form.js实现异步上传文件
Apr 28 jQuery
Vue报错:Uncaught TypeError: Cannot assign to read only property’exports‘ of object’#‘的解决方法
Jun 17 Javascript
微信小程序使用slider设置数据值及switch开关组件功能【附源码下载】
Dec 09 Javascript
用Axios Element实现全局的请求loading的方法
Mar 15 Javascript
JS实现图片上传多次上传同一张不生效的处理方法
Aug 06 Javascript
搭建vscode+vue环境的详细教程
Aug 31 Javascript
Vertx基于EventBus发送接受自定义对象
Nov 16 Javascript
通过JavaScript下载文件到本地的方法(单文件)
Mar 17 #Javascript
微信小程序登录session的使用
Mar 17 #Javascript
Javascript读写cookie的实例源码
Mar 16 #Javascript
vue自定义键盘信息、监听数据变化的方法示例【基于vm.$watch】
Mar 16 #Javascript
vue自定义指令用法经典实例小结
Mar 16 #Javascript
简单易扩展可控性强的Jquery转盘抽奖程序
Mar 16 #jQuery
基于vue通用表单解决方案的思考与分析
Mar 16 #Javascript
You might like
防止MySQL注入或HTML表单滥用的PHP程序
2009/01/21 PHP
PHP 面向对象 final类与final方法
2010/05/05 PHP
php笔记之:数据类型与常量的使用分析
2013/05/14 PHP
新手菜鸟必读:session与cookie的区别
2013/08/22 PHP
php实现的获取网站备案信息查询代码(360)
2013/09/23 PHP
py文件转exe时包含paramiko模块出错解决方法
2016/08/12 PHP
php+redis消息队列实现抢购功能
2018/02/08 PHP
Extjs ajax同步请求时post方式参数发送方式
2009/08/05 Javascript
Domino中运用jQuery读取视图内容的方法
2009/10/21 Javascript
Extjs 几个方法的讨论
2010/01/28 Javascript
JavaScript开发规范要求(规范化代码)
2010/08/16 Javascript
JavaScript入门之对象与JSON详解
2011/10/21 Javascript
用C/C++来实现 Node.js 的模块(二)
2014/09/24 Javascript
jquery.cookie.js使用指南
2015/01/05 Javascript
JavaScript比较两个对象是否相等的方法
2015/02/06 Javascript
AngularJS实现Model缓存的方式
2016/02/03 Javascript
浅谈js的url解析函数封装
2016/06/28 Javascript
JavaScript里 ==与===区别详解
2016/08/16 Javascript
jQuery弹出窗口打开链接的实现代码
2016/12/24 Javascript
canvas学习之API整理笔记(二)
2016/12/29 Javascript
基于JavaScript实现带缩略图的轮播效果
2017/01/12 Javascript
JS中call和apply函数用法实例分析
2018/06/20 Javascript
对python cv2批量灰度图片并保存的实例讲解
2018/11/09 Python
python实现控制台打印的方法
2019/01/12 Python
教你一步步利用python实现贪吃蛇游戏
2019/06/27 Python
使用Filter过滤python中的日志输出的实现方法
2019/07/17 Python
python 实现识别图片上的数字
2019/07/30 Python
Python中的整除和取模实例
2020/06/03 Python
python 中 .py文件 转 .pyd文件的操作
2021/03/04 Python
美国马匹用品和骑马配件购物网站:Horse.com
2018/01/08 全球购物
德国香水、化妆品和护理产品网上商店:Parfumdreams
2018/09/26 全球购物
三年级语文教学反思
2014/02/01 职场文书
美术教学感言
2014/02/22 职场文书
村党总支部公开承诺书2016
2016/03/25 职场文书
2016年清明节网上祭英烈活动总结
2016/04/01 职场文书
给numpy.array增加维度的超简单方法
2021/06/02 Python