疾速明白JavaScript中this的用法与圈套

this是 JS 这门言语的魅力之一——天真轻易又难以捉摸,即使是有履历的程序员,假如不细致也有能够搞错,关于this的用法也成为很多公司的典范面试题。

假如你写过 Java ,你能够打仗过this——平常指向当前对象,实际上,这时刻this的寄义已肯定了,由于Java属于编译期绑定,而JS属于运转期绑定,所以致使this的寄义在运转过程当中能够有多种变化。

进一步说,this和它声明环境无关,而完整取决于他的实行环境。务必切记这句话。

//读以下代码之前,必须先浏览《哈利·波特》原著。(笑)

var name = '罗恩';
var aaa = {
    name: '哈利',
    say: function () {
        console.log(this.name);
    }
}

var bbb = {
    name: '赫敏',
    say: aaa.say
}

var ccc = aaa.say;

aaa.say();    //哈利
bbb.say();    //赫敏
ccc();        //罗恩

我们看第一行,aaa.say()挪用的是aaa对象本身的say()要领,此时this指代的是aaa对象本身,所以此时输出固然就是aaa对象的name属性值。

第二行,bbb.say();输出赫敏肯定和JS新手们的基本学问不符合,实在只需切记“this取决于实行环境”就能够想邃晓。bbb对象是怎样声明本身的say要领的呢?它只是把aaa对象的say要领援用过来,注重,援用的是一个要领而非一个对象,而aaa.say存储的是一个匿名函数,所以这类写法和以下代码并没有什么区别。

var bbb = {
    name: '赫敏',
    say: function () {
        console.log(this.name);
    }
}

第三行的ccc()是在最外层实行,也就是在全局对象window下。所以ccc()实行的时刻this指代的就是window对象。而在window对象下声清楚明了name属性,就相当于window.name = '罗恩',输出的固然就是罗恩

固然,也有特殊状况,那就是 setTimeout 和 setInterval 。
我把开首的aaa对象的声明改成:

var aaa = {
    name: '哈利',
    getName: function () {
        setTimeout(function(){
            console.log(this.name);
        },100)
    }
}

仅仅是在console.log(this.name)表面套了一个setTimeout,猜猜本来三行的输出会是什么?

答案:3个罗恩
也就是说,三次this,指代的都是window对象。

关于为何会如许,我这里暂时不细致睁开,由于涉及到JS异步回调的学问,假如你仅仅想疾速熟习this的用法,那末只需记着这个特殊状况即可。这个学问点曾经是阿里照样小米的面试题。

明显,三个罗恩不是我想要的,毕竟韦斯莱夫人的孩子已够多了。那末我们只需轻微改写一下这个要领:

getName: function () {
        //在setTimeout外存储this指代的对象
        var that = this;
        setTimeout(function(){
            //this.name变成了that.name
            console.log(that.name);
        },100)
    }

输出就又一般了。

明显,that并非一个关键字,只是一个人人处理这类状况时约定俗成的名字。假如你情愿,也能够叫thatGuy。固然,考虑到能够会有其他人保护你的代码,照样用that比较好。

之所以写这篇文章,是为了我下一篇文章做铺垫:
《疾速明白JavaScript中apply()和call()的用法》
敬请期待~~

    原文作者:条件状语从句
    原文地址: https://segmentfault.com/a/1190000004580525
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