前言
参考学习以下文章
首先this的绑定方式有如下几种
-
默认绑定(非严格模式下this指向全局对象, 严格模式下
this
会绑定到undefined
) -
隐式绑定(当函数引用有上下文对象时, 如
obj.foo()
的调用方式,foo
内的this
指向obj
) -
显示绑定(通过
call()
或者apply()
方法直接指定this
的绑定对象, 如foo.call(obj)
) -
new绑定
-
箭头函数绑定(
this
的指向由外层作用域决定的)
函数中的this指向
立即执行函数,this执行window
1、普通函数
this 永远指向最后调用它的那个对象。
var name = 'window'
function Person (name) {
this.name = name
this.obj = {
name: 'obj',
foo1: function () {
console.log(this.name);
return function () {
console.log(this.name)
}
},
}
}
var person1 = new Person('person1')
var person2 = {name: 'person2'}
person1.obj.foo1() // 最后一个调用的对象时obj,输出obj
person1.obj.foo1()() // obj 、 window ,第一个()函数执行输出obj,return是一个函数,第二个()是立即执行函数,this执行window ,
person1.obj.foo1.call(person2)()
person1.obj.foo1().call(person2)
输出
2、箭头函数
它里面的this
是由外层作用域来决定的,且指向函数定义时的this而非执行时。
var name = 'window'
function Person (name) {
this.name = name
this.obj = {
name: 'obj',
foo2: function () {
console.log(this.name);
return () => {
console.log(this.name)
}
}
}
}
var person1 = new Person('person1')
var person2 = new Person('person2')
person1.obj.foo2()() // 第一个()执行输出obj,最后调用的是obj, 第二个()调用执行箭头函数,其上一层作用域是foo2函数的,this指向obj
person1.obj.foo2.call(person2)()
person1.obj.foo2().call(person2)
输出
解惑
1、 use strict
严格模式下的this指向
不是全部指向undefined,全局的this还是指向window ,在函数内的this 会指向undefined
"use strict";
var a = 10;
function foo () {
console.log('this1', this) // this1 undefined
console.log(window.a) // 10
console.log(this.a) // this 是undefined 所以报错
}
console.log(window.foo) // 打印函数
console.log('this2', this) // this 指向window
foo();
输出结果
2、 var 和let 和const
声明的变量的差异
let 和const 声明的变量 不会绑定到window 对象上,因此 此时this指向window ,而 window上没有该变量,自然就是undefined
let a = 1
const b = 2
function foo () {
console.log(this.a)
console.log(this.b)
}
foo();
console.log(window.a)
执行结果
3、 隐式绑定的隐式丢失问题
下面两种情况会发生丢失
- 1、 使用另一个变量来给函数取别名
function foo () {
console.log(this.a)
};
var obj = { a: 1, foo };
var a = 2;
var foo2 = obj.foo;
obj.foo(); // 1
foo2(); // 2
obj.foo()
this指向最后调用这个函数的对象,所以自然指向obj 输出 1
foo2()
隐式丢失了指向, 最后调用的是window,所以指向window 输出 2
- 2、 将函数作为参数传递时会被隐式赋值,回调函数丢失this绑定
function foo () {
console.log(this.a)
}
function doFoo (fn) {
console.log(this)
fn()
}
var obj = { a: 1, foo }
obj2 = { a: 3, doFoo}
var a = 2
doFoo(obj.foo)
obj2.doFoo(obj.foo)
输出
- 1 、
doFoo(ob.foo()
执行时,doFoo()
this指向window, - 2、
obj.foo()
即doFoo
里面的参数fn()
隐式丢失 ,this指向window
- 3 、
obj2.doFoo(obj.foo)
执行时 ,doFoo()
的this 指向obj2, - 4、里面的参数
fn()
隐式丢失 ,this指向window,所以隐式丢失和外层的this指向没有关系,丢失后fn()
是被window调用的,this指向window。
4、计时器包函数也有隐式丢失问题
var obj1 = {
a: 1
}
var obj2 = {
a: 2,
foo1: function () {
console.log(this.a)
},
foo2: function () {
setTimeout(function () {
console.log(this) // window
console.log(this.a) // 3
}, 0)
}
}
var a = 3
obj2.foo1() // 2
obj2.foo2()