鮮爲人知的javascript的內部屬性

內部屬性在咱們瞭解對象原型及環境變量時都有遇到過,但是畢竟看不到摸不着,很難更加深刻的瞭解它的工做流程和做用,最近在chrome當中查看對象結構時,看到了釋放出來的一些內部屬性,這些之前大概都是概念,那麼既然能看到,就讓咱們來探索一下吧~

[[Scopes]]

此屬性儲存在函數對象中,我記得從chrome 62開始我就發現這個屬性了,具體哪一個版本你們能夠google,如今咱們把它給打印出來看一下.javascript

clipboard.png

clipboard.png

這是一個不訪問外部變量的函數,因此Scopes中只儲存了Global全局對象。前端

還記得做用域鏈嗎(若是不記得,請點擊這裏看前半部分)?
從前日後分別是 [函數本身的變量對象,.., .., Global] 相似於這樣依次向後(上)查找這個執行環境所使用到的變量對象。java

在上面的文章說過,javascript在開始執行時,會通過兩個階段,預編譯->代碼執行,在v8中代碼執行階段運行的是機器碼,CPU能夠直接接收,
能夠說,在javascript代碼執行前都會通過複雜的代碼分割,生成抽象語法樹(AST),編譯解析與優化等操做,[[Scopes]]正是這其中的產物。下面說
下它造成的流程。react

  1. 詞法階段會定義函數所用到的變量,加入到[[Scopes]]內部屬性當中,它是一個數組,最後一位永遠都是Global全局對象,向前依次是祖先->父級。注意,這時只是在第一個階段,js引擎並無執行你的操做。(總之全部的髒活累活都要在第一個階段完成,以保證js引擎執行的最高效率)
  2. 執行流進入,讀取這個執行環境(函數)的[[Scopes]]屬性,並把自身的變量對象加入到前端(unshift),造成做用域鏈,這樣從頭至尾的變量對象,構成了偉大的做用域。

須要注意的是,並非全部的父級做用域的變量都進行存儲,而只會存儲當前函數所使用到的變量。因此咱們進行這樣的操做是查看不到父級變量的.chrome

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

clipboard.png

函數p當中並沒用使用到父級函數中的變量b,因此[[Scopes]]只有Global對象(注意,由於Global對象永遠存在,而且是引用,因此不會出現這種狀況),
我認爲這也是一種優化手段,能夠極大減小內存的使用。segmentfault

咱們換種寫法:數組

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

clipboard.png

咱們引用了父級做用域中的變量,並打印出來,在編譯階段,編譯器把他們加入到了[[Scopes]]中。瀏覽器

此屬性,咱們不可去訪問與修改它,目前只能在控制檯中點擊查看.dom

[[FunctionLocation]]

這個很容易理解,相似於debugger功能,能夠很容易的查找到此函數的代碼位置,好比咱們以React爲例,查看 React.Component函數位置.函數

clipboard.png

能夠看到,key右側的可點擊部分,表示函數在react-dom.min.js第34行,咱們點進去查看,暈了,代碼被混淆了...

clipboard.png

對於這個屬性,咱們之後能夠大大減小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

此時原型鏈關係是這樣的:

clipboard.png

貌似還有不少內部屬性,一時想不起來(若是發現,之後會更新),你們有知道的,能夠發表評論。

相關文章
相關標籤/搜索