首先,this和所谓的是指向谁或者指向哪个词法作用域没有关系,this实际上是函数调用的时候发生绑定的,他代表什么只取决于函数的调用方式(在那里被调用)
-
this的绑定规则
- 默认绑定:其实就是无法应用其他规则时的默认规则
function foo(){ console.log(this.a) } var a = 2 foo() //输出2
- 隐式绑定:看调用位置是否有上下文对象(是否被某个对象拥有或包含)
function foo(){ console.log(this.a) } var obj = { a:2, foo:foo } var obj1 = { a:5, obj:obj } obj.foo() //输出2 obj1.obj.foo() //还是输出2,对象属性引用链中只有最后一层在调用位置起作用
-
隐式丢失:
最常见的就是函数当参数传递时(回调函数一样会导致形式参数的隐式赋值),丢失绑定对象,然后应用默认绑定function foo(){ console.log(this.a) } var obj = { a:2, foo:foo } var a = "global" var bar = obj.foo bar() //输出global
function foo(){ console.log(this.a) } function dofoo(fn){ fn() } var obj = { a:2, foo:foo } var a = "global" dofoo(obj.foo) // 输出global
- 显式绑定:简单来说就是使用call或者apply函数来手动绑定this
function foo(){ console.log(this.a) } var obj = { a:2, } foo.call(obj)// 输出2
-
硬绑定:其实就是创建一个函数,在其内部调用apply或者call,强制确认绑定关系,因为硬绑定不能再次修改他的this(JS内置的bind函数就是这个原理)
以下是个简单的例子function bind(fn,obj){ return function(){ return fn.apply(obj,arguments) } } // 一个典型的硬绑定辅助函数
-
new绑定:这个几乎不会用到(一般不会需要new关键字来修改this),但是最好知道new的时候干了哪些事情
- 第一步:创建一个全新的对象
- 第二步:这个新对象执行[[prototype]]连接
- 第三步:这个新对象绑定到函数调用的this
- 第四步:如果函数没有返回其他对象,则new表达式中的函数调用会自动返回这个对象
优先级 new > 显式绑定 > 隐式绑定 > 默认绑定