一个JS初学者关于查找变量的一些感悟。。

我是一个js的初学者,这几天被直接访问标识符和经过this访问标识符搞的头疼,因而大胆的作了一个猜想:
1. 直接访问标识符是经过做用域链进行查找的。
2. 经过this访问标识符是经过原型链来查找的。
而后就开始试了起来!!!!前端

结合下面的代码来讲浏览器

var a = "abc";

var obj = {
    a: "def",
    display3: function () {
        var a = "sssss";
        console.log(a);
    },
    display4: function() {
        console.log(this.a);
    }
}

Object.prototype.a = "ghi";

function display1() {
    // var = "hahaha";
    console.log(a)
}

function display2() {
    console.log(this.a);
}

display1(); // "abc"
display2();  // "abc"

obj.display3();
obj.display4();

// display2.call(obj);  // "def"
// display1.call(obj);  // "abc"

首先:函数

第一个:
调用display1函数,经过做用域链来查找a。此时display1的做用域链为:display1的活动对象→全局活动对象,
因此找到了全局活动对象中的"abc",若是在display1中有变量a,那么输出的则是这个变量的值。this

第二个
调用diplay2函数,经过原型链来查找a。由于this是基于当前的执行环境绑定的,因此this指向全局变量对象(也就是window),因此找到了"abc"并输出。
有意思的是,此时若是我删除window中定义的a="abc", 那么输出结果则是"ghi". 因而回忆了一下本身所学的知识,发现由于window对象是Global对象在浏览器中的表现,而后Global是js中的单体内置对象,那么彷佛它也应该继承自Object.prototype, 恩..按照个人猜测,输出结果为"ghi"是情理之中的。prototype

第三个:
经过obj调用display3函数,由于前面没有this,因此是经过做用域链进行查找的,此时display3的做用域链为display1的活动对象→全局活动对象,因此输出结果是"abc", 一样,若是我再display3中定义了a,那么输出的则是这个a的值code

第四个
经过obj调用display4函数,由于前面有this,因此是经过原型链进行查找的,此时this指向的是obj,因此输出的结果是obj对象中"def",若是咱们删除obj中的a属性,那么输出结果则是Object.prototype中的"ghi",若是再删除这个ghi,那么输出结果就是undefined了。
上面这些好像都符合逻辑,但是我又忽然发现,当调用display1时,若是删除了做用域链中每一个变量对象的a属性,那么输出结果则是"ghi", 这个"ghi"是在Object.prototype中定义的,因此对象

综合了一下继承

1. 直接访问标识符是经过做用域链和原型链综合进行查找的。
2. 经过this访问标识符是经过原型链来查找的。
而后又出现了一个问题:直接访问标识符的查找顺序是 1:先查找做用域链前端的变量对象,而后再查找它的原型,而后再查找做用域链中下一个变量对象,而后再查找它的原型 仍是 2: 一直查找做用域链中的变量对象,知道window对象,再查找它的原型呢?ip

而后又忽然发现,在调用display1时,若是display1中没有定义a变量,访问到的则是window中的a = "abc",而不是Object.prototype中的a = "ghi".原型链

因此再综合一下

1. 直接访问标识符的顺序是按顺序查找做用域链中的每个变量对象直至全局变量对象,若是全局变量对象中没

有该变量,则沿着window对象的原型链进行查找。

2. 经过this访问标识符是经过原型链来查找的。

我去累死了,我也没想到本身写了这么多,从结果来看,应该是这样,不过也不知道究竟是不是这样。。

相关文章
相关标签/搜索