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