You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
this 关键字在 Javascript 中非常常见,但是很多开发者很难说清它到底指向什么。大部分人会从字面意思上去理解 this,认为 this 指向函数自身,实际上this 是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调
用时的各种条件。this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。
总结: 函数被调用时发生 this 绑定,this 指向什么完全取决于函数在哪里被调用。
一、this 的绑定规则
this 一共有 4 中绑定规则,接下来一一介绍每种规则的解释和规则直接的优先级
默认绑定(严格/非严格模式)
隐式绑定
显式绑定
new 绑定
1.1 默认绑定(严格/非严格模式)
独立函数调用: 独立函数调用时 this 使用默认绑定规则,默认绑定规则下 this 指向 window(全局对象)。
这两种方法都需要传入一个参数当作 this 的绑定对象。如果函数并不关心 this 的话,你仍然需要传入一个占位值,这时 null 可能是一个不错的选择(更安全的做法就是传入一个特殊的对象(空对象),把 this 绑定到这个对象不会对你的程序产生任何副作用。JS 中创建一个空对象最简单的方法是**Object.create(null)**,这个和{}很像,但是并不会创建 Object.prototype 这个委托,所以比{}更空。)
前言
this 关键字在 Javascript 中非常常见,但是很多开发者很难说清它到底指向什么。大部分人会从字面意思上去理解 this,认为 this 指向函数自身,实际上this 是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调
用时的各种条件。this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。
总结: 函数被调用时发生 this 绑定,this 指向什么完全取决于函数在哪里被调用。
一、this 的绑定规则
this 一共有 4 中绑定规则,接下来一一介绍每种规则的解释和规则直接的优先级
1.1 默认绑定(严格/非严格模式)
独立函数调用
严格模式下:
注意下边两种情况
函数 sayName 虽然是在 obj.fn 内部定义的,但是它仍然是一个独立函数调用,this 仍然指向 window。
虽然 bar 是 obj.foo 的一个引用,但是实际上,它引用的是函数本身,因此此时的
bar() 其实是一个不带任何修饰的独立函数调用,因此应用了默认绑定。
1.2 隐式绑定
当函数引用有上下文对象时(例如:obj.foo 这个时候使用 obj 上下文来引用函数 foo),隐式绑定规则会把函数中的 this 绑定到这个上下文对象。
对象属性引用链中只有上一层或者说最后一层在调用中起作用。
隐式丢失
被隐式绑定的函数会丢失绑定对象,而应用默认绑定,把 this 绑定到全局对象或者 undefined(严格模式) 上。
第一种
虽然 bar 是 obj.foo 的一个引用,但是实际上,它引用的是函数本身,因此此时的
bar() 其实是一个不带任何修饰的独立函数调用,因此应用了默认绑定。
第二种传入回调函数时:
1.3 显示绑定
通过 call() 或者 apply()方法。第一个参数是一个对象,在调用函数时将这个对象绑定到 this 上,称之为显示绑定。
显示绑定引申出来一个硬绑定,代码如下
bar 函数无论如何调用,它总会手动在 obj 上调用 fn,强制把 fn 的 this 绑定到了 obj。这样也解决前面提到的丢失绑定问题
由于硬绑定是一种非常常用的模式,所以在 ES5 中提供了内置的方法
Function.prototype.bind
1.4 new 绑定
使用 new 来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。
例如:
如下图是 new foo() 这个对象
二、四种绑定关系的优先级
判断 this,可以按照下面的顺序来进行判断:
指定的对象。
下文对象。
全局对象。
三、被忽略的 this
把 null 或者 undefined 作为 this 的绑定对象传入 call、apply 或者 bind,这些值在调用时会被忽略,实际应用的是默认规则。(this 指向 window)
例如:
下面两种情况下会传入 null
使用 apply(..)来“展开”一个数组,并当作参数传入一个函数
bind(..)可以对参数进行柯里化(预先设置一些参数)
这两种方法都需要传入一个参数当作 this 的绑定对象。如果函数并不关心 this 的话,你仍然需要传入一个占位值,这时 null 可能是一个不错的选择(更安全的做法就是传入一个特殊的对象(空对象),把 this 绑定到这个对象不会对你的程序产生任何副作用。JS 中创建一个空对象最简单的方法是
**Object.create(null)**
,这个和{}
很像,但是并不会创建 Object.prototype 这个委托,所以比{}更空。)四、箭头函数
以上四条规则已经可以包含所有正常的函数。但是 ES6 中介绍了一种无法使用这些规则的特殊函数类型:箭头函数。
箭头函数不使用this 的四种标准规则,而是根据外层(函数或者全局)作用域来决定 this。
看一下下边这个例子:
foo() 内部创建的箭头函数会捕获调用时 foo() 的 this。由于 foo() 的 this 绑定到 obj1,bar(引用箭头函数)的 this 也会绑定到 obj1,箭头函数的绑定无法被修改。
箭头函数最常用于回调函数中,例如事件处理器或者定时器:
在 ES6 之前我们就已经在使用一种几乎和箭头函数完全一样的模式。
五、接下里思考下边几道题加深对 this 的认识(答案在最下边)
答案:
答案:
答案:
The text was updated successfully, but these errors were encountered: