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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.函数调用栈和调用位置 在函数执行的时候,会有一个活动记录(也叫执行上下文)来记录函数的调用顺序,这个就是函数调...
    lightNate阅读 3,535评论 1 14
  • 前言 总括:详解JavaScript中的this的一篇总结,不懂this这个难点,很多时候会造成一些困扰,写出一些...
    秦至阅读 3,604评论 0 4
  • Javascript 中的 this,有时候让人迷惑,所以总结了一下关于this指向的问题。 在函数中 this ...
    lxt410725阅读 3,244评论 0 1
  • 导语 不得不说,作为一名初级的前端开发者,this关键字这个问题对于我来说一直是一个痛点,什么是this?什么是函...
    Nicole_tiny阅读 3,541评论 0 4
  • 1、女儿不睡,说明她不困,没玩好,要记得以后好好对女儿说话吧!她还小,不会记得很多,别让她想起我来真的会做恶梦! ...
    宁静的流星阅读 1,248评论 0 0