this的五种绑定问题
1,默认绑定
默认绑定通常是指函数独立调用,不涉及其他绑定规则。
- 非严格模式下,this指向window
- 严格模式,下,this指向undefined. 在普通函数内部的this
- let/const定义的变量存在暂时性死区,而目不会挂载到window对象上,因此print中是无法获取到a和b的。
- 自执行函数只要执行到就会运行,并且只会运行一次,this指向window.
- 如果函数是独立运行的,函数中的this依然是指向window对象。
- 匿名函数为默认绑定
2,隐式绑定
-
函数的调用是在某个对象上触发的,即调用位置存在上下文对象,通俗点说就是 XXX.func() 这种调用模式。此时func的this指向XXX。
-
但如果存在链式调用,例如XXX.YYY.ZZZ.func,记住一个原则: this永远指向最后调用它的那个对象。
-
隐式绑定可是个调皮的东西,一不小心它就会发生绑定的丢失。一般会有两种常见的丢失
-
使用另一个变量作为函数别名,之后使用别名执行函数
var foo = obi.foo:
上面将obi.foo赋值给foo,就是将foo也指向了obi.foo所指向的堆内存,此后再执行foo,相当于直接执行的堆内存的函数,与obi无关,foo为默认绑定。笼统的记,只要fn前面什么都没有,肯定不是隐式绑定。var obj2 ={a: 3,foo: obj.foo}
obj2.foo指向了obi.foo的堆内存,此后执行与obj无关(除非使用call/apply改变this指向) -
将函数作为参数传递时会被隐式赋值
doFoo(obj.foo)
obi.foo作为实参,在预编译时将其值赋值给形参fn,是将obj.foo指向的地址赋给了fn,此后fn执行不会与obj产生任何关系。fn为默认绑定。
只要涉及形参了,就只是传递了一个地址,和原来的没有关系了 -
隐式绑定丢失之后,this的指向会启用默认绑定,
3,显式(硬)绑定
- 显式绑定比较好理解,就是通过call()、apply()、bind()等方法,强行改变this指向
- call和apply函数会立即执行
- bind函数会返回新函数,不会立即执行函数
- call和apply的区别在于call接受若干个参数,apply接受数组
4,new绑定
- 创建一个空的简单JavaScript对象 (即{}) :
- 为步骤1新创建的对象添加属性proto,将该属性链接至构造函数的原型对象
- 将步骤1新创建的对象作为this的上下文: 如果该函数没有返回对象,则返口this.
- 通过new来调用构造函数,会生成一个新对象,并日把这个新对象绑定为调用函数的this
5, ES6新增箭头函数绑定
- 箭头函数没有自己的this,它的this指向外层作用域的this,
- 且指向函数定义时的this而非执行时this指向外层作用域的this
- 箭头函数没有this绑定,但它可以通过作用域链查到外层作用域的this指向函数定义时的this而非执行时
- JavaScript是静态作用域,就是函数定义之后,作用域就定死了跟它执行时的地方无关。更详细的个绍见JavaScript之静态作用域与动态作用域