JavaScript 中的 this

Jun 12, 2015


本文为慕课网 JavaScript深入浅出 笔记。

全局的 this

全局 this 一般指向全局对象,浏览器中的全局对象就是 window。

例如:

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

this.a = 91;
console.log(window.a); //91

一般函数的 this

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

可以看到一般函数的 this 也指向 window,在 nodeJS 中为 global object

function f2 () {
    "use strict";//使用严格模式
    return this;
}
console.log(f1() === undefined);//true

严格模式中,函数的 this 为 undefined


作为对象方法的函数的 this

var o = {
    prop: 37,
    f: function() {
        return this.prop;
    }
};
console.log(o.f()); // 37

上述代码通过字面量创建对象 o。

f 为对象 o 的方法。这个方法的 this 指向这个对象,在这里即对象 o。

var o = {
    prop: 37
};

function independent() {
    return this.prop;
}
o.f = independent;
console.log(o.f()); // 37

上面的代码,创建了对象 o,但是没有给对象 o,添加方法。而是通过 o.f = independent 临时添加了方法属性。这样这个方法中的 this 同样也指向这个对象 o。


对象原型链上的 this

var o = {
    f: function() {
        return this.a + this.b;
    }
};
var p = Object.create(o);
p.a = 1;
p.b = 2;
console.log(p.f()); //3

通过 var p = Object.create(o) 创建的对象,p 是基于原型 o 创建出的对象。

p 的原型是 o,调用 f() 的时候是调用了 o 上的方法 f(),这里面的 this 是可以指向当前对象的,即对象 p。


get/set 方法与 this

function modulus() {
    return Math.sqrt(this.re * this.re + this.im * this.im);
}
var o = {
    re: 1,
    im: -1,
    get phase() {
        return Math.atan2(this.im, this.re);
    }
};
Object.defineProperty(o, 'modulus', {
    get: modulus,
    enumerable: true,
    configurable: true
});
console.log(o.phase, o.modulus); // -0.78 1.4142

get/set 方法中的 this 也会指向 get/set 方法所在的对象的。


构造器中的 this

function MyClass() {
    this.a = 25;
}
var o = new MyClass();
console.log(o.a); //25

new MyClass() 的时候,MyClass()中的 this 会指向一个空对象,这个对象的原型会指向 MyClass.prototype。MyClass()没有返回值或者返回为基本类型时,默认将 this 返回。

function C2() {
    this.a = 26;
    return {
        a: 24
    };
}

o = new C2();
console.log(o.a); //24

因为返回了对象,将这个对象作为返回值


call/apply 方法与 this

function add(c, d) {
    return this.a + this.b + c + d;
}
var o = {
    a: 1,
    b: 3
};
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
function bar() {
    console.log(Object.prototype.toString.call(this));
}
bar.call(7); // "[object Number]"

bind 方法与 this

function f() {
    return this.a;
}
var g = f.bind({
    a: "test"
});
console.log(g()); // test
var o = {
    a: 37,
    f: f,
    g: g
};
console.log(o.f(), o.g()); // 37, test

绑定之后再调用时,仍然会按绑定时的内容走,所以 o.g() 结果是 test