[寫作中...]Js物件導向(2): 建立物件

LeoooY發表於2019-02-15

目標

  • 理解物件
  • 建立物件例項
  • 理解Js中的繼承

前言

理解物件中瞭解到了兩種最簡單的建立物件的方式,本篇詳細討論Js中各種建立物件的方法。

建立物件

重點需要搞清楚建構函式模式原型模式組合使用兩種模式的建立物件例項方法。(明白前兩個其實大概就明白瞭如何組合使用)

1、工廠模式

工廠模式是一種廣泛使用的設計模式, 建立物件的工廠模式,簡單地理解就是new Object()建立物件的具體過程封裝為一個函式

function CreatSomething(){
    const o = new object();
    o.propertyName1='value1';
    o.propertyName2='value2';
    ...
    o.functionName=function (){
        console.log(this.propertyName1);
    }
}
複製程式碼

工廠模式存在的問題是,沒有解決物件識別的問題(無法判斷一個物件是由哪個函式例項化的),因此用的也不多,作為一個瞭解。

2、建構函式模式

2.1、普通建構函式模式

通過Js的一些內建物件可以建立物件例項,如ObjectArray等,也可以自定義建構函式,如:

funtion Something(val,num){
    this.propertyName1=val;
    this.propertyName2=num;
    ...
    this.functionName=function (){
        console.log(this.propertyName1);
    }
}
const something1=new Something('val1',21);
const something2=new Something('val2',20);
複製程式碼

與工廠模式的區別在於:

  • 可以不用顯式地建立物件(原因是被new承包了) ...=new Object()
  • 屬性方法賦給了this物件
  • 可以不return新物件

所以相比工廠模式,使用建構函式建立物件例項更簡潔,高效。

那麼,建構函式是如何將屬性和方法賦給例項物件的呢?
關鍵在於:

2.2、new操作符

對於new操作符,我覺得理解下其執行步驟,應該就清楚了

  • (1) 建立一個新物件
  • (2) 將建構函式的作用域賦給新物件(將this繫結到這個新建立的物件)
  • (3) 執行建構函式中的程式碼(將屬性和方法新增到這個新物件)
  • (4) 返回該物件

補充:模擬一個new操作符的實現(建議瞭解清楚原型之後再回過頭來看)

function myNew(func){
    const objNull={};  //新物件
    if (func.prototype !== null){
        obj.__proto__=func.prototype; 
    }
    const obj=func.apply(res,Array.prototype.slice.call(arguments,1));  //繫結this
    if ((typeof obj === "object" || typeof obj === "function") && obj !==null){
        return obj;
    }
    return objNull;
    
}

複製程式碼

在StackOverflow查閱new的時候看到一個評論戳中笑點...

[寫作中...]Js物件導向(2): 建立物件

2.3、思考:建構函式建立物件例項存在的問題?

簡單來說,建構函式的問題在其物件的方法上。

3、原型模式

3.1、理解原型物件

我們建立的每一個函式都有一個prototype指標,指向一個物件(即原型物件),包含由當前函式派生出的所有例項共享的屬性和方法

當呼叫建構函式建立例項後,例項內部將會包含一個[[prototype]]指標(瀏覽器中的實現是__proto__),指向其建構函式的原型物件prototype

所以簡單總結下,

  • 例項.__proto__=建構函式.prototype
  • 另外ES5中封裝了一個方法,MDN建議使用這種方式來操作
    • Object.getPrototypeOf(例項)==建構函式.prototype
function Person(){...}
const someone=new Person();

someone.__proto__===Person.prototype                            //true
Object.getPrototypeOf(someone)===Person.prototype               //true
複製程式碼

3.2、普通原型模式

function Person(){
    
}
Person.prototype.property1=val1;
Person.prototype.property2=val2;
Person.prototype.funcName=function (){
    console.log(this.property1)
};

const someone = new Person();
someone.fucName()  // 輸出val1

複製程式碼

3.3、內建物件的原型


Object Array Date RegExp FUnction 

基本包裝型別
Boolean Number String

單體內建物件
Global Math
複製程式碼

3.4、思考:原型模式建立物件例項存在的問題?

物件中值為引用型別的屬性會被各例項共享,也就是說在原型模式下,改變一個例項物件的 引用型別屬性值會影響到其他所有例項物件。

4、組合使用構造韓式和原型模式

更多建立物件例項的方式

動態原型模式

寄生建構函式模式

穩妥建構函式模式

小結

此處應該有個小結,不過還沒想好該寫些什麼。

水平有限,不準確的地方,歡迎指正。

參考:

相關文章