ES5 中 this 指向问题-----【我的附庸的附庸,不是我的附庸】

        在欧洲中世纪,城堡是西欧封建社会的基层核心,但在最高王权与最底层的农奴之间,不止是有一层领主,而是有好几个层次,每个领主的领地都来源于上一级大领主的封赏,同时他可将自己的领地划成数块封给自己的属下(即他的附庸),依次类推,直至最低一等的普通骑士。通常情况下附庸只对他的直接上一级领主负责,从而形成了所谓“我的附庸的附庸不是我的附庸”的原则。

       在  ES 5 的世界里,this 隐式绑定时,他就是一个领主,只对他的直接上级领主负责,领主去哪里征战,他就奔赴哪里,赴汤蹈火,在所不辞,而他领主的领主,却不是他的领主......

 

1. 隐式绑定

在 js 中,我们知道变量都有自己的执行期上下文,一个变量在刚出生(声明)时,它的作用域就已经可知了;但是 this 却不一样,this 是谁直接调用它,它就指向谁!!!(es5)

我们下面就针对这句话进行详细的讲解:

首先还是老规矩,我们上代码:

【案例一】:

var name= "edward"

function fn(){
    var name = "zhangsan";
    console.log(this)             //  Window
    console.log(this.name);       //  edward
}
var b = fn();   

千万千万不可以认为!!!this.name就是this所在的作用域从而认为 this.name是zhangsan !!!

这里的 var b = fn()  实际上可以看成是  var b = window.fn()

其实,只要我们在全局里调用一个函数,其实都是 window 在调用,window 就是全局(Global)。类似的还有:window.alert('hello world')   window.setInterval('i am edward'),等等。

 

【案例二】:链式调用(我的附庸的附庸,不是我的附庸)

 1 var name= "edward"
 2 function fn(){
 3    var name= "zhangsan";
 4    console.log(this.name);
 5 }
 6 var obj = {
 7    name:"lisi"
 8 };
 9 obj.fn = fn;
10 
11 obj.fn();  // lisi

如果你刚刚看过案例一,你也许会想,第11行代码是不是要先看成是 window.obj.fn() 。当然这样是没有什么问题的,那么问题来了,到底是window调用了function fn 中的 this, 还是 obj 调用的,funciton fn 中的 this 又该何去何从呢?

需要注意的是,如果想知道某个函数中的 this 到底代表啥意思,当务之急是要找到是谁直接调用的 this,( 注意“直接”二字!!)

在window.obj.fn()这个链式调用中,window相当于国王,obj相当于是被国王册封的贵族,fn()中的 this 就是被贵族册封的下属,这俗话说的好啊,“我的附庸的附庸,不是我的附庸”。眼看着咱这话都说到了这个份儿上了,呵呵,fn 的 this 就发话了:“国王您就算再大,也甭想使唤我,就是这么硬气!”。国王想了想,反正是朕的江山,得嘞。就这样,this 忠心耿耿,一心向着 obj, obj说啥他就信啥,大智若愚。

 回到正题,obj.fn() 虽然在全局的范围,但直接调用function fn 中的 this 的,是对象obj:

var obj = {
   name:"lisi",
   fn: function () {
       var name = "zhangsan"
       console.log(this.name)
   }
}
obj.fn() // "lisi"

 再如:

    var person1 = {
        name:'Tom',
        getName(){
            console.log(this); // person1
            console.log(this.name); // Tom
        }
    };

    var person2 = {
        name:'sam',
        friend:person1
    };

   var person3 = {
        name: 'jam',
        friend:person2
    };

    person3.friend.friend.getName()  //本质上还是 person1 调用的

 

posted @ 2019-10-19 23:52  牧羊狼  阅读(561)  评论(0编辑  收藏  举报