Skip to content

JS里的this

1. 全局上下文

处于window上下文或者不在任何function中时,this指向window,不管当前是否处于use strict状态。

2. 函数调用中的this

在一个function中调用this时,要看function如何被调用。

2.1 非严格模式

直接调用方法时,this指向window:

js
function f1() {
    return this;
}
console.log(f1() === window); // true

let f2 = () => {
    return this;
}
console.log(f2() === window); // true

2.2 严格模式

严格模式下,若没有在调用时显式指定this,则this为undefined:

js
function f3() {
    'use strict';
    return this;
}
console.log(f3()); // undefined

然而,在使用箭头函数时,隐式的指定调用为this,即window:

js
let f4 = () => {
    'use strict';
    return this;
}
console.log(f4() === window); // true

3. 显式指定this

调用时需要指定this时,使用call或者apply(仅在函数是function直接定义时使用,箭头函数无此效果):

js
let custom = { desc: 'custom' }
let desc = 'window'

function normalWhatsThis() {
    return this.desc;
}

let arrowWhatsThis = () => {
    return this.desc;
}

normalWhatsThis(); // undefined
normalWhatsThis.call(custom); // "custom"
normalWhatsThis.apply(custom); // "custom"

// 箭头函数没有这个效果
arrowWhatsThis(); // undefined
arrowWhatsThis.call(custom); // undefined
arrowWhatsThis.apply(custom); // undefined

4. 使用bind绑定this

在调用函数时,使用bind可以绑定this:

js
let foo = {
    desc: 'foo'
}

let bar = {
    desc: 'bar',
    printMe: function() {
        console.log(this.desc);
    }
}

bar.printMe(); // bar
let printFoo = bar.printMe.bind(foo);
printFoo(); // foo

5. 箭头函数中的this

箭头函数调用中,this指向当前未关闭的语法上下文的this(enclosing lexical context's this):

js
let global = this;
let test = (() => this);
console.log(test() === this); // true

注意:使用call、bind或者apply调用箭头函数时,第一个入参会被忽略:

js
let custom2 = {
    desc2: 'custom'
}
let desc2 = 'window'

function arrowWhatsThis() {
    return console.log(this.desc2);
}

arrowWhatsThis(); // undefined
arrowWhatsThis.call(custom); // undefined

6. 对象方法中的this

如果函数本身作为对象(object)的成员,则函数中的this指向方法被调用的对象:

js
console.log('--------1-------');
let obj1 = {
    a: 3,
    fn: function() {
        console.log(this.a);
        console.log(this === obj1);
    }
}
obj1.fn();

console.log('--------------2-------');
let indiFn1 = function() {
    console.log(this.a);
    console.log(this === obj2);
}

let obj2 = {
    a: 4,
    fn: indiFn1
}

let obj4 = {
    a: 5,
    fn: {}
}

obj2.fn();
obj4.fn = indiFn1;
obj4.fn();

console.log('-----------3---------------');
let indiFn2 = () => {
    console.log(this.a);
    console.log(this === obj2);
}

let obj3 = {
    a: 5,
    fn: indiFn2
}

obj3.fn();

输出:

--------1-------
3
true
--------------2-------
4
true
5
false
-----------3---------------
undefined
false

7. 对象原型链中的this

js
let o = {
    f: function() {
        return this.a + this.b;
    }
}
let p = Object.create(o);
p.a = 3;
p.b = 4;
console.log(p.f()); // 7

注意:getter和setter的道理一致。

8. 构造器中的this

当一个方法被用作构造器,即方法是通过new关键词调用时,this被绑定为构造的新对象:

js
function fn() {
    this.c = 99
}
let obj = new fn();
console.log(obj.c); // 99

9. DOM事件处理函数中的this

DOM事件的handler为function,则其中的this指向抛出事件的对象,即e.currentTarget:

html
<button id='btn' onclick="alert(this.tagName)">ClickMe</button>
// 输出: BUTTON

总结

场景this指向
全局上下文window
非严格模式直接调用函数window
严格模式直接调用函数undefined
箭头函数定义时的上下文
对象方法调用调用该方法的对象
call/apply/bind指定的对象
构造函数新创建的对象
DOM事件处理函数触发事件的元素

引用

Last updated:

评论