JavaScript 中this在差别挪用形式中的差别

挪用一个函数会停息当前函数的实行,通报控制权和参数给新函数。除了声明时定义的情势参数,每一个函数还吸收两个附加参数: this 和 arguments。参数 this 的值取决于挪用的情势。在JavaScript中一共有4中挪用情势: 要领挪用情势、函数挪用情势、组织器挪用情势和 apply 挪用情势。

要领挪用情势(隐式绑定)

当一个函数被保存为对象的一个属性时,我们称它为一个要领。当一个要领被挪用时,this 被绑定到该对象。假如挪用表达式包含一个提取属性的行动(即包含一个 .点表达式或[subscript]下标表达式),那末它就是被当作一个要领来挪用。

// 建立 myObject 对象,有一个 value 属性和一个 increment 要领
// increment 要领吸收一个可选的参数。假如参数不是数字,那末默许运用数字1

var myObject = {
    value: 0,
    increment: function (inc){
        this.value += typeof inc === 'number' ? inc : 1;
    }
};

myObject.increment();
document.writeln(myObject.value);   // 1

myObject.increment(2);
document.writeln(myObject.value);   // 3

要领能够运用 this 接见本身所属的对象,所以它能从对象中取值货对对象举行修正。 this 到对象的绑定发生在挪用的时刻。

函数挪用情势(默许绑定)

当一个函数并不是一个对象的属性时,它就是被当作一个函数来挪用的。

var sum = add(3,4);   // sum 的值为7

以此情势挪用函数时,this 被绑定到全局对象。这是言语设想上的一个毛病。若准确,那末当内部函数被挪用时,this 应当依然绑定到外部函数的 this 变量。如许设想的效果就是要领不能应用内部函数来协助它事情,由于内部函数的 this 被绑定了毛病的值,不能同享该要领对对象的接见权。

解决方案: 假如该要领定义一个便令并给它赋值为 this,那末内部函数就能够经由过程谁人变量接见到 this。根据商定,把谁人变量命名为 that:

// 给 myObject 增添一个 double 要领

myObject.double = function () {
    var that = this;   // 解决要领
    
    var helper = function () {
        that.value = add(that.value, that.value);
    };
    
    helper();   // 以函数的情势挪用helper
};

// 以要领的情势挪用 double

myObject.double();
document.writeln(myObject.value);   // 6

假如运用严厉情势(strict mode),那末全局对象没法运用默许绑定,this 会绑定到undefined

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

var a = 2;

foo();   // TypeError: this is undefined

这里有一个玄妙然则异常中亚偶的细节,虽然 this 的绑定划定规矩完整取决于挪用位置,然则只要 foo() 运行在非 strict mode 下时,默许绑定才绑定到全局对象;严厉情势下与 foo() 的挪用位置无关:

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

var a = 2;

(function(){
    "use strict";
    
    foo();   // 2
})();

组织器挪用情势

假如在一个函数前面带上 new 来挪用,那末背地里将会建立一个衔接到该函数的 prototype 成员的新对象,同时 this 会被绑定到谁人新对象上。

起首,我们来相识一下组织函数。在传统的面向类的言语中,“组织函数”是类中的一些特别要领,运用 new 初始化类时会挪用类中的组织函数。一般的情势为:

something = new MyClass(..);

JavaScript也有一个 new 操纵符,运用要领看起来和那些面向类的言语一样,但 JavaScript 中的 new 机制实际上和面向类言语完整差别。
在 JavaScript 中,组织函数只是一些运用 new 操纵符时被挪用的函数。它们不属于某个类,也不会实例化一个类。实际上,它们以至都不能说是一种特别的函数范例,它们只是被 new 操纵符挪用的一般函数罢了。包含内置对象函数在内的一切函数都能够用 new 来挪用,这类函数挪用被称为组织函数挪用。实际上并不存在所谓的组织函数,只要关于函数的组织挪用。
运用 new 来挪用函数,会自动实行以下操纵:

  1. 建立(或者说组织)一个全新的对象。

  2. 这个新对象会被实行[[原型]]衔接

  3. 这个新对象会绑定到函数挪用的 this

  4. 假如函数没有返回其他对象,那末 new 表达式中的函数会自动返回这个新对象

// 建立一个名为 Quo 组织器函数。它组织一个带有 status 属性的对象

var Quo = function (string) {
    this.status = string;
};

// 给 Quo 的一切实例供应一个名为 get_status 的大众要领

Quo.prototype.get_status = function () {
    return this.status;
};

// 组织一个 Quo 实例

var myQuo = new Quo("confused");
document.writeln(myQuo.get_status());   // confused

Apply 挪用情势

apply 要领让我们构建一个参数数组通报给挪用函数,也许可我们挑选 this 的值。apply 要领吸收两个参数,第一个是要绑定给 this 的值,第二个就是一个参数数组。

// 组织一个包含两个数字的数组,并将它们相加

var array = [3,4];
var sum = add.apply(null,array);   // 7

// 组织一个包含 status 成员的对象

var statusObject = {
    status: 'A-OK';
};

// statusObject 并没有继续自 Quo.prototype,但我们能够在 statusObject 上挪用 get_statuse 要领,只管statusObject 并没有一个名为 get_status 的要领

var status = Quo.prototype.get_status.apply(statusObject);   // A-OK
    原文作者:puhongru
    原文地址: https://segmentfault.com/a/1190000006806076
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