摘要:對(duì)象字面量創(chuàng)建對(duì)象張三學(xué)生這種方式的好處顯而易見,就是解決了之前的缺點(diǎn)。構(gòu)造函數(shù)模式張三學(xué)生李四學(xué)生與之前工廠模式的方法對(duì)比變量名首字母大寫了在函數(shù)內(nèi)沒有顯式的創(chuàng)建及返回對(duì)象而使用了創(chuàng)建時(shí)使用了關(guān)鍵字。
面向?qū)ο笫荍S的重點(diǎn)與難點(diǎn),但也是走向“掌握J(rèn)S”的必經(jīng)之路,有很多的文章或書籍中都對(duì)其進(jìn)行了詳細(xì)的描述,本沒有必要再寫這些,但是對(duì)于學(xué)習(xí)來說,講給別人聽對(duì)自己來說是一種更好的受益方式。我想通過簡潔的語言來描述創(chuàng)建對(duì)象的方法以及這種方法的優(yōu)缺點(diǎn)。
本系列內(nèi)容:
基本創(chuàng)建模式
對(duì)象字面量創(chuàng)建對(duì)象
工廠模式
構(gòu)造函數(shù)模式
更新時(shí)間
2015年12月6日:創(chuàng)建
2017年7月8日:精簡內(nèi)容,修正錯(cuò)誤
創(chuàng)建對(duì)象的方法有許多,各有利弊。知其然,做到會(huì)用;知其所以然,做到為什么用這種方法。才能是真正的掌握。
1.1 基本創(chuàng)建模式var person = new Object(); person.name = "張三"; person.job = "學(xué)生"; person.viewName = function(){ console.log(this.name); }
這是一種最基礎(chǔ)的創(chuàng)建對(duì)象的方法,使用新建Object的方法創(chuàng)建對(duì)象,并且為其添加屬性和方法。
但這種方式有個(gè)不好的地方是重復(fù)使用了多個(gè)person變量,而且沒有任何的封裝性可言,于是就出現(xiàn)了更受開發(fā)人員喜愛的對(duì)象字面量形式。
1.2 對(duì)象字面量創(chuàng)建對(duì)象var person = { name: "張三", job: "學(xué)生", viewName: function(){ console.log(this.name); } }
這種方式的好處顯而易見,就是解決了之前的缺點(diǎn)。
但在實(shí)際需求中,需要?jiǎng)?chuàng)建一批類似的對(duì)象就有些力不從心了。比如一個(gè)小組有六個(gè)成員,我要基于每個(gè)組員進(jìn)行對(duì)象實(shí)例化,那么我要寫6遍以上的代碼,并且為其命名為person1~person6。如果可以像流水線一般創(chuàng)建對(duì)象就好了:給其提供原料(名字和職務(wù)),讓其自動(dòng)創(chuàng)建出組員,使用函數(shù)恰好能做到。
1.3 工廠模式var person = function(name, job){ var o = new Object(); o.name = name; o.job = job; o.viewName = function(){ console.log(this.name); } return o; }; var person1 = person("張三","學(xué)生"); var person2 = person("李四","學(xué)生");
工廠模式利用"創(chuàng)建對(duì)象函數(shù)"形成流水線的模式,使其流程化,將創(chuàng)建的過程都封裝到函數(shù)中,對(duì)外只暴露每個(gè)對(duì)象的特性(通過參數(shù)的形式傳入)。
具體的實(shí)現(xiàn)流程是:在函數(shù)內(nèi)創(chuàng)建了一個(gè)對(duì)象,將傳入的參數(shù)作為對(duì)象的屬性,在最后將其返回。調(diào)用函數(shù),函數(shù)就會(huì)返回?fù)碛刑囟▽傩缘膶?duì)象。
工廠模式流程化了創(chuàng)建對(duì)象的方法,使其創(chuàng)建對(duì)象變得非常簡便,但其中出了一個(gè)問題,既然person1和person2都使用person函數(shù)創(chuàng)建,那么,有什么方法可以證明person1和person2"師出同門"呢?或者用JS的話說是怎樣解決對(duì)象識(shí)別問題,答案是工廠模式不能證明。于是又出現(xiàn)了構(gòu)造函數(shù)模式,用此模式可以確定person1和person2的關(guān)系。
1.4 構(gòu)造函數(shù)模式var Person = function(name, job){ this.name = name; this.job = job; this.viewName = function(){ console.log(this.name); } } var person1 = new Person("張三","學(xué)生"); var person2 = new Person("李四","學(xué)生");
與之前工廠模式的方法對(duì)比:
Person變量名首字母大寫了
在函數(shù)內(nèi)沒有顯式的創(chuàng)建及返回對(duì)象而使用了this
創(chuàng)建時(shí)使用了new關(guān)鍵字。
Person變量首字母大寫是為了區(qū)別普通函數(shù),除此之外,別無它用。既然Person的首字母大寫只是為了讓自己一眼辨別出他是構(gòu)造函數(shù),在功能上是相同的。那么寫成person當(dāng)然可以,只是這樣不推薦(無法區(qū)分普通函數(shù)與構(gòu)造函數(shù))。
使用new操作符必須經(jīng)歷四個(gè)步驟
創(chuàng)建一個(gè)新的對(duì)象
將構(gòu)造函數(shù)的作用域賦值給新對(duì)象
執(zhí)行構(gòu)造函數(shù)的代碼:為其添加屬性和方法
返回新的對(duì)象
使用new操作符創(chuàng)建的對(duì)象都有一個(gè)constructor屬性,該屬性指向構(gòu)造函數(shù)。
person1.constructor == Person; // true person1.constructor === person2.constructor;// true console.log(person1.constructor);// 返回構(gòu)造函數(shù) //function (name, job){ // this.name = name; // this.job = job; // this.viewName = function(){ // console.log(this.name); // } //}
在測試的時(shí)候發(fā)現(xiàn)一個(gè)問題:不使用new關(guān)鍵字創(chuàng)建Object對(duì)象為什么constructor有值?
再回到原來的需求,小組有兩個(gè)人,我要?jiǎng)?chuàng)建兩個(gè)對(duì)象,對(duì)象的名字和職位可能不一樣,但是打印每個(gè)人的名字這個(gè)方法是一樣的。
對(duì)于以上幾種模式創(chuàng)建的對(duì)象。
person1.viewName === person2.viewName;// false
我每次創(chuàng)建一個(gè)對(duì)象,都創(chuàng)建一次viewName,但是每次都不相等(person1.viewName == person2.viewName返回false)。且如果有一天我們想把viewName方法改成return返回name值,我要每個(gè)對(duì)象都改嗎?我們只要把這個(gè)方法做成對(duì)象公用的就好了,我們可以這樣:
var Person = function(name, job){ this.name = name; this.job = job; this.viewName = viewName; } function viewName(){ console.log(this.name); } var person1 = new Person("張三","學(xué)生"); var person2 = new Person("李四","學(xué)生");
但是這又出現(xiàn)了一個(gè)問題,沒有封裝性可言啊,viewName明明是Person的私有方法,但是放在外面,變成了誰都可以調(diào)用,原型函數(shù)模式解決了這個(gè)問題。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/49684.html
摘要:對(duì)象重新認(rèn)識(shí)面向?qū)ο竺嫦驅(qū)ο髲脑O(shè)計(jì)模式上看,對(duì)象是計(jì)算機(jī)抽象現(xiàn)實(shí)世界的一種方式。除了字面式聲明方式之外,允許通過構(gòu)造器創(chuàng)建對(duì)象。每個(gè)構(gòu)造器實(shí)際上是一個(gè)函數(shù)對(duì)象該函數(shù)對(duì)象含有一個(gè)屬性用于實(shí)現(xiàn)基于原型的繼承和共享屬性。 title: JS對(duì)象(1)重新認(rèn)識(shí)面向?qū)ο? date: 2016-10-05 tags: JavaScript 0x00 面向?qū)ο?從設(shè)計(jì)模式上看,對(duì)象是...
摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來。注意中,對(duì)象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來。注意中,對(duì)象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來。注意中,對(duì)象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:是完全的面向?qū)ο笳Z言,它們通過類的形式組織函數(shù)和變量,使之不能脫離對(duì)象存在。而在基于原型的面向?qū)ο蠓绞街?,?duì)象則是依靠構(gòu)造器利用原型構(gòu)造出來的。 JavaScript 函數(shù)式腳本語言特性以及其看似隨意的編寫風(fēng)格,導(dǎo)致長期以來人們對(duì)這一門語言的誤解,即認(rèn)為 JavaScript 不是一門面向?qū)ο蟮恼Z言,或者只是部分具備一些面向?qū)ο蟮奶卣?。本文將回歸面向?qū)ο蟊疽?,從?duì)語言感悟的角度闡述為什...
摘要:基于原型的面向?qū)ο笤诨谠偷恼Z言中如并不存在這種區(qū)別它只有對(duì)象不論是構(gòu)造函數(shù),實(shí)例,原型本身都是對(duì)象。允許動(dòng)態(tài)地向單個(gè)的對(duì)象或者整個(gè)對(duì)象集中添加或移除屬性。為了解決以上兩個(gè)問題,提供了構(gòu)造函數(shù)創(chuàng)建對(duì)象的方式。 showImg(https://segmentfault.com/img/remote/1460000013229218); 一. 重新認(rèn)識(shí)面向?qū)ο?1. JavaScript...
閱讀 3347·2021-11-22 14:44
閱讀 1183·2021-11-16 11:53
閱讀 1332·2021-11-12 10:36
閱讀 766·2021-10-14 09:43
閱讀 3779·2019-08-30 15:55
閱讀 3451·2019-08-30 14:14
閱讀 1799·2019-08-26 18:37
閱讀 3472·2019-08-26 12:12