摘要:而原型對象都會獲得一個構造函數(shù)屬性,這是一個指向?qū)傩运诤瘮?shù)的指針。所以組合使用構造函數(shù)模式和原型模式簡單來說就是構造函數(shù)里面定義實例屬性,原型模式定義共享屬性。
一、創(chuàng)建對象
創(chuàng)建對象的發(fā)展史:
最早
var person = new Object() person.name = "Green"
對象字面量
var person = { name = "Green", age = "25", sayName: function(){ alert("this.name") } }
以上兩種都會有大量重復性的代碼,于是乎:
工廠模式
function createPerson(name, age, job){ var o = new Object(); // 這個叫做顯式的創(chuàng)造對象 o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert("this.name") }; return o; } var example = createPerson("Green",25,"無業(yè)!");
雖然解決了重復代碼問題,但沒有解決對象識別(工廠模式無從識別對象的類型,因為全部都是Object,不像Date、Array等,本例中,得到的都是o對象,對象的類型都是Object,因此出現(xiàn)了構造函數(shù)模式)
構造函數(shù)模式
function Person(name,age,family) { this.name = name; this.age = age; this.family = family; this.say = function(){ alert(this.name); } } var person1 = new Person("lisi",21,["lida","lier","wangwu"]); var person2 = new Person("lisi",21,["lida","lier","lisi"]); /* 這是在創(chuàng)建Person的實例,必須用到new - 創(chuàng)建一個新對象 - 將構造函數(shù)的作用域賦過去(this指向新對象) - 執(zhí)行構造函數(shù)的代碼 - 返回新對象 */ console.log(person1 instanceof Object); //true console.log(person1 instanceof Person); //true
算是構造函數(shù)的特點?
。沒有顯式的創(chuàng)建對象(拗口)
。將屬性方法賦給了this對象
。沒有return
instanceof: 識別對象類型
在全局作用域中調(diào)用一個函數(shù)時,this永遠指向window (踩坑了~)
構造函數(shù)模式內(nèi)的方法每次都會在實例上重建一遍,里面的方法在做同一件事,但是實例化后卻產(chǎn)生了不同的對象,方法是函數(shù) ,函數(shù)也是對象。但如果相同的方法都寫在全局作用域里,會產(chǎn)生很多全局函數(shù),失去了這個引用類型的封裝性。所以就產(chǎn)生了:
原型模式
function Person() { } Person.prototype.name = "lisi"; Person.prototype.age = 21; Person.prototype.family = ["lida","lier","wangwu"]; Person.prototype.say = function(){ alert(this.name); }; console.log(Person.prototype); //Object{name: "lisi", age: 21, family: Array[3]} var person1 = new Person(); //創(chuàng)建一個實例person1 console.log(person1.name); //lisi var person2 = new Person(); //創(chuàng)建實例person2 person2.name = "wangwu"; person2.family = ["lida","lier","lisi"]; console.log(person2); //Person {name: "wangwu", family: Array[3]} // console.log(person2.prototype.name); //報錯 console.log(person2.age); //21
~ 每個函數(shù)有一個prototype屬性,指向一個對象(該函數(shù)的原型對象),用途是包含了一些屬性和方法等信息,可以被一些由調(diào)用該函數(shù)創(chuàng)建的實例所共享。這些信息不必定義在構造函數(shù)內(nèi),只要添加到原型對象上即可。
~ 而原型對象都會獲得一個constructor(構造函數(shù))屬性,這是一個指向prototype屬性所在函數(shù)的指針。(prototype和constructor屬性在函數(shù)與原型之間互相指)
~ 而創(chuàng)建出的實例內(nèi)部,又有一個指針,指向原型對象(和構造函數(shù)里的prototype指的一樣,其實實例與構造函數(shù)無關,與他的原型有關),是你嗎__proto__?
檢測屬性
使用 hasOwnProperty() 方法可以檢測一個屬性是存在于實例還是他的原型中。給定屬性存在于實例中會返回true。
in操作符:多帶帶使用時,無論屬性存在于哪里,只要有就是true
for-in循環(huán)使用時,返回所有能夠通過對象訪問的可枚舉屬性,實例和原型的都包括。入所需要取得對象上所有可枚舉的實例屬性,推薦Object.key()方法。【深拷貝用過】
原型模式的優(yōu)點是共享,缺點也是共享(過度)。比如兩個實例由調(diào)用同一個構造函數(shù)得來,其中一個實例修改了原型對象上屬性值 ,另一個實例也會共享這個修改。所以:
組合使用構造函數(shù)模式和原型模式
簡單來說就是構造函數(shù)里面定義實例屬性,原型模式定義共享屬性。
原型鏈簡單描述,就是將一個構造函數(shù)的實例賦值給另一個構造函數(shù)的原型對象。層層套在一起成為一個鏈條。是實現(xiàn)繼承的方法。
原型鏈的繼承仍然存在共享過度的問題,除此之外子類型實例不能給超類型傳遞參數(shù)。于是我們就要用到:
借用構造函數(shù)
基本思想: 在子類型構造函數(shù)內(nèi)部調(diào)用超類型構造函數(shù)(通過call apply方法)
但是這樣方法又必須全定義在構造函數(shù)里,又不能復用了。于是就又有了:
組合繼承
基本思想:使用原型鏈實現(xiàn)對原型屬性和方法的繼承,通過借用構造函數(shù)來實現(xiàn)對實例屬性的繼承。這樣既通過在原型上定義方法實現(xiàn)了函數(shù)的復用,又能夠保證每個函數(shù)都有自己的屬性。
function SuperType(name) { this.name = name this.color = ["red", "blue"] } SuperType.prototype.getName = function() { console.log(this.name) } function SubType(name, age) { SuperType.call(this, name) // 繼承屬性 this.age = age } SubType.prototype.getAge = function() { console.log(this.age) } SubType.prototype = new SuperType() // 繼承方法 SubType.prototype.constructor = SubType var instance1 = new SubType("zhangsan", 18) instance1.colors.push("black") console.log(instance1.colors) // "red", "blue", "black" console.log(instance1.getName) // "zhangsan" console.log(instance1.getAge) // 18 var instance2 = new SubType("lisi", 20) console.log(instance2.colors) // "red", "blue" console.log(instance2.getName) // "lisi" console.log(instance2.getAge) // 20屬性類型 1、數(shù)據(jù)屬性
有四個描述特性:
configurable 能否刪除屬性 (*置為false后就無法再改變)
enumerable 能否通過for-in循環(huán)返回屬性
writable 能否修改屬性值
value 從這里讀取或者寫入屬性值
前三項默認值都為true,如果需要修改,需要調(diào)用大名鼎鼎的Object.defineProperty()方法
var person = {} Object.defineProperty(person,"name",{ // 三個參數(shù) writable: false, // 這里如果不指定都默認為false value: "Green" }) alert(person.name); // Green person.name = "Blue" alert(person.name); // Green2、訪問器屬性
包含一對getter(讀取訪問器屬性時調(diào)用)和setter(寫入訪問器屬性時調(diào)用)函數(shù)
有四個描述特性:
configurable 一樣
enumerable 一樣
get 讀取屬性時調(diào)用的函數(shù)
set 寫入屬性時調(diào)用的函數(shù)
仍需調(diào)用Object.defineProperty()方法來定義
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
這是使用訪問器屬性的常見方式,即設置一個屬性的值會導致其他屬性發(fā)生變化。
*_year的下劃線表示只能通過對象方法訪問(不懂,等我再查查)
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/103763.html
摘要:深入之繼承的多種方式和優(yōu)缺點深入系列第十五篇,講解各種繼承方式和優(yōu)缺點。對于解釋型語言例如來說,通過詞法分析語法分析語法樹,就可以開始解釋執(zhí)行了。 JavaScript深入之繼承的多種方式和優(yōu)缺點 JavaScript深入系列第十五篇,講解JavaScript各種繼承方式和優(yōu)缺點。 寫在前面 本文講解JavaScript各種繼承方式和優(yōu)缺點。 但是注意: 這篇文章更像是筆記,哎,再讓我...
摘要:是完全的面向?qū)ο笳Z言,它們通過類的形式組織函數(shù)和變量,使之不能脫離對象存在。而在基于原型的面向?qū)ο蠓绞街?,對象則是依靠構造器利用原型構造出來的。 JavaScript 函數(shù)式腳本語言特性以及其看似隨意的編寫風格,導致長期以來人們對這一門語言的誤解,即認為 JavaScript 不是一門面向?qū)ο蟮恼Z言,或者只是部分具備一些面向?qū)ο蟮奶卣?。本文將回歸面向?qū)ο蟊疽?,從對語言感悟的角度闡述為什...
摘要:通常有這兩種繼承方式接口繼承和實現(xiàn)繼承。理解繼承的工作是通過調(diào)用函數(shù)實現(xiàn)的,所以是寄生,將繼承工作寄托給別人做,自己只是做增強工作。適用基于某個對象或某些信息來創(chuàng)建對象,而不考慮自定義類型和構造函數(shù)。 一、繼承的概念 繼承,是面向?qū)ο笳Z言的一個重要概念。通常有這兩種繼承方式:接口繼承和實現(xiàn)繼承。接口繼承只繼承方法簽名,而實現(xiàn)繼承則繼承實際的方法。 《JS高程》里提到:由于函數(shù)沒有簽名,...
摘要:一基礎接口的意義百度規(guī)范擴展回調(diào)抽象類的意義我的前端面試經(jīng)歷百度前端掘金博主就讀于電子科技大學,大三狗一枚面試是個漫長的過程,從海投到收獲電話面試,一面二面三面,一個步驟出錯那么后面就宣告終結。 一道常被人輕視的前端 JS 面試題 - 前端 - 掘金 目錄前言第一問第二問變量聲明提升函數(shù)表達式第三問第四問第五問第六問構造函數(shù)的返回值第七問最后前言 年前剛剛離職了,分享下我曾經(jīng)出過的一道...
摘要:創(chuàng)建構造函數(shù)后,其原型對象默認只會取得屬性至于其他的方法都是從繼承來的。上圖展示了構造函數(shù)的原型對象和現(xiàn)有的兩個實例之間的關系。所有原生的引用類型都在其構造函數(shù)的原型上定義了方法。 第6章我一共寫了3篇總結,下面是相關鏈接:讀《javaScript高級程序設計-第6章》之理解對象讀《javaScript高級程序設計-第6章》之繼承 工廠模式 所謂的工廠模式就是,把創(chuàng)建具體對象的過程抽象...
閱讀 4286·2021-09-26 10:11
閱讀 2678·2021-07-28 00:37
閱讀 3231·2019-08-29 15:29
閱讀 1193·2019-08-29 15:23
閱讀 3139·2019-08-26 18:37
閱讀 2474·2019-08-26 10:37
閱讀 606·2019-08-23 17:04
閱讀 2354·2019-08-23 13:44