摘要:引言對(duì)于面向?qū)ο螅嘈糯蠹乙欢ú荒吧?chuàng)建對(duì)象面向?qū)ο蟮谝徊绞鞘裁创饎?chuàng)建對(duì)象。構(gòu)造函數(shù)優(yōu)于工廠模式也是在于它可以通過(guò)辨識(shí)出一類的對(duì)象。
引言
對(duì)于面向?qū)ο螅嘈糯蠹乙欢ú荒吧W罱戳艘恍╆P(guān)于es6面向?qū)ο蟮闹R(shí),正好通過(guò)這篇文章把關(guān)于面向?qū)ο蟮臇|西給串起來(lái)分享給大家。
什么是對(duì)象很多人會(huì)鄙視我,說(shuō)你這篇文章是騙騙剛?cè)胄械男∨笥训陌桑裁词菍?duì)象我還能不知道?罵我的吃瓜群眾先冷靜一下,你可能對(duì)對(duì)象一無(wú)所知。
{ name: "李小花", sayname () { console.log(this.name) } }
這是我們最常見的對(duì)象,這個(gè)對(duì)象是通過(guò)對(duì)象字面量形式創(chuàng)建的。
屬性類型對(duì)象的含義是無(wú)序的集合,其屬性可以包含基本值、對(duì)象或者函數(shù)。
js中有兩種內(nèi)置的屬性,數(shù)據(jù)屬性和訪問(wèn)器屬性,這兩個(gè)屬性是只有內(nèi)部才能訪問(wèn)的屬性,所以這些屬性都放在了兩對(duì)方括號(hào)中,如[[enumerable]],大家在vue中經(jīng)常
數(shù)據(jù)屬性數(shù)據(jù)屬性包含一個(gè)數(shù)據(jù)值的位置。在這個(gè)位置可以讀取和寫入值。數(shù)據(jù)屬性有 4 個(gè)描述其行為的特性。
[[Configurable]]:表示能否通過(guò) delete
刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問(wèn)器屬性。
[[Enumerable]]:表示能否通過(guò) for-in 循環(huán)返回屬性。
[[Writable]]:表示能否修改屬性的值。
[[Value]]:包含這個(gè)屬性的值。讀取屬性值的時(shí)候,從這個(gè)位置讀;寫入屬性值的時(shí)候,把新值保存在這個(gè)位置。這個(gè)特性的默認(rèn)值為
undefined。
現(xiàn)在有一個(gè)對(duì)象通過(guò)字面量創(chuàng)建
var person = { name: "張全蛋" }
[[Configurable]]、[[Enumerable]]、[[Writable]]屬性都會(huì)被設(shè)置為true,[[Value]]被設(shè)置為了‘張全蛋’。如果想修改這幾個(gè)屬性任意一個(gè)值,必須使用大名鼎鼎的Object.defineProperty()方法,為啥說(shuō)它大名鼎鼎,因?yàn)槿绻憬佑|過(guò)vue,就知道他核型就是通過(guò)這個(gè)方法實(shí)現(xiàn)的。
var person = {}; Object.defineProperty(person, "name", { writable: false, value: "張全蛋" }) Object {name: "張全蛋"}
現(xiàn)在的name屬性是只讀的,如果是嚴(yán)格模式的話,
這樣做還會(huì)報(bào)錯(cuò)。同樣的也適用于其他屬性,我這里就不一一演示了。
注意??,Object.defineProperty()方法只有現(xiàn)代瀏覽器才支持,IE8只是部分實(shí)現(xiàn)。
訪問(wèn)器屬性訪問(wèn)器屬性不包含數(shù)據(jù)值,它們包含一對(duì) getter 和 setter 函數(shù)(這兩個(gè)函數(shù)都不是必須的)。在讀取訪問(wèn)器屬性時(shí),會(huì)調(diào)用
getter 函數(shù),這個(gè)函數(shù)負(fù)責(zé)返回有效的值;在寫入訪問(wèn)器屬性時(shí),會(huì)調(diào)用 setter
并傳入新值,這個(gè)函數(shù)負(fù)責(zé)決定如何處理數(shù)據(jù)。訪問(wèn)器屬性有如下 4 個(gè)特性。
[[Configurable]]:表示能否通過(guò) delete 刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為數(shù)據(jù)屬性。
[[Enumerable]]:表示能否通過(guò) for-in 循環(huán)返回屬性。
[[Get]]:在讀取屬性時(shí)調(diào)用的函數(shù)。默認(rèn)值為 undefined。
[[Set]]:在寫入屬性時(shí)調(diào)用的函數(shù)。默認(rèn)值為 undefined。
訪問(wèn)只能通過(guò)bject.defineProperty()方法來(lái)定義。
var book = { _year: 2004, edition: 1 }; Object.defineProperty(book, "year", { get: function() { return this._year; }, set: function(newValue) { if (newValue > 2004) { this._year = newValue; this.edition += newValue - 2004; } } }); book.year = 2005; alert(book.edition); // 2 alert(book.year); // 2005
訪問(wèn)器屬性 year 則包含一個(gè) getter 函數(shù)和一個(gè) setter 函數(shù)。getter 函數(shù)返回 _year 的值,setter 函數(shù)通過(guò)計(jì)算來(lái)確定正確的版本。因此,把 year 屬性修改為 2005 會(huì)導(dǎo)致 _year 變成 2005,而 edition 變?yōu)?2。這是使用訪問(wèn)器屬性的常見方式,即設(shè)置一個(gè)屬性的值會(huì)導(dǎo)致其他屬性發(fā)生變化。
注意??,訪問(wèn)器屬性只有IE9以上才支持,這就是為什么VUE只能支持到IE9的原因。
創(chuàng)建對(duì)象js面向?qū)ο蟮谝徊绞鞘裁矗看穑簞?chuàng)建對(duì)象。創(chuàng)建對(duì)象有很多中方式,我們最常用的是對(duì)象字面量來(lái)創(chuàng)建對(duì)象,var obj = {},你看我這不就創(chuàng)建了一個(gè)對(duì)象了嗎,我還干嘛要繼續(xù)了解那些奇葩的方法呢?這么想的人活該單身,多掌握些找對(duì)象只有好處沒有壞處哈。正經(jīng)的,高階上有這么一句話,使用對(duì)象字面量創(chuàng)建單個(gè)對(duì)象,有個(gè)明顯的缺點(diǎn),使用同一個(gè)接口創(chuàng)建很多對(duì)象,會(huì)產(chǎn)生大量重復(fù)的代碼。為了解決這個(gè)問(wèn)題,我們需要了解下面?這些方式。
工廠模式工廠模式很簡(jiǎn)單,貼上一段代碼。
function createPerson (name, age, job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function () { alert(this.name) } return o; } var person1 = createPerson("鐵蛋", 20, "工頭") var person2 = createPerson("李四", 30, "挖掘機(jī)駕駛員")
工廠模式的優(yōu)點(diǎn)不必多說(shuō),如果我想創(chuàng)建兩個(gè)對(duì)象,上面同樣有name、age、job屬性,這樣就省去了創(chuàng)建包含同樣屬性多個(gè)對(duì)象的麻煩,但是卻沒有解決對(duì)象識(shí)別的問(wèn)題。
有人會(huì)問(wèn),對(duì)象識(shí)別是什么鬼。我們創(chuàng)建對(duì)象是為了模仿類的概念,這里的person1,person2應(yīng)該都屬于“人”一類,但是顯然我們現(xiàn)在沒辦法將他們歸為一類,所以這個(gè)時(shí)候逼格更高的方法出現(xiàn)了。
function Person (name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function () { alert(this.name) } } var person1 = new Person("鐵蛋", 20, "工頭") var person2 = new Person("李四", 30, "挖掘機(jī)駕駛員")
這里有個(gè)顯然很突出的地方,就是這個(gè)Person的P是大寫的,其實(shí)大寫不是必須的,據(jù)說(shuō)這種習(xí)慣是很多后端程序員轉(zhuǎn)前端帶過(guò)來(lái)的。構(gòu)造函數(shù)模式跟工廠模式不一樣的地方還在于,沒有用new Object顯式地創(chuàng)建對(duì)象,同樣沒有return語(yǔ)句。
那我們?cè)趎ew完一個(gè)構(gòu)造函數(shù),實(shí)則產(chǎn)生一個(gè)實(shí)例,我們new一個(gè)構(gòu)造函數(shù),會(huì)經(jīng)歷以下神奇的四步。
創(chuàng)建對(duì)象 將this指向這個(gè)新對(duì)象 為這個(gè)對(duì)象添加屬性 返回這個(gè)對(duì)象
person1、person2 是我們通過(guò) new Person這個(gè)構(gòu)造函數(shù)得到的,所以這兩個(gè)的構(gòu)造函數(shù)都是Person,constructor(構(gòu)造函數(shù))屬性就都是Person,我以前一直都不能理解constructor是什么東西,現(xiàn)在才理解原來(lái)constructor的中文翻譯就是構(gòu)造函數(shù)?,也難怪我英文最熟的一句就是"hello kugou"了。我們可以通過(guò)使用instanceof操作符來(lái)檢測(cè)對(duì)象的類型。
let arr = new Array(2) arr instanceof Array // true arr instanceof Object // true
構(gòu)造函數(shù)優(yōu)于工廠模式也是在于它可以通過(guò)instanceof辨識(shí)出一類的對(duì)象。
接下來(lái)大家看一段一般沒品的面試官會(huì)考的問(wèn)題
this.name = "張全蛋" function Person (name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function () { alert(this.name) } } var person1 = new Person("鐵蛋", 20, "工頭") var person2 = Person("李小花", 30, "廠花") person1.sayName() // 鐵蛋 person2.sayName() // 報(bào)錯(cuò)
我們首先要確定一個(gè)概念,構(gòu)造函數(shù)也是函數(shù),如果不用new 的方式來(lái)調(diào)用它,它跟普通函數(shù)沒有半毛錢的區(qū)別,我們知道在函數(shù)的作用域是window,所以this指向的是window,所以這段代碼person2對(duì)象this就是window,window沒有sayName屬性,所以會(huì)報(bào)錯(cuò)。如果通過(guò)的是new方式調(diào)用的話,我們上面也講了,為將this賦值給這個(gè)對(duì)象,所以this就是person1這個(gè)實(shí)例。那么構(gòu)造函數(shù)是不是沒有缺點(diǎn)呢?顯然是不對(duì)的,因?yàn)槲乙呀?jīng)這么問(wèn)了。構(gòu)造函數(shù)的缺點(diǎn),每個(gè)方法都要在實(shí)例上重新創(chuàng)建一遍,js中函數(shù)也是對(duì)象,定義函數(shù)就是實(shí)例化對(duì)象
function Person (name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = new Function () { alert(this.name) } }
每次new一個(gè)function就會(huì)多一次標(biāo)識(shí)符解析,標(biāo)識(shí)符(通常指命名)的解析是有代價(jià)的,實(shí)際上沒有那種計(jì)算機(jī)操作可以不產(chǎn)生性能開銷。在執(zhí)行環(huán)境的作用域鏈(扯到作用域鏈就一定會(huì)扯到閉包問(wèn)題,以后有空再仔細(xì)聊聊閉包)中,一個(gè)標(biāo)識(shí)符所在的位置越深,它的讀寫速度也就越慢。也就是說(shuō)函數(shù)中讀寫局部變量總是最快的,而讀寫全局變量總是最慢的。因?yàn)槿肿兞靠偸窃趫?zhí)行環(huán)境作用域的末端。其實(shí)我們可以將函數(shù)移出來(lái)當(dāng)全局函數(shù)來(lái)處理,但那樣會(huì)造成全局函數(shù)污染,這里就不多做介紹。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/83013.html
摘要:還有一個(gè)問(wèn)題,就是不能在創(chuàng)建子類性時(shí),像父類型的構(gòu)造函數(shù)傳遞參數(shù)。組合繼承將原型鏈和借用構(gòu)造函數(shù)組合到一起,發(fā)揮兩者之長(zhǎng)的一張繼承模式,下面來(lái)看個(gè)例子。組合繼承最大的問(wèn)題是無(wú)論在什么情況下,都會(huì)調(diào)用兩次父類型構(gòu)造函數(shù)。 繼承 繼承是面向?qū)ο笳Z(yǔ)言中特別重要的概念,js的繼承主要是靠原型鏈實(shí)現(xiàn)的。 原型鏈!!! 看到我給標(biāo)題打了三個(gè)嘆號(hào)嗎,這里真的很重要!這里真的很重要!這里真的很重要!j...
摘要:我們通過(guò)這個(gè)構(gòu)造函數(shù)為原型對(duì)象添加其他方法和屬性。這個(gè)屬性存在與實(shí)例與構(gòu)造函數(shù)的原型對(duì)象上直接,而不存在于實(shí)例與構(gòu)造函數(shù)之間。李小花班花張全蛋張全蛋李小花李小花我們?cè)诒闅v對(duì)象的的屬性的時(shí)候,經(jīng)常需要判斷屬性是否來(lái)自于對(duì)象的原型還是屬性。 引言 上面說(shuō)了創(chuàng)建對(duì)象有字面量方式和工廠模式還有構(gòu)造函數(shù)模式,結(jié)果發(fā)現(xiàn)他們都各自有缺點(diǎn),所以下面再給大家介紹幾種創(chuàng)建對(duì)象的方式,爭(zhēng)取能找到一種無(wú)痛的模...
摘要:會(huì)造成內(nèi)存浪費(fèi)的問(wèn)題構(gòu)造函數(shù)繼承聲明父類聲明子類生成實(shí)例組合式繼承組合式繼承是汲取了兩者的優(yōu)點(diǎn),既避免了內(nèi)存浪費(fèi),又使得每個(gè)實(shí)例化的子類互不影響。 寫在前面 既然是淺談,就不會(huì)從原理上深度分析,只是幫助我們更好地理解... 面向?qū)ο笈c面向過(guò)程 面向?qū)ο蠛兔嫦蜻^(guò)程是兩種不同的編程思想,剛開始接觸編程的時(shí)候,我們大都是從面向過(guò)程起步的,畢竟像我一樣,大家接觸的第一門計(jì)算機(jī)語(yǔ)言大概率都是C語(yǔ)...
摘要:不必在構(gòu)造函數(shù)中定義對(duì)象實(shí)例的信息。其次,按照一切事物皆對(duì)象的這餓極本的面向?qū)ο蟮姆▌t來(lái)說(shuō),類本身并不是一個(gè)對(duì)象,然而原型方式的構(gòu)造函數(shù)和原型本身也是個(gè)對(duì)象。第二個(gè)問(wèn)題就是在創(chuàng)建子類型的實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù)。 前言 對(duì)象(Object)應(yīng)該算是js中最為重要的部分,也是js中非常難懂晦澀的一部分。更是面試以及框架設(shè)計(jì)中各出沒。寫這篇文章,主要參考與JavaScrip...
閱讀 3764·2023-04-25 20:00
閱讀 3117·2021-09-22 15:09
閱讀 512·2021-08-25 09:40
閱讀 3421·2021-07-26 23:38
閱讀 2210·2019-08-30 15:53
閱讀 1100·2019-08-30 13:46
閱讀 2794·2019-08-29 16:44
閱讀 2050·2019-08-29 15:32