重學前端面向對象及其原型(二)

重學前端(二)

  • 運行時類型是代碼實際執行過程中我們用到的類型。所有的類型數據都會屬於7個類型之一。從變量、參數、返回值到表達式中間結果,任何JavaScript代碼運行過程中產生的數據,都具有運行時類型。

類型

  • Undefined
  • Null
  • Boolean
  • String
  • Number
  • Symbol
  • Object

Undefined Null

  • Undefined類型表示未定義,他的類型只有一個值,就是undefined.任何變量在賦值前是Undefined類型、值爲undefined,一般我們可以用全局變量undefined(就是名爲undefined的這個變量)來表達這個值,或者void運算來把任意一個表達式變成undefined
  • Null類型也只有一個值,就是null,表示爲控制,與undefined不同

String

  • String用於表示文本數據,最大長度爲2^53 - 1

Number

  • Number類型基本符合IEEE 754-2008規定的雙精度浮點數規則,根據浮點數的定義,非整數的Number類型無法用 **== (===也不行)**來比較

    • 0.1 + 0.2 == 0.3 //輸出 false
      
    • 正確的比較方法:使用JavaScript提供的最小精度值

    • Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON
      
  • NaN,佔用了 9007199254740990,這原本是符合IEEE規則的數字;

  • Infinity,無窮大;

  • -Infinity,負無窮大。

  • JavaScript中有+0 和 -0 ,在假髮類運算中它們沒有區別,單數觸發的場合則需要特別留意區分**,‘忘記檢測除以-0,而得到負無窮大’**的情況經常會導致錯誤,而區分+0 和 -0 的方式,正式檢測 1/x 是 infinity還是-infinity

Symbol

  • SymbolES6中引入的新類型,它是一切非字符串的對象key的集合,在ES6中,整個對象系統被用Symbol

Object

  • 對象的定義是‘屬性的集合’。屬性分爲數據屬性和訪問器屬性,二者都是key-value結構,key可以是字符串或者Symbol類型
  • JS中的類僅僅是運行時對象的一個私有屬性,而JS中時無法自定義類型的,在js的幾個基本類型中,都在對象類型中有一個親戚
    • Number
    • String
    • Boolean
    • Symbol
  • 所以,3 和 new Number(3)是完全不同的值,它們是一個Number類型,一個是對象類型,NumberStringBoolean,三個構造器是倆用的,當跟new搭配時,它們產生對象,當直接調用的時候,它們表示強制類型轉換
  • .(點)運算符提供了裝箱操作,它會根據基礎類型構造一個臨時對象,使得我們能在基礎類型上調用對應對象的方法

裝箱轉換

  • 每一種基本類型NumberStringBooleanSymbol在對象中都有對應的類,所謂裝箱轉換,正是把基本類型轉換爲對應的對象,他是類型轉換中一種相當重要的種類

拆箱轉換

  • 在JavaScript標準中,規定了 ToPrimitive函數,它是對象類型到基本類型的轉換(即,拆箱轉換)。
  • 對象到 String 和 Number 的轉換都遵循“先拆箱再轉換”的規則。通過拆箱轉換,把對象變成基本類型,再從基本類型轉換爲對應的 String 或者 Number。
  • 拆箱轉換會嘗試調用 valueOf 和 toString 來獲得拆箱後的基本類型。如果 valueOf 和 toString 都不存在,或者沒有返回基本類型,則會產生類型錯誤 TypeError。

總結

  • List 和 Record: 用於描述函數傳參過程。
  • Set:主要用於解釋字符集等。
  • Completion Record:用於描述異常、跳出等語句執行過程。
  • Reference:用於描述對象屬性訪問、delete等。
  • Property Descriptor:用於描述對象的屬性。
  • Lexical Environment 和 Environment Record:用於描述變量和作用域。
  • Data Block:用於描述二進制數據。

JavaScript對象的特徵

  • 對象具有唯一標識性:即使完全相同的倆個對象,也並非同一個對象
  • 對象有狀態:對象具有狀態,同一對象可能處於不同狀態之下
  • 對象具有信鴿網i:季對象的狀態,可能因爲它的行爲產生變遷

(一)具有唯一標識性

  • 各種語言的對象唯一標識性都是用內存地址來體現的,對象具有唯一表示的內存地址,所以具有唯一的標識

(二)第二 和 第三特徵

  • JS中,將狀態和行爲統一抽象爲‘屬性’,考慮到JavaScript中函數設計成一種特殊對象

  • 下面代碼就展示了 普通屬性 和 函數作爲屬性的一個例子,其中 o是對象,d是屬性,而函數f也是一個屬性,儘管寫法不太相同,但是對JavaScript來說,df就是倆個普通屬性

  • var o = {
    	d:1,
    	f(){
    		console.log(this.d)
    	}
    }
    

JavaScript中對象獨有的特色是:對象具有高度的動態性,這是因爲JS賦予了使用者在運行是爲對象添加狀態和行爲的能力

  • 爲了提高抽象能力,JavaScript的屬性被設計成比別的語言更加複雜的形式,它提供了 數據屬性和訪問器屬性(getter / setter)倆類

