资讯专栏INFORMATION COLUMN

this绑定方式和优先级比较

weknow619 / 2152人阅读

摘要:但在严格模式下默认绑定不起作用显式绑定显式绑定用到了和方法,因为可以直接指定的绑定对象,因此称之为显式绑定。隐式绑定显式绑定当我们使用显式绑定时,输出的值为的值所以显式绑定的优先级更高。

上篇文章介绍了this的隐式绑定(implicit binding),接着介绍this其他三种绑定方式

默认绑定 (Default Binding)

显式绑定 (Explicit Binding)

new绑定(new Binding)

默认绑定 (Default Binding)

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

function foo() {
    console.log( this.a );
}

var a = 2;

foo(); // 2

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

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

function foo() {
    "use strict";

    console.log( this.a );
}

var a = 2;

foo(); // TypeError: `this` is `undefined`
显式绑定 (Explicit Binding)

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

function foo() {
    console.log( this.a );
}

var obj = {
    a: 2
};

foo.call( obj ); // 2

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

硬绑定(Hard Binding)

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

function foo() {
    console.log( this.a );
}

var obj = {
    a: 2
};

var bar = function() {
    foo.call( obj );
};

bar(); // 2
setTimeout( bar, 100 ); // 2

// `bar` hard binds `foo`"s `this` to `obj`
// so that it cannot be overriden
bar.call( window ); // 2

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

function foo(something) {
    console.log( this.a, something );
    return this.a + something;
}

var obj = {
    a: 2
};

var bar = function() {
    return foo.apply( obj, arguments );
};

var b = bar( 3 ); // 2 3
console.log( b ); // 5

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

function foo(something) {
    console.log( this.a, something );
    return this.a + something;
}

// simple `bind` helper
function bind(fn, obj) {
    return function() {
        return fn.apply( obj, arguments );
    };
}

var obj = {
    a: 2
};

var bar = bind( foo, obj );

var b = bar( 3 ); // 2 3
console.log( b ); // 5

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

function foo(something) {
    console.log( this.a, something );
    return this.a + something;
}

var obj = {
    a: 2
};

var bar = foo.bind( obj );

var b = bar( 3 ); // 2 3
console.log( b ); // 5
new Binding

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

function foo(n) {
    this.studentNum = n;
    this.name = "cnio"
}
  
var bar =  new foo(1)

console.log(bar) // foo {studentNum: 1, name: "cnio"}

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

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

在控制台打印出的proto中,就有getName属性。
使用new关键字时,会发生如下几个步骤

创建一个全新的对象。

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

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

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

优先级比较

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

隐式绑定 VS 显式绑定
function foo() {
    console.log( this.a );
}

var obj1 = {
    a: 2,
    foo: foo
};

var obj2 = {
    a: 3,
    foo: foo
};

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

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

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

new绑定 VS 隐式绑定
function foo(something) {
    this.a = something;
}

var obj1 = {
    foo: foo
};

var obj2 = {};

obj1.foo( 2 );
console.log( obj1.a ); // 2

obj1.foo.call( obj2, 3 );
console.log( obj2.a ); // 3

var bar = new obj1.foo( 4 );
console.log( obj1.a ); // 2
console.log( bar.a ); // 4

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

function foo(something) {
    this.a = something;
}

var obj1 = {};

var bar = foo.bind( obj1 );
bar( 2 );
console.log( obj1.a ); // 2

var baz = new bar( 3 );
console.log( obj1.a ); // 2
console.log( baz.a ); // 3

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

综上,优先级比较如下

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78766.html

相关文章

  • Javascript基础之-this

    摘要:应该算是前期比较容易混淆的一个关键字了,在这里,我就打算按照我的理解来说一下首先呢,的值是跟运行时被调用的位置相关的,而不是词法作用域。来一个例子在浏览器中执行,会发现,如果作为一个函数单独调用,那么指向的就是全局对象。 this应该算是前期比较容易混淆的一个关键字了,在这里,我就打算按照我的理解来说一下 首先呢,this的值是跟运行时被调用的位置相关的,而不是词法作用域。 也就是说,...

    lcodecorex 评论0 收藏0
  • YouDontKnowJS 小黄书学习小结

    摘要:真正的理解闭包的原理与使用更加透彻绑定的四种规则机制你不知道的人称小黄书,第一次看到这本书名就想到了一句话你懂得,翻阅后感觉到很惊艳,分析的很透彻,学习起来也很快,块级作用域语句语句相当于比较麻烦而且用在对象上创建的块作用域仅仅在声明中有效 真正的理解闭包的原理与使用 更加透彻this绑定的四种规则机制 你不知道的JavaScript 人称小黄书,第一次看到这本书名 就想到了一句话...

    Yuqi 评论0 收藏0
  • 深入理解JavaScript中的this指向

    摘要:和作用域判别失败相关,而代表作用域判别成功,但是对结果的操作是非法的不合理的。在中,构造函数只是使用操作符时被调用的函数,它们并不属于一个类,也不会实例化一个类。也就是说,中,不存在所谓的构造函数,只有对函数的构造调用。 与其他语言相比,js中的this有所不同,也是比较头疼的问题。在参考了一些资料后,今天,就来深入解析一下this指向问题,有不对的地方望大家指出。 为什么要用this...

    不知名网友 评论0 收藏0
  • 十分钟快速了解《你不知道的 JavaScript》(上卷)

    摘要:最近刚刚看完了你不知道的上卷,对有了更进一步的了解。你不知道的上卷由两部分组成,第一部分是作用域和闭包,第二部分是和对象原型。附录词法这一章并没有说明机制,只是介绍了中的箭头函数引入的行为词法。第章混合对象类类理论类的机制类的继承混入。 最近刚刚看完了《你不知道的 JavaScript》上卷,对 JavaScript 有了更进一步的了解。 《你不知道的 JavaScript》上卷由两部...

    赵春朋 评论0 收藏0
  • 深入理解 js this 绑定 ( 无需死记硬背,尾部有总结面试题解析 )

    摘要:那默认绑定到哪呢,一般是上,严格模式下是。这种情况下,函数里的默认绑定为上下文对象,等价于打印故输出。只接受两个参数,且第二个参数必须是数组,这个数组代表原函数的参数列表。即继承原函数的原型将这个新对象绑定到此函数的上。 js 的 this 绑定问题,让多数新手懵逼,部分老手觉得恶心,这是因为this的绑定 ‘难以捉摸’,出错的时候还往往不知道为什么,相当反逻辑。让我们考虑下面代码: ...

    wall2flower 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<