this的总结

默认绑定 (Default Binding)

这个是最简单的绑定,最常用的调用类型:独立函数调用

functionfoo(){console.log(this.a );}vara =2;foo();// 2

首先foo()在全局作用域中被调用,根据调用域(call-site),此时this绑定到了全局,所以结果很明显。

但在严格模式下,默认绑定不起作用

functionfoo(){    "use strict";console.log(this.a );}vara =2;foo();// TypeError: `this` is `undefined`

显式绑定 (Explicit Binding)

显式绑定用到了call()和apply()方法,因为可以直接指定this的绑定对象,因此称之为显式绑定。

functionfoo(){console.log(this.a );}varobj = {a:2};foo.call( obj );// 2

通过foo.call(),我们可以在调用foo时强制把它this绑定到obj上。

硬绑定(Hard Binding)

因为我们强制把foo的this绑定到了obj,无论之后如何调用bar,之后的操作并不会覆盖之前的,它总会在obj上调用foo。

functionfoo(){console.log(this.a );}varobj = {a:2};varbar =function(){    foo.call( obj );};bar();// 2setTimeout( bar,100);// 2// `bar` hard binds `foo`'s `this` to `obj`// so that it cannot be overridenbar.call(window);// 2

硬绑定的应用场景就是创建一个包裹函数,负责接收参数并返回值:

functionfoo(something){console.log(this.a, something );returnthis.a + something;}varobj = {a:2};varbar =function(){returnfoo.apply( obj,arguments);};varb = bar(3);// 2 3console.log( b );// 5

另一种使用方法是创建一个可以重复使用的辅助函数

functionfoo(something){console.log(this.a, something );returnthis.a + something;}// simple `bind` helperfunctionbind(fn, obj){returnfunction(){returnfn.apply( obj,arguments);    };}varobj = {a:2};varbar = bind( foo, obj );varb = bar(3);// 2 3console.log( b );// 5

由于硬绑定是非常常用的,所以ES5提供了内置方法Function.prototype.bind()

functionfoo(something){console.log(this.a, something );returnthis.a + something;}varobj = {a:2};varbar = foo.bind( obj );varb = bar(3);// 2 3console.log( b );// 5

new Binding

使用new来调用foo()时,我们会构造一个新对象并把它绑定到foo()调用中的this上。

functionfoo(n){this.studentNum = n;this.name ='cnio'}varbar =newfoo(1)console.log(bar)// foo {studentNum: 1, name: "cnio"}

如果foo原型链上也有内容,比如添加

foo.prototype.getName =function(){returnthis.name;}

在控制台打印出的proto中,就有getName属性。

使用new关键字时,会发生如下几个步骤

创建一个全新的对象。

这个新对象会被执行[[Prototype]]连接。

这个新对象会绑定到函数调用的this。

如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。

优先级比较

前面已经了解了this绑定的四条规则,但是这几种某次应用了多条该怎么办?所以需要测试一下优先级,也就是谁的权利更大些,就听谁的,否则小弟this将不知所措了。

隐式绑定 VS 显式绑定

functionfoo(){

    console.log( this.a );

}varobj1={

    a: 2,

    foo: foo

};varobj2 ={

    a: 3,

    foo: foo

};obj1.foo();// 2obj2.foo();// 3obj1.foo.call( obj2 );// 3obj2.foo.call( obj1 );// 2

当我们使用call(obj2)显式绑定时,输出的值为obj2的值(a=3),所以显式绑定的优先级更高。

new绑定 VS 隐式绑定

functionfoo(something){this.a = something;}varobj1 = {foo: foo};varobj2 = {};obj1.foo(2);console.log( obj1.a );// 2obj1.foo.call( obj2,3);console.log( obj2.a );// 3varbar =newobj1.foo(4);console.log( obj1.a );// 2console.log( bar.a );// 4

可以看到,new绑定的优先级>隐式绑定

那么new绑定的优先级与显式绑定优先级呢?因为new和apply/call无法一起使用,但硬绑定也是显式绑定的一种,可以替换测试

functionfoo(something){this.a = something;}varobj1 = {};varbar = foo.bind( obj1 );bar(2);console.log( obj1.a );// 2varbaz =newbar(3);console.log( obj1.a );// 2console.log( baz.a );// 3

new修改了硬绑定调用bar()中的this,代码感觉无法修改this绑定,但是又的确修改了this绑定,这个很特殊,理论上我们可以认为new绑定优先级>显式绑定

综上,优先级比较如下

new绑定 > 显式绑定 > 隐式绑定

你可能感兴趣的:(this的总结)