重學前端學習筆記(九)--JavaScript中的對象分類

筆記說明

重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄, 天天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完整的能夠加入winter的專欄學習【原文有winter的語音】,若有侵權請聯繫我,郵箱:kaimo313@foxmail.com。

1、javaScript對象分類介紹

1.0、宿主對象(host Objects)

由 JavaScript 宿主環境提供的對象,它們的行爲徹底由宿主環境決定。

1.一、內置對象(Built-in Objects)

由 JavaScript 語言提供的對象。

1.1.0、固有對象(Intrinsic Objects )

由標準規定,隨着 JavaScript 運行時建立而自動建立的對象實例。

1.1.一、原生對象(Native Objects)

能夠由用戶經過 Array、RegExp 等內置構造器或者特殊語法建立的對象。

1.1.二、普通對象(Ordinary Objects)

{} 語法、 Object 構造器或者 class 關鍵字定義類建立的對象,它可以被原型繼承。

下面winter主要介紹了普通對象以外的對象原型(恰好都是我不太懂的,mark一下)html

2、宿主對象

2.0、window對象

  • 全局對象 window 上的屬性,一部分來自 JavaScript 語言,一部分來自瀏覽器環境
  • 宿主也會提供一些構造器,好比使用 new Image來建立 img 元素(winter下次會講瀏覽器的API,到時再詳細的mark一下)

3、內置對象·固有對象

3.0、簡單介紹

  • 固有對象在任何 JS 代碼執行前就已經被建立出來,相似基礎庫的角色
  • ECMA 標準爲咱們提供了一份固有對象表,裏面含有 150+ 個固有對象(連接打開比較慢,稍等一下就好)

3.一、小實驗:獲取所有 JavaScript 固有對象

3.1.0、三個值

Infinity、NaN、undefined

3.1.一、九個函數

eval、isFinite、isNaN、parseFloat、parseInt、decodeURI decodeURIComponent、encodeURI、encodeURIComponent

3.1.二、一些構造器

Array、Date、RegExp、Promise、Proxy、Map、WeakMap、Set、WeapSet、Function、Boolean、String、Number、Symbol、Object、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError URIError、ArrayBuffer、SharedArrayBuffer、DataView、Typed Array、Float32Array、Float64Array、Int8Array、Int16Array、Int32Array、UInt8Array、UInt16Array、UInt32Array、UInt8ClampedArray

3.1.三、四個用於看成命名空間的對象

Atomics、JSON、Math、Reflect

3.1.四、處理方法

一、winter的作法:使用廣度優先搜索,查找這些對象全部的屬性和 Getter/Setter,就能夠得到 JavaScript 中全部的固有對象。前端

二、下面代碼能夠研究一下看看,new Set()不懂的能夠看看MDN關於set的介紹,(我如今尚未看明白,我去不一樣網頁打開運行輸出set不同,感受有點懵逼_(:3」∠)_,理解的大佬能夠留言告訴我,不勝感激)java

var set = new Set();
var objects = [
    eval,
    isFinite,
    isNaN,
    parseFloat,
    parseInt,
    decodeURI,
    decodeURIComponent,
    encodeURI,
    encodeURIComponent,
    Array,
    Date,
    RegExp,
    Promise,
    Proxy,
    Map,
    WeakMap,
    Set,
    WeakSet,
    Function,
    Boolean,
    String,
    Number,
    Symbol,
    Object,
    Error,
    EvalError,
    RangeError,
    ReferenceError,
    SyntaxError,
    TypeError,
    URIError,
    ArrayBuffer,
    SharedArrayBuffer,
    DataView,
    Float32Array,
    Float64Array,
    Int8Array,
    Int16Array,
    Int32Array,
    Uint8Array,
    Uint16Array,
    Uint32Array,
    Uint8ClampedArray,
    Atomics,
    JSON,
    Math,
    Reflect];
objects.forEach(o => set.add(o));

