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