目標
- 理解物件
- 建立物件例項
- 理解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的一些內建物件可以建立物件例項,如Object
、Array
等,也可以自定義建構函式,如:
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
新物件
所以相比工廠模式,使用建構函式建立物件例項更簡潔,高效。
那麼,建構函式是如何將屬性和方法賦給例項物件的呢?
關鍵在於:
new 操作符
- 以及
this
指標、作用域等相關知識點,參考this、apply、call、bind。
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的時候看到一個評論戳中笑點...
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、組合使用構造韓式和原型模式
更多建立物件例項的方式
動態原型模式
寄生建構函式模式
穩妥建構函式模式
小結
此處應該有個小結,不過還沒想好該寫些什麼。
水平有限,不準確的地方,歡迎指正。
參考:
- 《JavaScript高階程式設計》
- 《你不知道的JavaScript》
- MDN文件
- this、apply、call、bind
- 《JavaScript入門》 阮一峰
- 自己畫的前端知識體系思維導圖 | PressOn
- What is the 'new' keyword in JavaScript | stackOverflow