掌握Js中简单的'this'规则[翻译集]

223 阅读3分钟
弄清几个简单的规则就能掌握函数中的this指向问题~\(≧▽≦)/~啦啦啦。


要知道this指向谁其实很简单,定位this的首要规则就是判断一个函数被首次调用的环境。通常遵循以下这几个规则,有优先级关系。

规则

1. 当调用函数的时候用到了 new 关键词, 那么在函数中this 指向的是一个全新的对象。

function ConstructorExample() {
    console.log(this);
    this.value = 10;
    console.log(this);
}

new ConstructorExample();// -> {}
// -> { value: 10 }


2. 调用函数的时候如果用到了apply, call 或者 bind,那么函数中this的指向就是给之前所说的方法传递的参数。

function fn() {
    console.log(this);
}

const obj = {
    value: 5
}

const boundFn = fn.bind(obj);
boundFn();    // -> { value: 5 }
fn.call(obj); // -> { value: 5 }fn.apply(obj); // -> { value: 5 }

3.  如果一个函数是通过.符号调用的话,this 指向的是包含这个函数属性的对象。换句话说就是当.在一个函数的左边,this指向的就是.左边的那个对象。

const obj = {
    value: 5,
    printThis: function() {
        console.log(this);
    }
}

obj.printThis();     // -> { value: 5, printThis: f }


4. 如果一个函数被调用的时候没有任何条件,那么this指向的是全局对象,在浏览器中this 指向的就是window。

function fn() {
    console.log(this);
}

// if called in browser
fn();    // -> Window {....}

*注意,这个规则其实和规则3很相像,不同之处在于一个函数如果不是通过对象方法申明的时候,那么它自动就变成全局对象的一个属性。因此这种方法是一种隐式的方法调用。当我们调用fn()的时候,它自动被解释成window.fn(), 这里this 指向的就是window。

console.log(fn === window.fn );    // -> true

5. 如果以上的5种规则出现了几种,优先级别高的会先应用。

6.如果是es6的箭头函数,那么以上的规则都不适用了。箭头函数的this是根据创建时的上下文环境决定的。要找到this,将目光由箭头函数上移一行,找this在这里指向的是什么,在箭头函数外就可以使用上面的规则拉。找到的this指向就代表箭头函数的this 指向。

const obj = {
    value: 'abc',
    createArrowFn: function() {
        return () => console.log(this);
    }
}

const arrowFn = obj.createArrowFn();
arrowFn();    // { value: 'abc', createArrowFn: f }

解释: 看到obj.createArrowFn()的时候,我们就要想到第三条规则,this 指向的是.左边的那个对象即obj,因此arrowFn函数中的this指向的就是obj。如果我们在全局环境中建立箭头函数,那么箭头函数中this指向的就是window。


练习一下

找出以下代码中哪个规则适用

var obj = {
    value: 'hi',
    printThis: function() {
        console.log(this);
    }
}

var print = obj.printThis;

obj.printThis();    // { value: 'hi', printThis: f}
print();     // Window {...}

obj.printThis() 应用的就是第三个规则,运用点操作符。而print()应用的是第四条规则。


当有多个规则时

var obj1 = {
    value: 'hi',
    print: function() {
        console.log(this)
    }
}
var obj2 = { value: 17 }


当第二条和第三条规则同时存在时,优先应用第二条规则

obj1.print().call(obj2);    // { value: 17 }

当第一条和第三条同时存在,优先应用第一条规则

new obj1.print();    // {}


翻译自https://codeburst.io/the-simple-rules-to-this-in-javascript-35d97f31bde3