this、call()、apply()、bind()

this 关键字

JavaScript 中 this 不是固定不变的,它会随着执行环境的改变而改变。

全局环境

无论是否在严格模式下,在全局执行环境中(在任何函数体外部)this 都指向全局对象。

// 浏览器中,window对象同时也是全局对象

console.log(this === window) // true

函数(运行内)环境

在函数内部,this 的值取决于函数被调用的方式。

非严格模式

function f1() {

    return this;

}

// 在浏览器中

f1() === window; // true

严格模式

function f2(){

    "use strict";

    return this;

}

f2() === undefined; // true

如果想要把 this 的值从一个环境传到另一个环境,就要用 call 或者 apply 方法。

call、apply方法

// 将一个对象作为 call 和 apply 的第一个参数,this 会被绑定到这个对象

let obj = { a: 'Custom' };

let a = 'Global';

function whatsThis( arg ) {

    return this.a; // this 的值取决于函数的调用方式

}

whatsThis(); // 'Global'

whatsThis.call(obj); // 'Custom'

whatsThis.apply(obj); // 'Custom'

当一个函数在其主体中使用 this 关键字时,可以通过使用函数继承自 Function.prototype 的 call 或 apply 方法将 this 值绑定到调用的特定对象。

function add( c,d ){

    return this.a + this.b + c + d;

}

let o = { a: 1, b: 3 };

// 第一个参数是作为‘this’使用的对象

 // 后续参数作为参数传递给函数调用 

add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16


 // 第一个参数也是作为‘this’使用的对象 

// 第二个参数是一个数组,数组里的元素用作函数调用中的参数 

add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34     

使用 call 和 apply 函数的时候要注意,如果传递给 this 的值不是一个对象,JavaScript 会尝试使用内部 ToObject 操作将其转化为对象。因此,如果传递的值是一个原始值比如 7 或 ‘foo’,那么会使用相关构造函数将它转换为对象,所以原始值 7 会被转换为对象,像 new Number(7),而字符串 ‘foo’ 转化为 new String( 'foo' )。

bind方法

ES5 引入了 Function.prototype.bind。调用 f.bind(obj) 会创建一个与 f 具有相同函数体和作用域的函数,但是在这个新函数中,this 将永久被绑定到 bind 的第一个参数,无论这个函数是如何被调用的。

function f() {

    return this.a;

}


let g = f.bind( { a:"azerty" } );

console.log( g() ); // azerty


let h = g.bind( { a:'yoo' } ); // bind只生效一次! 

console.log( h() ); // azerty 


let o = { a: 37, f: f, g: g, h: h };

console.log( o.f(), o.g(), o.h() ); // 37, azerty, azerty

各种情况下this 的指向问题:

箭头函数

在箭头函数中,this 与封闭词法环境的 this 保持一致。在全局代码中,它将被设置为全局对象。无论如何,函数的 this 被设置为他被创建时的环境。这同样适用于在其他函数内创建的箭头函数:这些箭头函数的 this 被设置为封闭的词法环境。

注意:箭头函数中,如果将 this 传递给 call、bind、apply,它将被忽略。

作为对象的方法

当函数作为对象里的方法被调用时,它们的 this 是调用该函数的对象。

注意:这样定义的函数不受函数定义方式或位置的影响。同样,this 的绑定只受最靠近的成员引用的影响。

原型链中的 this

如果该方法存在于一个对象的原型链上,那么 this 指向的是调用这个方法的对象,就像该方法在对象上一样。

getter 与 setter 中的 this

用作 getter 或 setter 的函数都会把 this 绑定到设置或获取属性的对象。

作为构造函数

当一个函数用作构造函数时(使用 new 关键字),它的 this 被绑定到正在构造的新对象。

作为一个DOM事件处理函数

当函数被用作事件处理函数时,它的 this 指向触发事件的元素(一些浏览器在使用非 addEventListener 的函数动态添加监听函数时不遵守这个约定)。

作为一个内联事件处理函数

当代码被内联 on-event 处理函数调用时,它的 this 指向监听器所在的 DOM 元素。

你可能感兴趣的:(this、call()、apply()、bind())