• js通过沿着作用域链还是原型链查找变量


    这是一道非常典型的JS闭包问题,结果和具体的解析请看这里

    对于其中的`函数作用域链的问题`博主似乎没有解释清楚,有一些疑问:js中的变量到底是沿着作用域链还是原型链查找呢?

    首先,要分清作用域链与原型链的区别,简单来说

    作用域链是相对于函数的,原型链是相对于对象的

    js中访问变量有多种方式
    1. 直接通过标识符访问
    2. 通过 . 或 [] 访问对象中的标识符

    猜想访问方式不同,导致了查找的方式不同:
    1. 直接通过标识符访问,访问的可能是函数中的标识符,也可能是全局对象(浏览器中是 window)的标识符,也就是说,可能沿着作用域链也可能沿着原型链访问
    2. 通过 . 或 [] 访问对象中的标识符,js会沿着原型链查找

    对于第二点,以下的小测试可以证明

    ① 相当于调用 window.test(),this 指向 window,访问的是 window.a;

    ② 中 this 指向 o,访问的是 o.a;

    将全局的 a, 也就是 window.a 和 o.a 删除之后,得到的结果均是 1。

    因此,通过 . 或 [] 访问`对象`中的标识符,js会沿着原型链查找。

    第一点,直接通过标识符访问,也就是访问当前执行上下文EC的作用域中的变量,这一过程称为标识符解析,依赖于作用域链。


    作用域链Scope其实就是对执行上下文EC中的变量对象VO|AO有序访问的链表

    关于作用域链与执行上下文 EC 的关系,请看这里

    测试

    把 this.a 改为 a,②的结果就变啦。

    ① 和 ② 的执行上下文EC(即 this 的指向)分别为 window 和 o,但作用域链都是 test变量对象 + 全局变量对象。而test变量对象中没有 a,全局变量对象含有 a 。这就说明,在函数中直接通过标识符变量,js会沿着作用域中查找。

    有趣的是,当删除了全局变量对象中的 a,再访问 a,浏览器并没有报错,而是输出 4;删除 Window.prototype.a 之后,输出的这是 1.
    在 test 中添加一下代码 :


    由结果可知,访问到的a 分别为 Window.prototype 和 Object.prototype 中的变量。

    为什么呢?因为在浏览器中,全局变量对象在浏览器中指向 window, window 也是对象,且位于作用域链的末尾;作用域链查找完,仍然找不到,js 就会沿着全局变量对象的原型链查找。

    结论

    1. 直接通过标识符访问变量,首先沿着作用域链查找每一个变量对象,直到全局变量对象(window)仍没有,就沿着全局变量对象(window)的原型链查找
    2. 通过 . 或 [] 访问对象中的标识符,就直接沿着原型链查找

  • 相关阅读:
    通过圆形按钮的绘制熟悉Qt的绘图机制,掌握这种终极方法
    Qt用委托绘制需要的图形的步骤
    定位问题的一个思路
    头文件找不到引用的类的定义
    model的index无限次数执行导致stackOverFlow
    error C2248: 'QObject::QObject' : cannot access private member declared in class 'QObject'
    Python爬虫之使用celery加速爬虫
    Python之celery的简介与使用
    NLP入门(七)中文预处理之繁简体转换及获取拼音
    NLP入门(六)pyltp的介绍与使用
  • 原文地址:https://www.cnblogs.com/xxhuan/p/6008037.html
Copyright © 2020-2023  润新知