摘要:中創建對象的方法最近手頭一個項目剛完成,下一個顯目還在準備中,趁這個空檔期,拿起塵封多年的書,重溫一遍面向對象程序設計,然后就得出下文,算是一個總結吧。
JS中創建對象的方法
最近手頭一個項目剛完成,下一個顯目還在準備中,趁這個空檔期,拿起塵封多年的JS書,
重溫一遍JS面向對象程序設計,然后就得出下文,算是一個總結吧。
也許,你會說 “創建對象不就是一對花括號的事嗎?”,是的,目前我們最常用,
也是最便捷的方式就是所謂的一對花括號的事,也就是我們常說的JSON對象(嚴格意義上,這其實不算JSON對象,具體我們這里不做深入),如下:
let obj = { name:"xiaohong", age: 17, gender: "female" }
這是就是我們常說的對象字面量(Literal)的方法創建對象,應該是目前使用最廣泛的方法了。
這總方法基本上等同與下面(創建Object實例)的方法
let obj = new Object() obj.name = "xiaohong" obj.age = 17 obj.gender: "female"
但是由于 對象字面量的方法,比較簡潔直觀,足以滿足大部分場景下的需求,所以被開發著們廣泛采用,
而Object實例的方式就很少有人問津了。
不過字面量方法也是有缺點的,缺點就是完全沒有復用性可言,如果需要創建多個對象,
就會有很多重復的代碼,比如:
var studentA = { name: "xiaohong" age: 17, gender: "female" } var studentB = { name: "xiaoming" age: 18, gender: "male" } var studentC = { name: "lili" age: 17, gender: "female" }
不難看出,三個對象只有冒號后面的內容不一樣,其他的代碼都是冗余的,那有什么辦法可以避免這個冗余呢?
平常開發中,如果我們碰到一個要重復用到的功能的時候,我們會怎么做?對的,
就是把這個功能封裝成一個函數,然后重復調用:
function Student(name,age,gender){ // 以下代碼還可以用es6這樣寫 return {name,age,gender} // 詳情請參考es6 屬性簡寫 return { name:name, age:age, gender:gender } } // 然后在需要的時候,調用一下這個函數,傳進一些參數即可 var studentA = Student("xiaohong",17,"f") var studentB = Student("xiaoming",18,"m") var studentC = Student("lili",17,"f")
這樣是不是簡潔很多,每次只要調用一下Student這個函數,然后傳進名字,年齡,性別,
就能得到一個你想要的對象了。
這種方法叫 工廠模式 ,是不是真的很像一個加工廠呢? 這種方法對創建多個對象的時候很有用,
不過這種方法也是有缺點的,就是無法知道對象的類型,比如,
我想通過條件語句判斷studentA是不是一個Student對象,就做不到
typeof studentA === "Student" //false studentA instanceof Student // false
由于工廠模式在對象識別的問題上不堪重任,所以我們通常用 構造函數 模式來解決對象識別的問題
function Student(name,age,gender){ this.name = name this.age = age this.gender = gender } // 通過調用構造函數,new一個對象(這個估計是有其他面向對象語言基礎的童鞋對容易接受的一種方式) var studentA = new Student("xiaohong",17,"f") var studentB = new Student("xiaoming",18,"m") var studentC = new Student("lili",17,"f")
構造函數跟工廠模式的很相似,區別主要在以下2點:
沒有返回對象,而是直接把參數賦值給this作用域下的同名變量,因為new的時候,
會把this指向調用new出來的那個實例對象,所以就完成了賦值操作
調用構造函數的時候,在構造函數前面加一個new(
如果沒加new,就當做普通函數使用,作用域會在當前代碼塊的環境下面,函數里面的值會賦給當前作用域)
通過構造函數new出來的對象,我們是能檢測到它的類型的
studentA instanceof Student // true studentA instanceof Object // true
事實上,當我們使用 new 實例化一個構造函數的時候,js其實偷偷的在背后做了4件事,這個也是個比較經典的面試題:
創建一個新對象(prototype 指向構造函數的prototype)
把作用域(this)指給這個對象
執行構造函數的代碼
返回這個對象
然而,構造函數也不是沒有缺點,使用構造函數創建的對象里面都是數據是沒啥問題,
但是如果對象里面有函數(方法)呢?
還是上面那個代碼,我們拿來稍微修改一下,需要給學生增加一個學習的技能:
function Student(name,age,gender){ this.name = name this.age = age this.gender = gender this.study = fucntion() { console.log("我在學習...")} }
這樣咋看起來,也沒啥毛病,調用一些實例的study,也可以打印出“我在學習...”
var studentA = new Student("xiaohong",17,"f") studentA.study() // 我在學習...
但是,如果我們這樣
var studentA = new Student("xiaohong",17,"f") var studentB = new Student("xiaoming",18,"m") studentA.study == studentB.study // false
我們發現,2個實例的study不是指向同一個函數,而是2個不同的函數,但是他們的功能一模一樣
相當于這樣
studentA.study = fucntion() { console.log("我在學習...")} studentB.study = fucntion() { console.log("我在學習...")} studentC.study = fucntion() { console.log("我在學習...")}
這讓強迫癥怎么接受?
事實證明,寫代碼的,大部分都有強迫癥,于是,就有了原型模式
原型模式的原理,就是我不把方法和屬性添加到構造函數里面去,我直接添加到構造函數的原型里面去,
由于原型的共享的,所以我們在這邊就解決了冗余:
function Student(){} // 聲明一個空函數 Student.prototype.name = "xiaohong" Student.prototype.age = 17 Student.prototype.gender = "f" Student.prototype.study = fucntion() { console.log("我在學習...")} var studentA = new Student() var studentB = new Student() studentA.study == studentA.study // true
這樣,就能解決函數重復聲明的問題,所有的實例,都共享原型上的函數study.然而,函數是共享了沒錯,
不過其他數據也共享了,所有實例上都會有相同的name,age,gender,這也不是我們想要的效,這時,
聰明的你肯定會想,把數據放在構造函數里面,只把方法放在原型里面:
function Student(name,age,gender){ this.name = name this.age = age this.gender = gender } Student.prototype.study = fucntion() { console.log("我在學習...")}
這樣把普通的數據放在構造函數里面聲明,把函數(方法)放在原型上聲明的模式,
我們稱之為組合模式(即組合使用構造函數模式和原型模式),組合模式,既有數據的獨立,又有方法的共享
可以說是比較完美的一種對象的創建方式了。ES6的class語法糖實現的原理大體上也是利用組合模式。
以上就是ES5里面創建對象的一些常用模式,當然還有一些不常用的奇葩的模式,比如動態原型模式,
寄生構造函數模式,穩妥構造函數模式...等等,,這里就不一一列舉了,感興趣的童鞋自行百度一下
好了,關于創建對象的話題,就到這里了,感謝收看!
如果覺得對您有用,請給本文的github加個star,萬分感謝,另外,github上還有其他一些關于前端的教程和組件,有興趣的童鞋可以看看,你們的支持就是我最大的動力。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94161.html
摘要:對象字面量的方式今年創建實例的發明者我是今年屬性是可以動態添加,修改的構造函數無參構造函數有參構造函數我叫,今年歲實例化創建對象調用方法由于指針在對象實例的時候發生改變指向新的實例。是我的名字混合方式構造函數原型我是,今年 javascript創建對象簡單的說,無非就是使用內置對象或各種自定義對象,當然還可以用JSON;方法很多,也能混合使用。 對象字面量的方式: var pers...
摘要:構造函數模式定義構造函數模式是語言創建對象的通用方式。但兩種語言用構造函數創建對象的方式略有不同在中沒有類的概念,函數即為一等公民,因此,不必顯式聲明某個類,直接創建構造函數即可,類的方法和屬性在構造函數中或原型對象上處理。 工廠模式 定義:工廠模式非常直觀,將創建對象的過程抽象為一個函數,用函數封裝以特定接口創建對象的細節。通俗地講,工廠模式就是將創建對象的語句放在一個函數里,通...
摘要:在模塊中有個函數,通過可以執行命令及其相關選項,同時提供了創建子進程的一些選項,其中選項則與我們的需求密切相關。在文件中設置了函數,目的是避免父進程等待子進程退出。不同會話的進程無法通過通信,因此父子進程相隔離。 背景 在node工程部署中,常常涉及到三方:本地客戶端、跳板機和服務器(集群)。在通過git觸發gitlab hook腳本后,需要在跳板機中執行相應的ssh命令執行shell...
摘要:中創建對象是如何實現的其實通過上面方式,使用構造函數聲明實例的專屬變量和方法,使用原型聲明公用的實例和方法,已經是創建對象的完美解決方案了。 1. 使用對象字面量創建對象 key-value var cat = { name: tom, info: this.name + : 1212, getName: function() { return...
閱讀 3475·2021-10-13 09:39
閱讀 1458·2021-10-08 10:05
閱讀 2260·2021-09-26 09:56
閱讀 2275·2021-09-03 10:28
閱讀 2673·2019-08-29 18:37
閱讀 2032·2019-08-29 17:07
閱讀 600·2019-08-29 16:23
閱讀 2191·2019-08-29 11:24