函数中的 this 是 JavaScript 中的难点之一。根据 this 的英文词义,有些人将 this 误解为指向自身,但事实显然不会这么简单。根据 this 的特性,到 ES6 , this 总的来说有五种绑定情况。下面我将这些情况 一 一 列举出来:
1.默认绑定
默认绑定时, this 绑定全局对象。如果函数调用时没有任何修饰符,就会应用 this 的默认绑定。这种情况很容易分辨,具体看下方代码:
function func() { console.log(this.c); } var c = 3; func() //3
代码中函数 func 的调用就是没有任何修饰符的调用,这是 this 绑定全局对象,c 声明于全局作用域,是全局对象的属性。所以 c 可以通过 this.c 访问,结果为 3 。
此外,还应该注意严格模式与非严格模式的区别。如果函数声明于严格模式中,无论函数在何处执行,this 都不会绑定到全局对象。此时通过 this 访问全局属性只会得到 undefined ,就像下方代码。
"use strict" function func() { console.log(this.c); } var c = 3; func() //undefined
2. 隐式绑定
隐式绑定时,this 绑定上下文对象。什么是上下文对象?举个简单的例子:
var obj = {num:2, func:con } function con() { console.log(this.num); } obj.func() // 2
在上方代码中,一个对象内部包含一个函数,通过对象引用属性而间接地引用了 con 函数。 obj 就是 con 的上下文对象,this 隐式绑定到 obj ,所以 this.num 等于 2。
如果只是用 1 中的方式调用函数,结果就变成了 undefined。
func() //结果为 undefined
3. 显式绑定
显式绑定时,this 绑定到特定函数指定的对象。有三个函数可以指定 this 绑定的对象,分别为 apply、call、bind。JavaScript 中绝大部分函数都可以调用这三个方法,方式也很简单:
var obj = {a:1}; function func(c,b) { console.log(this.a+c) } func.apply(obj,[1,2]) func.call(obj,[1,2]); func.bind(obj,[1,2]);
三种方法的第一个参数都为 this 要绑定的对象,第二个参数都为要传入的参数列表。apply 与 call 的区别为 ,call 函数可以传入多个参数列表。bind 函数与另外两种方法的区别为,函数调用 apply 或 call 后会立即执行。
4. new 绑定
new 绑定时,this 绑定 new 构造的新对象。代码如下:
function func(num) { this.num = num; } var obj = new func(3); console.log(obj.num); // 3
obj 为 new 构造的新对象,所以 this.num 即为 obj.num。
5.箭头函数中 this 的绑定
箭头函数中,this 继承外层作用域的 this 绑定。如果外层作用域 this 绑定一个对象,箭头函数也绑定这个对象,就像下方代码中所展示的:
var obj = { nun:1, func:function(){ var boo = () =>{ console.log(this.nun); } boo(); } } obj.func();//1
函数执行时,obj 是 func 的上下文对象,所以 func 函数中的 this 绑定 obj 对象。由于 func 函数是箭头函数的外层作用域,所以箭头函数的 this 也绑定 obj 对象。因此 this.nun = 1 ,函数执行结果为 1。
以上就是 JavaScript 中 this 五种绑定的完整总结。当然,实际代码中的 this 有各种各样让人迷惑的地方。
|