白驹过隙,这篇文章距今已有一年以上的历史。技术发展日新月异,文中的观点或代码很可能过时或失效,请自行甄别:)

很久没有写过JS了,最近因为项目原因又再次滚回JS的怀抱。而之前的this就没怎么弄得很明白,于是今儿抽空仔细的总结了下,利人利己吧:0
this这玩意儿是个什么东西呢?在面向对象语言,比如宇宙第一的语言PHP中代表的就是某个对象。而在同样NB的JS里面,这玩意儿更玄乎,稍微不注意就会挂在这里,其实只要弄明白函数的几种调用场景就能很清晰地理解this了。下面一一来搞定。

用作函数调用

这种形式应该JS中用的最多最广的一种方法了,比如说下面这段函数:

function sayWords(){
    alert(this.words);
}
sayWords();

当我们运行sayWords()的时候会发生什么呢?很显然,会显示出一个没有找到words这个属性的错误提示。好了,我们改一下:

var words = "hello javascript";
function sayWords(){
    alert(this.words);
}
sayWords();

这个时候我们知道了,当用作函数调用的时候,函数体里面的this指向的是window这个对象.

事情到这里还没有结束,看看那下面这段代码:

function sayWords(){
    alert(this.words);
}

var Student = {
    words:"hello world",
    sayWords:function(){
        sayWords();
    }
}

Student.sayWords();

当我们运行Student.sayWords()的时候会发生什么呢?会alert出hello world吗?当你运行时会悲伤地发现,报错了!!!显示找不到words这个属性。好吧,怎么玩呢?

这个时候我们有几种方法:

方法一:

function sayWords(){
    alert(this.words);
}

var Student = {
    words:"hello world",
    sayWords:function(){
        sayWords.apply(this); //注意这里,也可以用sayWords.call(this)
    }
}

Student.sayWords();

在上面的代码中,我们使用了sayWords.apply(this),当然我们使用sayWords.call(this)也可以达到相同的效果,在这里,我们强制将sayWords中this改变为Student对象了,这样就能正确的hello world了:0

当然,在ES5中,我们还可以这样:

function sayWords(){
    alert(this.words);
}

var Student = {
    words:"hello world",
    sayWords:function(){
        var sayWords2 = sayWords.bind(this); //注意这里,也可以用sayWords.call(this)
        sayWords2();
    }
}

Student.sayWords();

上面的sayWords2 = sayWords.bind(this);这里用了ES5的bind方法,该方法会创建一个函数的实例,其this值会通被绑定到传给bind()函数的值

第二种:

var Student = {
    words:"hello world",
    sayWords:function(){
        var that = this;

        function sayWords(){
            alert(that.words);
        }

        sayWords();
    }
}

Student.sayWords();

这种解法应该是很普遍的吧,先把this赋值给另外一个变量,按照习惯,我们一般将这个变量叫做that或者self。这样我们再tath.words的时候就肯定是对的啦

作为对象的方法

这种形式应该是用的最多最广的吧。比如说下面这种代码:

var Student = {
    name:"Scofield Peng",
    age:18,
    showName:function(){
        alert(this.name);
    },
    showAge:function(){
       alert(this.age);
    }
};

Student.showName(); // Scofield Peng
Student.showAge();  // 18

这里面Student.showName和Student.showAge中this指向的就是Student这个对象,相应的this.name就是Stduent.name了,恩,so easy,不多说了

用作构造函数

我们应该常常用这种方法来进行类的实现,尤其是对象的创建的时候,比如:

function Student(){
    this.name = "Scofield Peng";
    this.age  = 18;
    this.sayName = function(){
        alert(this.name);
    }
}

var student = new Student();
student.name = "Julia Gan";
this.sayName();

运行后会alert出"Julia Gan"的字符串,所以在这里,this在这里指向的是student这个对象

用作apply和call的方法

这里的用法在上面已经说了,不再解释。在这种情况下,函数的this所指的就是apply/call中传进来的this对象了