在理解this的绑定过程之前,我们先来理解调用位置(不是声明位置) ,最重要的是要分析调用栈(就是为了到达当前执行位置所调用的所有函数)。
我们关心的调用位置就在当前正在执行的函数的前一个调用中,例:
好了,调用位置我们已经找到了,然后我们来看看this绑定的四大规则
第一个规则:默认绑定(独立函数调用),可以把这条规则看做是无法应用其他规则时的默认规则,看代码
代码中foo()是直接使用不带有任何修饰的函数引用进行调用的,因此只能使用默认绑定,无法应用其他规则。如果使用严格模式(strict mode),
则不能将全局对象用于默认绑定,因此this会绑定到undefined。
第二个规则:隐式绑定
看代码
当函数引用有上下文对象时,隐式绑定规则会把函数调用的this绑定到这个上下文对象,因为调用foo时
this被绑定到obj,因此this.a和obj.a是一样的。对象属性引用链中只有上一层或者说最后一层在调用位置起作用
如:
隐式丢失:看代码
虽然bar是obj.foo的一个引用,但是实际上,它引用的是foo函数本身,因此此时的bar()其实是一个不带任何修饰的函数调用,因此应用了默认绑定。
参数传递其实就是一种隐式赋值,所以结果和上面结果一样
如果把函数传入语言内置的函数而不是传入你声明的函数,结果是一样的,没有区别
第三个规则:显示绑定
说到这里就不得不说call和apply函数了,那么他们是如何工作的呢?
他们的第一个参数是一个对象,是给this准备的,接着在调用函数时将其绑定到this。因为你可以直接指定this的绑定对象,因此称之为显示绑定
看代码:
如果你传入了一个原始值(字符串类型、布尔类型或者数字类型)来当做this的绑定对象,这个原始值会被转换成他的
对象形式(也就是new String(...)、new Boolean(...)或者new Number(...))。这通常被称为装箱。
硬绑定:方法1
方法2
由于硬绑定是一种非常常用的模式,所以es5提供了内置的方法function.prototype.bind,用法如下
规则四:new绑定
使用 new来调用函数,会自动执行以下操作:
1、创建一个全新的对象
2、这个新对象会被执行[[prototype]]连接
3、这个新对象会绑定到函数调用的this
4、如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象
看以下代码,new this绑定