摘要:一創(chuàng)建一個(gè)對(duì)象起因用或?qū)ο笞置媪縿?chuàng)建對(duì)象會(huì)產(chǎn)生大量的重復(fù)代碼而且只能通過變量名來區(qū)分不同的對(duì)象沒有記錄對(duì)象的類型例如創(chuàng)建對(duì)象字面量創(chuàng)建對(duì)象工廠模式創(chuàng)建對(duì)象工廠模式解決了相似代碼重復(fù)書寫的問題好處中無法創(chuàng)建類為了模仿類的創(chuàng)建方式抽象具體對(duì)象的
一.創(chuàng)建一個(gè)對(duì)象
起因.................
用Object或?qū)ο笞置媪縿?chuàng)建對(duì)象會(huì)產(chǎn)生大量的重復(fù)代碼,而且只能通過變量名來區(qū)分不同的對(duì)象,沒有記錄對(duì)象的類型
例如:
//Object創(chuàng)建對(duì)象 var student = new Object(); student.name = "s"; student.age = "20"; var student1 = new Object(); student1.name = "s1"; student.age = "20"; //字面量創(chuàng)建對(duì)象 var student = { name: "s", age: "23" } var student1 = { name: "s", age: "23" }1.工廠模式創(chuàng)建對(duì)象
工廠模式解決了相似代碼重復(fù)書寫的問題
//好處:js中無法創(chuàng)建類,為了模仿類的創(chuàng)建方式,抽象具體對(duì)象的創(chuàng)建過程; //缺點(diǎn):工廠模式創(chuàng)建的對(duì)象是通過普通函數(shù)調(diào)用實(shí)現(xiàn)的,沒有解決標(biāo)識(shí)對(duì)象類型的問題,無法區(qū)分對(duì)象的類型, function person(name) { var o = new Object(); o.name = name; o.sayName = function() { console.log(this.name) } return o; } var p1 = person("a"); var p2 = person("b");2.構(gòu)造函數(shù)模式創(chuàng)建對(duì)象
function Person(name) { this.name = name; this.sayName = function() { console.log(this.name); } //function() { console.log(this.name);}相當(dāng)于new Function(){console.log(this.name);}} var a = new Person("ww"); a.sayName(); console.log(a)
new 一個(gè)實(shí)例的過程:
(1)先創(chuàng)建一個(gè)對(duì)象
(2)將構(gòu)造函數(shù)的作用域賦給新對(duì)象
(3),執(zhí)行構(gòu)造函數(shù)中的代碼
(4)返回新對(duì)象
構(gòu)造函數(shù)模式解決了標(biāo)識(shí)構(gòu)造函數(shù)類型的問題,但是構(gòu)造函數(shù)內(nèi)部每定義一個(gè)函數(shù)就會(huì)實(shí)例化一個(gè)對(duì)象,可以通過將公用的方法提到全局環(huán)境下,通過普通函數(shù)調(diào)用的方式實(shí)現(xiàn)調(diào)用函數(shù),避免了重復(fù)實(shí)例化對(duì)象的問題
function Person(name) { this.name = name; this.sayName = sayName; } function sayName() { console.log(this.name) } var a = new Person("p1"); var b = new Person("p2"); a.sayName(); b.sayName();
如果Person內(nèi)部封裝較多的函數(shù),會(huì)導(dǎo)致定義大量的全局函數(shù),這些函數(shù)散亂分布在全局環(huán)境中,失去了封裝性.為了解決這個(gè)問題,可以用原型模式創(chuàng)建對(duì)象
3.原型模式原型模式創(chuàng)建對(duì)象,把屬性和函數(shù)添加到對(duì)象的prototype上,實(shí)例化一個(gè)對(duì)象p1,p1可以通過原型鏈訪問到原型鏈上的對(duì)象
function Person() {} Person.prototype.name = "ww"; Person.prototype.sayName = function() { console.log(this.name); } var p1 = new Person(); p1.sayName();
(1)原型模式的另一種方式:
這種方式會(huì)導(dǎo)致,Person.prototype上原本指向Person的constructor丟失,可以手動(dòng)添加constructor屬性,如下
(2)如果先創(chuàng)建實(shí)例,再定義Person.prototyp的值會(huì)報(bào)錯(cuò),p1還是通過[[prototype]]隱式屬性指向Person沒修改過的原型,導(dǎo)致找不到sayName方法
解釋如js高級(jí)程序設(shè)計(jì)一書中的例子:
(3)原型鏈模式存在以下問題:(1),prototype上的屬性和方法共享,一個(gè)對(duì)象對(duì)prototype屬性的修改會(huì)影響另一個(gè)對(duì)象的屬性;(2)不能傳遞參數(shù)
4.組合使用構(gòu)造函數(shù)和原型函數(shù)我們可以把一些共享的屬性和方法添加到prototype,再利用構(gòu)造函數(shù)在實(shí)例對(duì)象上添加不同屬性
二.繼承 1.原型鏈繼承通過將一個(gè)構(gòu)造函數(shù)的原型重新賦值(另一個(gè)構(gòu)造函數(shù)的實(shí)例)實(shí)現(xiàn)繼承
例子:
function SuperType() { this.property = ["p1"]; } SuperType.prototype.getValue = function() { console.log(this.property); } function SubType() { this.subproperty = ["1"]; } SubType.prototype.getSubValue = function() { console.log("getSubVlue", this.subproperty); } SubType.prototype = new SuperType(); var a = new SubType(); console.log("a", a);
結(jié)果:
對(duì)于引用類型屬性,原型鏈繼承會(huì)將該屬性作為公共屬性,誰都可以對(duì)它的值進(jìn)行修改;對(duì)于像name這樣的非引用類型,每創(chuàng)建一個(gè)實(shí)例就會(huì)定義一個(gè)新額屬性,不會(huì)和其他實(shí)例中的屬性共享,如下所示
2.借用構(gòu)造函數(shù)為了解決引用類型值共享的問題和原型鏈繼承不能傳遞參數(shù)的缺陷,可以在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù)。如下:
function SuperType() { this.property = ["p1"]; } function SubType() { this.subproperty = ["1"]; SuperType.call(this); } SubType.prototype = new SuperType(); var a = new SubType(); var b = new SubType(); a.property.push("2"); console.log(a.property, b.property);
利用單純的借用構(gòu)造函數(shù)解決了引用類型值共享的問題,但是如果大量的函數(shù)寫著超類中,函數(shù)無法復(fù)用,所有需要結(jié)合原型構(gòu)造函數(shù).
3.組合構(gòu)造函數(shù)組合構(gòu)造函數(shù)到的思路是將利用構(gòu)造函數(shù)實(shí)例實(shí)現(xiàn)對(duì)屬性的繼承,利用原型鏈來實(shí)現(xiàn)對(duì)原型對(duì)象的屬性和函數(shù)的繼承.
由于給SubType.prototype直接賦值為SuperType的實(shí)例,導(dǎo)致constructor丟失,利用Object.defineProperty找回
4.原型式繼承思路:基于已有的對(duì)象創(chuàng)建新對(duì)象,繼承一個(gè)現(xiàn)成的對(duì)象
原型式繼承存在的問題就和原型模式一樣,對(duì)于引用型屬性有共享的特性
思路:創(chuàng)建一個(gè)僅用于封裝繼承過程的函數(shù)
該繼承方式存在的問題是a對(duì)象內(nèi)部的函數(shù)不能復(fù)用
6.寄生組合繼承組合構(gòu)造函數(shù)也有缺陷,需要調(diào)用兩次超類構(gòu)造函數(shù),降低效率
function SuperType(name) { this.name = name; this.books = ["b1"] } SuperType.prototype.getName = function() { console.log(this.name); } function SubType(name, age) { this.age = age; SuperType.call(this, name); //第二次調(diào)用構(gòu)造函數(shù) } SubType.prototype = new SuperType(); //第一次調(diào)用構(gòu)造函數(shù) SubType.prototype.constructor = SubType; SubType.prototype.getSubValue = function() { console.log("getSubVlue", this.age); }
利用寄生式繼承來繼承超類的原型,利用構(gòu)造函數(shù)繼承實(shí)例屬性
有不對(duì)或者表達(dá)不準(zhǔn)確的地方歡迎指出!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/102798.html
摘要:創(chuàng)建實(shí)例的方式有三種對(duì)象字面量表示法操作符跟構(gòu)造函數(shù)中的函數(shù)。下面主要講的是最為復(fù)雜的操作符跟構(gòu)造函數(shù)的創(chuàng)建對(duì)象實(shí)例的方法。 創(chuàng)建對(duì)象 一.創(chuàng)建對(duì)象的方法 理解原型對(duì)象: 無論什么時(shí)候,只要?jiǎng)?chuàng)建了新函數(shù),就會(huì)根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個(gè) prototype屬性,這個(gè)屬性指向函數(shù)的原型對(duì)象。在默認(rèn)情況下,所有原型對(duì)象都會(huì)自動(dòng)獲得一個(gè)constructor屬性,這個(gè)屬性包含一個(gè)指向p...
摘要:創(chuàng)建自定義的構(gòu)造函數(shù)之后,其原型對(duì)象只會(huì)取得屬性,其他方法都是從繼承來的。優(yōu)缺點(diǎn)寄生式繼承在主要考慮對(duì)象而不是創(chuàng)建自定義類型和構(gòu)造函數(shù)時(shí),是十分有用的。 原文鏈接:https://kongchenglc.coding.me... 1.原型鏈 ??js的繼承機(jī)制不同于傳統(tǒng)的面向?qū)ο笳Z言,采用原型鏈實(shí)現(xiàn)繼承,基本思想是利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法。理解原型鏈必須先理...
摘要:寄生式繼承的思路與寄生構(gòu)造函數(shù)和工廠模式類似,即創(chuàng)建一個(gè)僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部已某種方式來增強(qiáng)對(duì)象,最后再像真的是它做了所有工作一樣返回對(duì)象。 這篇本來應(yīng)該是作為寫JS 面向?qū)ο蟮那白?,只是作為《javascript高級(jí)程序設(shè)計(jì)》繼承一章的筆記 原型鏈 code 實(shí)現(xiàn) function SuperType() { this.colors = [red,blu...
摘要:可以通過構(gòu)造函數(shù)和原型的方式模擬實(shí)現(xiàn)類的功能。原型式繼承與類式繼承類式繼承是在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型的構(gòu)造函數(shù)。寄生式繼承這種繼承方式是把原型式工廠模式結(jié)合起來,目的是為了封裝創(chuàng)建的過程。 js繼承的概念 js里常用的如下兩種繼承方式: 原型鏈繼承(對(duì)象間的繼承) 類式繼承(構(gòu)造函數(shù)間的繼承) 由于js不像java那樣是真正面向?qū)ο蟮恼Z言,js是基于對(duì)象的,它沒有類的概念。...
摘要:在節(jié)中,我們學(xué)習(xí)到了通過構(gòu)造函數(shù)創(chuàng)建對(duì)象的三個(gè)重要步驟,其中的一步是把構(gòu)造函數(shù)的對(duì)象設(shè)置為創(chuàng)建對(duì)象的原型。利用而不是直接用創(chuàng)建一個(gè)實(shí)例對(duì)象的目的是,減少一次調(diào)用父構(gòu)造函數(shù)的執(zhí)行。 JavaScript語言不像面向?qū)ο蟮木幊陶Z言中有類的概念,所以也就沒有類之間直接的繼承,JavaScript中只有對(duì)象,使用函數(shù)模擬類,基于對(duì)象之間的原型鏈來實(shí)現(xiàn)繼承關(guān)系,ES6的語法中新增了class關(guān)鍵...
閱讀 2906·2021-10-14 09:42
閱讀 3205·2019-08-30 15:52
閱讀 3333·2019-08-30 14:02
閱讀 1132·2019-08-29 15:42
閱讀 562·2019-08-29 13:20
閱讀 1186·2019-08-29 12:24
閱讀 508·2019-08-26 10:20
閱讀 707·2019-08-23 18:31