JavaScript對象的倆類屬性

數據屬性具有四個特徵
  • value:就是屬性的值
  • writable:決定屬性能否被賦值
  • enumerable:決定for in能否枚舉該屬性
  • configurable:決定改屬性能否被刪除或者改變特徵值

訪問器(getter / setter)屬性

  • getter:函數 或者 undefined,在取屬性值時被調用
  • setter:函數 或者 undefined,在設置屬性值時被調用
  • enumerable:決定for in能否枚舉該屬性
  • configurable:決定該屬性能否被刪除或者改變特徵值

訪問器屬性是的屬性在讀和寫時執行代碼,它允許使用者在寫和堵屬性時,得到完全不同的值,它可以是爲一種函數的語法糖

我們通常用於定義屬性的代碼會產生數據屬性,其中的writableenumerableconfigurable都會默認true, 我們可以使用內置函數 Object.getOwnPropertyDescripter來查看

JavaScript對象的具體設計:具有高度動態性的屬性集合

JavaScript得原型

  • 如果所有對象都有私有字段[[prototype]],就是對象的原型
  • 讀一個屬性,如果對象本身沒有,則會繼續訪問對象的原型,知道原型爲空或者找到爲止,(原型鏈)

ES6,JS提供了一系列內置函數,以便更爲直接的訪問操縱原型

  • Object.create根據指定的原型創建新對象,原型可以是null;
  • Object.getPrototypeOf獲得一個對象的原型;
  • Object.setPrototypeOf設置一個對象的原型。

早期版本中的類與原型

  • ‘類’的定義是一個私有屬性[[class]],語言標準爲內置類型諸如NumberStringDate等指定了[[class]]屬性,以表示它們的類。語言使用者唯一可以訪問[[class]]屬性的方式是Object.prototype.toString

  •     var o = new Object;
        var n = new Number;
        var s = new String;
        var b = new Boolean;
        var d = new Date;
        var arg = function(){ return arguments }();
        var r = new RegExp;
        var f = new Function;
        var arr = new Array;
        var e = new Error;
        console.log([o, n, s, b, d, arg, r, f, arr, e].map(v => 	Object.prototype.toString.call(v))); 
      
      //輸出
      (10) ["[object Object]", "[object Number]", "[object String]", "[object Boolean]", "[object Date]", "[object Arguments]", "[object RegExp]", "[object Function]", "[object Array]", "[object Error]"]
    0: "[object Object]"
    1: "[object Number]"
    2: "[object String]"
    3: "[object Boolean]"
    4: "[object Date]"
    5: "[object Arguments]"
    6: "[object RegExp]"
    7: "[object Function]"
    8: "[object Array]"
    9: "[object Error]"
    length: 10
    __proto__: Array(0)
    

new運算接受一個構造器 和一組調用參數,實際上做了幾件事

  • 以構造器的prototype屬性(注意與私有字段[[prototype]]的區分)爲原型,創建新對象
  • this和調用參數傳給構造器,執行
  • 如果構造器返回的時對象,則返回,否則返回第一步創建的對象

JavaScript中的對象分類

  • 宿主對象(host Objects):由JavaScript宿主環境提供的環境,它們的行爲完全由宿主環境決定
  • 內置對象(Built-in Object):由JavaScript語言提供的對象
    • 內置對象(intrinsic Objects):由標準規定,隨着JavaScript運行時創建而自動創建的對象實例
    • 原生對象(Native Object):可以由用戶通過ArrayRegExp等內置構造器或者特殊語法創建的對象
    • 普通對象(Ordinary Objects):由{}語法、Objects構造器或者class關鍵字定義類創建的對象,它能夠被原型繼承

宿主對象

  • 瀏覽器環境中的宿主,全局對象時windowwindow上又有很多屬性,比如document,實際上這個全局對象window上的屬性,一部分來自於JavaScript語言,一部分來自於瀏覽器環境
  • 宿主對象也分爲固有的和用戶可創建的倆種,比如document.createElement就可以創建一些dom對象,宿主也會提供一些構造器,比如我們可以使用 new Image來創建img對象

內置對象-固有對象

  • 固有對象是由標準規定,隨着JavaScript運行時創建而自動創建的對象實例,固有對象在任何JS代碼執行前就已經被創建出來了。

內置對象-原生對象

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-5EcAR0pB-1581861071709)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200123193705440.png)]

  • 通過這些構造器,我們可以用new運算創建薪得對象,所以我們把這些對象稱作爲原生對象
  • 這些構造器創建的對象多數使用了私有字段,例如:
    • Error: [[ErrorData]]
    • Boolean: [[BooleanData]]
    • Number: [[NumberData]]
    • Date: [[DateValue]]
    • RegExp: [[RegExpMatcher]]
    • Symbol: [[SymbolData]]
    • Map: [[MapData]]

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

  • 函數對象的定義是:具有[[call]]私有字段的對象,構造器對象的定義是:具有私有字段[[construct]]的對象
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章