for(var i = 0; i < objects.length; i++) {
    var o = objects[i]
    for(var p of Object.getOwnPropertyNames(o)) {
        var d = Object.getOwnPropertyDescriptor(o, p)
        if( (d.value !== null && typeof d.value === "object") || (typeof d.value === "function"))
            if(!set.has(d.value))
                set.add(d.value), objects.push(d.value);
        if( d.get )
            if(!set.has(d.get))
                set.add(d.get), objects.push(d.get);
        if( d.set )
            if(!set.has(d.set))
                set.add(d.set), objects.push(d.set);
    }
}

4、內置對象·原生對象

4.0、分類

winter按照不一樣應用場景,將原生對象分紅了如下幾個種類

原生對象種類

4.一、注意的幾個點

  • 能夠用 new 運算建立新的對象
  • 幾乎全部這些構造器的能力都是沒法用純 JavaScript 代碼實現
  • 也沒法用 class/extend 語法來繼承
  • 建立的對象多數使用了私有字段,好比:Error: [[ErrorData]]...這些字段使得原型繼承方法沒法正常工做
  • 全部這些原生對象都是爲了特定能力或者性能,而設計出來的特權對象

5、用對象來模擬函數與構造器:函數對象與構造器對象

5.0、函數對象的定義

具備 [[call]] 私有字段的對象

[[call]] 私有字段必須是一個引擎中定義的函數,須要接受 this 值和調用參數,而且會產生域的切換數組

5.一、構造器對象的定義

具備 [[construct]] 私有字段的對象

5.1.0、[[construct]] 的大體執行過程

一、以 Object.protoype 爲原型建立一個新對象
二、以新對象爲 this,執行函數的 [[call]]
三、若是 [[call]] 的返回值是對象,那麼,不然返回第一步建立的新對象瀏覽器

5.二、例子

一、內置對象 Date 在做爲構造器調用時產生新的對象,做爲函數時,則產生字符串,見如下代碼:函數

console.log(new Date);
console.log(Date())

二、瀏覽器宿主環境中,提供的 Image 構造器,則根本不容許被做爲函數調用。性能

console.log(new Image);
console.log(Image()); // 拋出錯誤 Uncaught TypeError: Failed to construct 'Image': Please use the 'new' operator, this DOM object constructor cannot be called as a function.'Image'

三、基本類型(String、Number、Boolean),它們的構造器被看成函數調用,則產生類型轉換的效果學習

四、在 ES6 以後 => 語法建立的函數僅僅是函數,它們沒法被看成構造器使用,見如下代碼:ui

new (a => 0) // 報錯:Uncaught TypeError: (intermediate value) is not a constructor

五、使用 function 語法或者 Function 構造器建立的對象來講,[[call]][[construct]] 行爲老是類似的,它們執行同一段代碼。this

function f(){
    return 1;
}
var v = f(); // 把 f 做爲函數調用
var o = new f(); // 把 f 做爲構造器調用

六、若是構造器返回了一個新的對象,那麼 new 建立的新對象就變成了一個構造函數以外徹底沒法訪問的對象,這必定程度上能夠實現私有

function cls(){
    this.a = 100;
    return {
        getValue: () => this.a
    }
}
var o = new cls;
o.getValue(); //100
//a 在外面永遠沒法訪問到

6、特殊行爲的對象

6.0、行爲不大同樣的對象

winter總結了常見的下標運算(就是使用中括號或者點來作屬性訪問)或者設置原型跟普通對象不一樣的對象,以下:
  • ArrayArraylength 屬性根據最大的下標自動發生變化。
  • Object.prototype:做爲全部正常對象的默認原型,不能再給它設置原型了。
  • String:爲了支持下標運算,String 的正整數屬性訪問會去字符串裏查找。
  • Argumentsarguments 的非負整數型下標屬性跟對應的變量聯動。
  • 模塊的 namespace 對象:特殊的地方很是多,跟通常對象徹底不同,儘可能只用於 import
  • 類型數組和數組緩衝區:跟內存塊相關聯,下標運算比較特殊
  • bind 後的 function:跟原來的函數相關聯

我的總結

看完這篇,有點崩潰,如今已經凌晨2點48了,還沒搞懂,感受以前學的過於皮毛,這些東西看起來一臉懵逼,哈哈哈...,有時間在好好增強一下這塊的知識

相關文章
相關標籤/搜索