摘要:都是構(gòu)造函數(shù)模式創(chuàng)建的原生構(gòu)造函數(shù)。使用構(gòu)造函數(shù)創(chuàng)建對(duì)象經(jīng)歷了以下四個(gè)過(guò)程創(chuàng)建一個(gè)新對(duì)象構(gòu)造函數(shù)的作用域交給新對(duì)象。
??在創(chuàng)建對(duì)象的時(shí)候,使用對(duì)象字面量和 new Object() 構(gòu)造函數(shù)的方式創(chuàng)建一個(gè)對(duì)象是最簡(jiǎn)單最方便的方式。但是凡是處于初級(jí)階段的事物都會(huì)不可避免的存在一個(gè)問(wèn)題,沒(méi)有普適性,意思就是說(shuō)我要為世界上(程序中)的所有使用到的對(duì)象都使用一遍 var xxx = {} ,對(duì)于"懶惰"的程序員來(lái)講是不可以接受的。即便你能接受這種創(chuàng)建的方式,也無(wú)法保證將所有對(duì)象歸類(lèi)這一哲學(xué)問(wèn)題。
??由此,優(yōu)秀的程序員們利用現(xiàn)有的規(guī)則,創(chuàng)造出了一種種優(yōu)秀的解決方案 -- 這些優(yōu)秀的解決方案統(tǒng)稱(chēng)為設(shè)計(jì)模式。
??在 JavaScript 中,設(shè)計(jì)模式由初級(jí)到高級(jí)的區(qū)別是他們的副作用的大小。依次可以分為:
工廠模式
構(gòu)造函數(shù)模式
原型模式
others
??同時(shí),使用設(shè)計(jì)模式也可以優(yōu)雅的解決 JavaScript 在 ES6之前都是沒(méi)有類(lèi)的尷尬問(wèn)題。
工廠模式??工廠模式,顧名思義就是創(chuàng)建對(duì)象的一個(gè)工廠,工廠可以創(chuàng)造一類(lèi)具有相似結(jié)構(gòu)和功能的對(duì)象。這個(gè)模式的誕生也基本解決了:
創(chuàng)建多個(gè)對(duì)象的時(shí)候,需要大量重復(fù)代碼
先看下在這種設(shè)計(jì)模式下,應(yīng)該如何組織我們的代碼:
function createPerson(name, age) { var obj = new Object(); obj.name = name ; obj.age = age; obj.say = function() { console.log(this.name)} return obj; } var p1 = createPerson("ZhangSan", 12); p1.say() //ZhangSan
這種叫工廠模式的設(shè)計(jì)模式:是指使用統(tǒng)一的方法(函數(shù),因?yàn)?Js 沒(méi)有類(lèi))來(lái)描述對(duì)象創(chuàng)建的細(xì)節(jié)
把這個(gè)對(duì)象封裝起來(lái),每次使用類(lèi)似的對(duì)象都使用這個(gè)工廠函數(shù)來(lái)創(chuàng)建。
它抽象了創(chuàng)建一個(gè)對(duì)象的過(guò)程。
當(dāng)然,處于初級(jí)階段的 工廠模式, 一定有它處于初級(jí)階段的道理:
優(yōu)勢(shì):
工廠函數(shù)可以解決創(chuàng)建多個(gè)類(lèi)似功能對(duì)象的問(wèn)題。
缺點(diǎn):
工廠模式無(wú)法解決對(duì)象的識(shí)別問(wèn)題: 不知道對(duì)象是什么類(lèi)型的。
使用工廠函數(shù)創(chuàng)建的對(duì)象,只有開(kāi)發(fā)者是知道它的類(lèi)型的(通過(guò)工廠函數(shù)變量名),但是程序仍然認(rèn)為它是一個(gè)普通的對(duì)象。
每個(gè)對(duì)象都是通過(guò)工廠造就的全新的對(duì)象。
構(gòu)造函數(shù)模式??在 JavaScript 的開(kāi)發(fā)中,經(jīng)常會(huì)聽(tīng)說(shuō)和使用的一個(gè)詞語(yǔ)叫做構(gòu)造函數(shù),這里的構(gòu)造函數(shù)就是出自構(gòu)造函數(shù)模式這一種設(shè)計(jì)模式。在長(zhǎng)時(shí)間的傳承中,文化或者其他的名詞都會(huì)變成一種泛稱(chēng),所以人們常說(shuō)的構(gòu)造函數(shù),有的時(shí)候指的是構(gòu)造函數(shù)模式,有的時(shí)候指的是構(gòu)造函數(shù)模式創(chuàng)造的對(duì)象中的構(gòu)造函數(shù)方法(實(shí)例的 constructor )。
??構(gòu)造函數(shù)是用來(lái)創(chuàng)建特定的類(lèi)型的對(duì)象的。比如Js原生提供的Object, Array。都是構(gòu)造函數(shù)模式創(chuàng)建的原生構(gòu)造函數(shù)。
慣例,看下在這種設(shè)計(jì)模式下,該如何組織代碼:
function Person (name, age) { this.name = name; this.age = age; this.say = function() { console.log(this.age); } } var p1 = new Person("ZhangSan", 12); var p2 = new Person("LiSi", 22); p1.say() // 12 p2.say() // 22
使用構(gòu)建函數(shù)模式和工廠模式創(chuàng)建對(duì)象的區(qū)別:
沒(méi)有明顯的創(chuàng)建對(duì)象的過(guò)程: (new Object()的過(guò)程)
直接將參數(shù)賦值給了 this。(因?yàn)?沒(méi)有創(chuàng)建明顯的對(duì)象,就需要用 this 進(jìn)行賦值)
沒(méi)有 return 。
構(gòu)造函數(shù)的首字母大寫(xiě),這是代碼風(fēng)格上的變化(為了和其他的 OOM 語(yǔ)言的代碼風(fēng)格保持一致)
創(chuàng)建一個(gè)由構(gòu)造函數(shù)創(chuàng)建的對(duì)象,需要使用 new Person() 進(jìn)行創(chuàng)建。
使用構(gòu)造函數(shù)創(chuàng)建對(duì)象經(jīng)歷了以下四個(gè)過(guò)程:
創(chuàng)建一個(gè)新對(duì)象
構(gòu)造函數(shù)的作用域交給新對(duì)象。this指向新對(duì)象
執(zhí)行內(nèi)部代碼,給新對(duì)象增加屬性和方法
返回新對(duì)象
由構(gòu)造函數(shù)創(chuàng)建的對(duì)象稱(chēng)為這個(gè)構(gòu)造函數(shù)的實(shí)例,在實(shí)例中會(huì)存在一個(gè) constructor 屬性,這個(gè)屬性指向創(chuàng)造它的構(gòu)造函數(shù)。(證明自己從哪里來(lái))
p1.constructor == Person; // true p2.constructor == Person; // true
每一個(gè)實(shí)例都是可以被檢測(cè)出來(lái)的,檢測(cè)對(duì)象是否屬于某一個(gè)類(lèi)型,可以使用 instanceof XX。
p1 instanceof Person // true p1 instanceof Object // true
知道了構(gòu)造函數(shù)模式創(chuàng)建實(shí)例的過(guò)程和方法,下面介紹一些使用構(gòu)造函數(shù)方法中,一些不為人知的秘密(高級(jí)知識(shí)點(diǎn)):
使用構(gòu)造函數(shù)的時(shí)候常規(guī)操作是:使用操作符new。但是也可以直接當(dāng)做一個(gè)普通的函數(shù)使用。
// Person 在上個(gè) Demo var p3 = Person("Person3", 33); p3; // undefined; p3.say(); // undefined; Person("Person4", 44); window.say(); // 44;
如果把構(gòu)造函數(shù)當(dāng)做普通函數(shù)使用了,就不能構(gòu)造實(shí)例了,即使構(gòu)造了實(shí)例,也都是 undefined。
直接使用 構(gòu)造函數(shù)當(dāng)做普通函數(shù)使用, 屬性和方法會(huì)被添加到全局中(window/global)。
當(dāng)然也可以使用 call把 this 指向其他對(duì)象。(不了解 call,可以先忽略。call 是改變 this 指針的方式之一)。
??了解了高級(jí)用法之后,細(xì)心的孩子已經(jīng)發(fā)現(xiàn)了構(gòu)造函數(shù)方法作為 Level 2的設(shè)計(jì)模式,一定有哪里不對(duì)。其實(shí)很簡(jiǎn)單,在構(gòu)造函數(shù)創(chuàng)建的過(guò)程中,很好的解決了工廠模式創(chuàng)建對(duì)象不知道類(lèi)型的問(wèn)題(不知道自己從哪里來(lái))。在構(gòu)想上,實(shí)例的屬性和方法應(yīng)該都是唯一指向的,理想情況是都指向構(gòu)造函數(shù)。但是差強(qiáng)人意的地方出現(xiàn)了:
屬性都很好的指向了 構(gòu)造函數(shù)。 this.name = name
方法又自己偷摸的創(chuàng)建了新的對(duì)象(函數(shù)也是對(duì)象)。這就不符合理想的情況了,因?yàn)檫@個(gè)時(shí)候:
p1.say === p2.say // false
原理也很清楚啊:this.say = function() {} 就是 this.say = new Function() 啊。
這個(gè)時(shí)候,一個(gè)構(gòu)造函數(shù)的補(bǔ)救措施出現(xiàn)了:
var Person = function(name, age) { this.name = name; this.age = age; this.say = sayFunc; } var sayFunc = function() { console.log(this.age) }
使用額外的函數(shù),將構(gòu)造函數(shù)內(nèi)的方法指向外部,這樣就保證了實(shí)例方式的相同。
俗話說(shuō)的好,補(bǔ)救措施終究是補(bǔ)救措施:
在構(gòu)造函數(shù)存在大量的方法的時(shí)候,外部會(huì)存在數(shù)量巨多的補(bǔ)救方法。
補(bǔ)救方法在構(gòu)造函數(shù)的外部,毫無(wú)封裝性可言。
外部方法也是一個(gè)普通的函數(shù),也可以被其他方法或構(gòu)造函數(shù)執(zhí)行。
外部方法被添加到 全局(window/global)上,性能浪費(fèi)。如果在 window 上調(diào)用,this 就指向了 window。造成 this 指向混亂(誰(shuí)調(diào)用,this 指向誰(shuí))
所以,構(gòu)造函數(shù)的方法仍然是一個(gè)不完美的方法。但是在開(kāi)發(fā)速度上,構(gòu)造函數(shù)的設(shè)計(jì)模式還是有很大優(yōu)勢(shì)的。
而且當(dāng)你需要你的方法在全局被使用的時(shí)候,構(gòu)造函數(shù)模式是最適合的,這也是 Object, Array原生構(gòu)造函數(shù)出現(xiàn)的原因。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/99004.html
摘要:都是構(gòu)造函數(shù)模式創(chuàng)建的原生構(gòu)造函數(shù)。使用構(gòu)造函數(shù)創(chuàng)建對(duì)象經(jīng)歷了以下四個(gè)過(guò)程創(chuàng)建一個(gè)新對(duì)象構(gòu)造函數(shù)的作用域交給新對(duì)象。 ??在創(chuàng)建對(duì)象的時(shí)候,使用對(duì)象字面量和 new Object() 構(gòu)造函數(shù)的方式創(chuàng)建一個(gè)對(duì)象是最簡(jiǎn)單最方便的方式。但是凡是處于初級(jí)階段的事物都會(huì)不可避免的存在一個(gè)問(wèn)題,沒(méi)有普適性,意思就是說(shuō)我要為世界上(程序中)的所有使用到的對(duì)象都使用一遍 var xxx = {} ,...
摘要:目錄導(dǎo)語(yǔ)理解對(duì)象和面向?qū)ο蟮某绦蛟O(shè)計(jì)創(chuàng)建對(duì)象的方式的繼承機(jī)制原型對(duì)象原型鏈與原型對(duì)象相關(guān)的方法小結(jié)導(dǎo)語(yǔ)前面的系列文章,基本把的核心知識(shí)點(diǎn)的基本語(yǔ)法標(biāo)準(zhǔn)庫(kù)等章節(jié)講解完本章開(kāi)始進(jìn)入核心知識(shí)點(diǎn)的高級(jí)部分面向?qū)ο蟮某绦蛟O(shè)計(jì),這一部分的內(nèi)容將會(huì)對(duì)對(duì)象 目錄 導(dǎo)語(yǔ) 1.理解對(duì)象和面向?qū)ο蟮某绦蛟O(shè)計(jì) 2.創(chuàng)建對(duì)象的方式 3.JavaScript的繼承機(jī)制 3.1 原型對(duì)象 3.2 原型鏈 3.3 與...
摘要:其實(shí)在之前的工廠模式里面,也存在這個(gè)問(wèn)題,不過(guò)工廠模式更徹底,直接完全創(chuàng)建一個(gè)新對(duì)象,而構(gòu)造函數(shù)模式的話只是方法會(huì)被重新創(chuàng)建。 我來(lái)重新學(xué)習(xí) javascript 的面向?qū)ο螅╬art 1) 很多job 的描述都說(shuō)要求精通 javascript 面向?qū)ο缶幊蹋歉鶕?jù)一般的套路,寫(xiě)精通其實(shí)就是熟練,寫(xiě)熟練其實(shí)就是一般,寫(xiě)一般其實(shí)就是懵逼! showImg(https://segment...
摘要:解決了構(gòu)造函數(shù)模式不能共享方法的問(wèn)題。六寄生構(gòu)造模式流程創(chuàng)建一個(gè)構(gòu)造函數(shù),在這個(gè)函數(shù)內(nèi)部創(chuàng)建一個(gè)對(duì)象,用返回對(duì)象。除了使用操作符并把使用的包裝函數(shù)叫做構(gòu)造函數(shù)以外,這個(gè)模式與工程模式其實(shí)是一模一樣的。 JavaScript面向?qū)ο蟾呒?jí)——對(duì)象創(chuàng)建模式 一、工廠模式 流程: 定義一個(gè)函數(shù),函數(shù)返回對(duì)象。 適用場(chǎng)景: 需要?jiǎng)?chuàng)建多個(gè)對(duì)象,都是Object類(lèi)型。 優(yōu)點(diǎn):完成了返回一個(gè)對(duì)象的...
摘要:對(duì)象字面量創(chuàng)建對(duì)象張三學(xué)生這種方式的好處顯而易見(jiàn),就是解決了之前的缺點(diǎn)。構(gòu)造函數(shù)模式張三學(xué)生李四學(xué)生與之前工廠模式的方法對(duì)比變量名首字母大寫(xiě)了在函數(shù)內(nèi)沒(méi)有顯式的創(chuàng)建及返回對(duì)象而使用了創(chuàng)建時(shí)使用了關(guān)鍵字。 面向?qū)ο笫荍S的重點(diǎn)與難點(diǎn),但也是走向掌握J(rèn)S的必經(jīng)之路,有很多的文章或書(shū)籍中都對(duì)其進(jìn)行了詳細(xì)的描述,本沒(méi)有必要再寫(xiě)這些,但是對(duì)于學(xué)習(xí)來(lái)說(shuō),講給別人聽(tīng)對(duì)自己來(lái)說(shuō)是一種更好的受益方式。我...
閱讀 1619·2021-11-11 10:59
閱讀 2624·2021-09-04 16:40
閱讀 3650·2021-09-04 16:40
閱讀 2979·2021-07-30 15:30
閱讀 1615·2021-07-26 22:03
閱讀 3164·2019-08-30 13:20
閱讀 2225·2019-08-29 18:31
閱讀 439·2019-08-29 12:21