资讯专栏INFORMATION COLUMN

不为人知的javascript的内部属性

plokmju88 / 2138人阅读

摘要:词法阶段会定义函数所用到的变量,加入到内部属性当中,它是一个数组,最后一位永远都是全局对象,向前依次是祖先父级。这个等同于的非标准但许多浏览器实现的属性。

内部属性在我们了解对象原型及环境变量时都有遇到过,可是毕竟看不到摸不着,很难更加深入的了解它的工作流程和作用,最近在chrome当中查看对象结构时,看到了释放出来的一些内部属性,这些以前大概都是概念,那么既然能看到,就让我们来探索一下吧~
[[Scopes]]

此属性储存在函数对象中,我记得从chrome 62开始我就发现这个属性了,具体哪个版本大家可以google,现在我们把它给打印出来看一下.

这是一个不访问外部变量的函数,所以Scopes中只储存了Global全局对象。

还记得作用域链吗(如果不记得,请点击这里看前半部分)?
从前往后分别是 [函数自己的变量对象,.., .., Global] 类似于这样依次向后(上)查找这个执行环境所使用到的变量对象。

在上面的文章说过,javascript在开始执行时,会经过两个阶段,预编译->代码执行,在v8中代码执行阶段运行的是机器码,CPU可以直接接收,
可以说,在javascript代码执行前都会经过复杂的代码分割,生成抽象语法树(AST),编译解析与优化等操作,[[Scopes]]正是这其中的产物。下面说
下它形成的流程。

词法阶段会定义函数所用到的变量,加入到[[Scopes]]内部属性当中,它是一个数组,最后一位永远都是Global全局对象,向前依次是祖先->父级。注意,这时只是在第一个阶段,js引擎并没有执行你的操作。(总之所有的脏活累活都要在第一个阶段完成,以保证js引擎执行的最高效率)

执行流进入,读取这个执行环境(函数)的[[Scopes]]属性,并把自身的变量对象加入到前端(unshift),形成作用域链,这样从头到尾的变量对象,构成了伟大的作用域。

需要注意的是,并不是所有的父级作用域的变量都进行存储,而只会存储当前函数所使用到的变量。所以我们进行这样的操作是查看不到父级变量的.

  var a = 1;
  function fun(){
      var b = 1;
      const p = ()=>{}
      console.dir(p)
  }
  fun();

函数p当中并没用使用到父级函数中的变量b,所以[[Scopes]]只有Global对象(注意,因为Global对象永远存在,并且是引用,所以不会出现这种情况),
我认为这也是一种优化手段,可以极大减少内存的使用。

我们换种写法:

var a = 1;
  function fun(){
      var b = 1;
      const p = ()=>{
        var c = 1;
        const f = ()=>{ console.log(b,c) }
        console.dir(f)
      }
      p();
  }
  fun();

我们引用了父级作用域中的变量,并打印出来,在编译阶段,编译器把他们加入到了[[Scopes]]中。

此属性,我们不可去访问与修改它,目前只能在控制台中点击查看.

[[FunctionLocation]]

这个很容易理解,类似于debugger功能,可以很容易的查找到此函数的代码位置,比如我们以React为例,查看 React.Component函数位置.

可以看到,key右侧的可点击部分,表示函数在react-dom.min.js第34行,我们点进去查看,晕了,代码被混淆了...

对于这个属性,我们以后可以大大减少console的使用啦

[[Prototype]]
遵循ECMAScript标准,someObject.[[Prototype]] 符号是用于指向 someObject的原型。从 ECMAScript 6 开始,[[Prototype]]
可以用Object.getPrototypeOf()和Object.setPrototypeOf()访问器来访问。这个等同于 JavaScript 的非标准但许多浏览器实现的属性
__proto__。我们经常使用Object.prototype.toString来判断对象类型,toString就是把当前的这个属性转换成字符串返回出去了.

这个内部属性,表示对象的原型链,类似与[[Scopes]]也是一个数组格式.

   var b = {a:1};
   function o(a){
     this.b = a;
   }
   o.prototype = { c:3; }
   b.__proto__ = new o(2);
   console.log(b.a,b.b,b.c); //1 2 3

此时原型链关系是这样的:

貌似还有很多内部属性,一时想不起来(如果发现,以后会更新),大家有知道的,可以发表评论。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92500.html

相关文章

  • 关于JavaScript对象,你所不知道事(一)- 先谈对象

    摘要:对象与属性让我们保持耐心,再梳理一下对象与属性的关系对象是属性的集合,当对象的属性是函数时,我们将其称之为方法。 这篇博文的主要目的是为了填坑,很久之前我发表了一篇名为关于JavaScript对象中的一切(一) — 对象属性的文章,想要谈一谈JavaScript对象,可那时只是贴了一张关于这个主题的思维导图,今天我会针对这一主题进行展开,将JavaScript对象一些平常不太常用的知识...

    mykurisu 评论0 收藏0
  • JavaScript面向对象OOM 2(JavaScript 创建对象工厂模式和构造函数模式)

    摘要:都是构造函数模式创建的原生构造函数。使用构造函数创建对象经历了以下四个过程创建一个新对象构造函数的作用域交给新对象。   在创建对象的时候,使用对象字面量和 new Object() 构造函数的方式创建一个对象是最简单最方便的方式。但是凡是处于初级阶段的事物都会不可避免的存在一个问题,没有普适性,意思就是说我要为世界上(程序中)的所有使用到的对象都使用一遍 var xxx = {} ,...

    you_De 评论0 收藏0
  • JavaScript面向对象OOM 2(JavaScript 创建对象工厂模式和构造函数模式)

    摘要:都是构造函数模式创建的原生构造函数。使用构造函数创建对象经历了以下四个过程创建一个新对象构造函数的作用域交给新对象。   在创建对象的时候,使用对象字面量和 new Object() 构造函数的方式创建一个对象是最简单最方便的方式。但是凡是处于初级阶段的事物都会不可避免的存在一个问题,没有普适性,意思就是说我要为世界上(程序中)的所有使用到的对象都使用一遍 var xxx = {} ,...

    liuchengxu 评论0 收藏0
  • Webkit 渲染基础与硬件加速

    摘要:网页的渲染方式主要有两种软件渲染和硬件加速渲染。而使用合成化的渲染技术,以使用软件绘图的合成化渲染为例,对于使用绘制的层,其结果保存在内存中,之后传输到中进行合成。 Webkit 渲染基础与硬件加速 当浏览器加载一个 html 文件并对它进行解析完毕后,内核就会生成一个极为重要的数据结构即 DOM 树,树上每一个节点都对应着网页里面的某一个元素,并且开发人员也可以通过 JavaScri...

    ivan_qhz 评论0 收藏0
  • Javascript零碎之各种宽高属性及应用

    摘要:一挂在上的上最常用的只有其中,永远都是窗口的大小,跟随窗口变化而变化。这个是距该元素最近的不为的祖先元素,如果没有则指向元素。 在Javascript的开发过程中,我们总会看到类似如下的边界条件判断(懒加载): const scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.b...

    DevYK 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<