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