Javascript中的this

thisJavascript语言的一个关键字。
它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。比如,

function test() {
  this.x = 1;
}

随着函数使用场合的不同,this的值会发生变化。但是有一个总的原则,那就是this指的是,调用函数的那个对象。
下面分四种情况,详细讨论this的用法。

情况一:纯粹的函数调用

这是函数的最通常用法,属于全局性调用,因此this就代表全局对象Global

function test(){
  this.x = 1;
  alert(this.x);
}
test(); // 1

为了证明this就是全局对象,我对代码做一些改变:

var x = 1;
function test(){
  alert(this.x);
}
test(); // 1

运行结果还是1。再变一下:

var x = 1;
function test(){
  this.x = 0;
}
test();
alert(x); //0

这时内部函数不能访问外部函数的thisarguments,解决方法是在外部函数定义一个变量并给它赋值为this

情况二:作为对象方法的调用

函数还可以作为某个对象的方法调用,这时this就指这个上级对象。

function test(){
  alert(this.x);
}
var o = {};
o.x = 1;
o.m = test;
o.m(); // 1

情况三 作为构造函数调用

所谓构造函数,就是通过这个函数生成一个新对象(object)。这时,this就指这个新对象。

function test(){
   this.x = 1;
}
var o = new test();
alert(o.x); // 1

运行结果为1。为了表明这时this不是全局对象,我对代码做一些改变:

var x = 2;
function test(){
  this.x = 1;
}
var o = new test();
alert(x); // 2

运行结果为2,表明全局变量x的值根本没变。

情况四 apply调用

apply()是函数对象的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象。因此this指的就是这第一个参数。

var x = 0;
function test() {
  alert(this.x);
}
var o = {};
o.x = 1;
o.m = test;
o.m.apply(); // 0

apply()的参数为空时,默认调用全局对象。因此,这时的运行结果为0,证明this指的是全局对象。
如果把最后一行代码修改为

o.m.apply(o); // 1

运行结果就变成了1,证明了这时this代表的是对象o

情况五:箭头函数

函数体内的this对象,绑定定义时所在的对象,而不是使用时所在的对象。第一段代码中如果没有用self代替this,那么setTimeout函数内function中的this将指向全局对象。

function foo() {
    var self = this;
    setTimeout(function() {
        console.log("id:", self.id);
    }, 100);
}

foo.call( { id: 42 } );
// id: 42

function foo() {
    setTimeout( () => {
        console.log("id:", this.id);
    }, 100);
}

foo.call( { id: 42 } );
// id: 42

箭头函数看上去是匿名函数的一种简写,但实际上,箭头函数和匿名函数有个明显的区别:箭头函数内部的this是词法作用域,由上下文确定(词法作用域,即变量的作用域在函数定义的时候就决定了)。

由于 JavaScript 函数对this绑定的错误处理,下面的例子无法得到预期结果:

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = function () {
            return new Date().getFullYear() - this.birth; // this指向window或undefined
        };
        return fn();
    }
};

现在,箭头函数完全修复了this的指向,this总是指向词法作用域,也就是外层调用者obj

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象
        return fn();
    }
};
obj.getAge(); // 25

如果使用箭头函数,以前的那种 hack 写法:

var that = this;

就不再需要了。

由于this在箭头函数中已经按照词法作用域绑定了,所以,用call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略:

var obj = {
    birth: 1990,
    getAge: function (year) {
        var b = this.birth; // 1990
        var fn = (y) => y - this.birth; // this.birth仍是1990
        return fn.call({birth:2000}, year);
    }
};
obj.getAge(2015); // 25

this指向的详细说明请看:从 ECMAScript 规范解读 this

你可能感兴趣的:(Javascript中的this)