摘要:改進方法方法一通過先執行一次的原型重寫寫在創建對象之前輸出方法二提前先執行一次初次運行時,多調用一次輸出中的相當于中的構造函數,如果不寫默認為空,定義在對象自身上面該方法定義在上輸出可以說,用法就是中動態原型模式。
js創建對象有很多方法,以下是常見方法整理。
ES5創建對象 工廠模式function person (name, age, sex) { var O = new Object(); O.name = name; O.age = age; O.sex = sex; O.sayName =function(){ console.log(this.name); } return O; } var per = person("per",10,"male"); //不需要用new,因為有return,就是個普通函數,很好理解 console.log(per instanceof person); //false構造函數模式
function Person (name, age, sex) { this.name = name; this.age = age; this.sex = sex; this.sayName =function(){ console.log(this.name); } } var per =new Person("per",10,"male"); console.log(per instanceof Person); //true
分析創建過程,
var per =new Person("per",10,"male");
在這行代碼執行時,四個步驟:
①出現了一個空的對象
②this指向這個對象
③執行構造函數的代碼
④把這個對象取個名字是per,per的指針就指向這個對象,于是可以通過per操作這個對象
工廠模式定義出的對象,instanceof識別不出是"person類"。
構造函數模式,每次new一個對象,里面的函數都會創建一次,就這個sayName函數,明明共有同一個就可以了。
解決這個問題,出現了原型模式:
function Person () { Person.prototype.name = "p1"; Person.prototype.age = 10; Person.prototype.sex = "female"; Person.prototype.sayName =function(){ console.log(this.name); } }
那么,這些代碼干了什么呢?
①當你創建Person()函數后,就會有一個prototype屬性隨之而來
我們可以看看,這個prototype是什么,執行以下代碼:
console.log(Person.prototype);
_proto_保存繼承自Object的方法。里面只有一個constructor屬性指向Person()函數自身。
②當然我們是要用這個函數的,執行以下代碼:
var per1 =new Person(); var per2 =new Person(); console.log(Person.prototype);
在創建實際對象時候,就會運行構造函數中的代碼,而且per1、per2兩個對象,就會執行兩次構造函數的代碼,但并不會多創建一個Person的prototype屬性,只是重新賦值里面的name、age、sex和sayName變量。
③per1和per2有各自的prototype屬性,指向Person的prototype屬性。可以簡單理解為per1、per2各自的"指針"指向同一個"對象"。
這個原型模式啊,就真的好像單例模式了,每個創建的對象都在操作同一個對象。
最優:動態原型模式function Person (name, age, sex) { this.name = name; this.age = age; this.sex = sex; if(typeof this.sayName != "function"){ Person.prototype.sayName = function(){ console.log(this.name); } Person.prototype.sayAge = function(){ console.log(this.age); } } } var per = new Person("wlq", 19, "man");
這樣的代碼,使得每個對象的name、age、sex都是各自的(不共有),然后函數寫在原型上,就又是共享的,很不錯。還有個地方,if語句的判斷,使得第二次創建對象時候,不會重新給Person.prototype.sayName和Person.prototype.sayAge重賦值。
原型重寫的問題function Person (name, age, sex) { this.name = name; this.age = age; this.sex = sex; if(typeof this.sayName != "function"){ Person.prototype.sayName = function(){ console.log(this.name); } } } function WPerson (name, age, sex) { this.name = name; this.age = age; this.sex = sex; if(typeof this.sayName != "function"){ WPerson.prototype = { //這里進行了原型的重寫 constructor: WPerson, sayName: function(){ console.log(this.name); } } } } var per1 = new Person("w", 19, "man"); var per2 = new WPerson("q", 18, "man"); var per3 = new WPerson("q", 18, "man"); per1.sayName(); //輸出w per2.sayName(); //報錯,說沒有sayName這個方法 per3.sayName(); //輸出q console.log(per2.name); //輸出q原因
重寫原型的發生是在創建對象之后的,per2指向的WPerson的原型上面只有name、age、sex,再創建完per2后,才執行WPerson原型的重寫,per3甚至以后創建的WPerson類型對象就都會有sayName函數了。
改進方法方法一(通過先執行一次WPerson的原型重寫):
function WPerson (name, age, sex) { this.name = name; this.age = age; this.sex = sex; } WPerson.prototype = { //寫在創建對象之前 constructor:WPerson, sayName: function(){ console.log(this.name); } } var per = new WPerson("q", 18, "man"); per.sayName(); //輸出q
方法二(提前先執行一次new):
function WPerson (name, age, sex) { this.name = name; this.age = age; this.sex = sex; if(typeof this.sayName != "function"){ WPerson.prototype = { constructor:WPerson, sayName: function(){ console.log(this.name); } }; return new WPerson(name,age,sex); //初次運行時,多調用一次new } } var per = new WPerson("q", 18, "man"); per.sayName(); //輸出qES6中的class
class Point{ constructor(x, y) { //相當于java中的構造函數,如果不寫默認為空 this.x = x; //x,y定義在對象自身上面 this.y = y; } add() { //該方法定義在Point.prototype上 console.log(this.x + this.y); } } var p = new Point(2, 3); p.add(); //輸出5
可以說,class用法就是ES5中動態原型模式。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93259.html
摘要:生成的類的原型會被自動調整,而你還能調用方法來訪問基類的構造器。唯一能避免調用的辦法,是從類構造器中返回一個對象。 起源 JS 從創建之初就不支持類,也沒有把類繼承作為定義相似對象以及關聯對象的主要方式,這讓不少開發者感到困惑。而從 ES1 誕生之前直到ES5 時期,很多庫都創建了一些工具,讓 JS 顯得貌似能支持類。盡管一些 JS 開發者強烈認為這門語言不需要類,但為處理類而創建的代...
摘要:一面向對象概念面向對象就是使用對象。因此在構造函數中表示剛剛創建出來的對象。在構造函數中利用對象的動態特性為其對象添加成員。 一、面向對象 1.1 概念 面向對象就是使用對象。面向對象開發就是使用對象開發。 面向過程就是用過程的方式進行開發。面向對象是對面向過程的封裝。 1.2 三大特性 抽象性所謂的抽象性就是:如果需要一個對象描述數據,需要抽取這個對象的核心數據 提出需要的核心...
摘要:對象詳解對象深度剖析,深度理解對象這算是醞釀很久的一篇文章了。用空構造函數設置類名每個對象都共享相同屬性每個對象共享一個方法版本,省內存。 js對象詳解(JavaScript對象深度剖析,深度理解js對象) 這算是醞釀很久的一篇文章了。 JavaScript作為一個基于對象(沒有類的概念)的語言,從入門到精通到放棄一直會被對象這個問題圍繞。 平時發的文章基本都是開發中遇到的問題和對...
摘要:接下來我們來聊一下的原型鏈繼承和類。組合繼承為了復用方法,我們使用組合繼承的方式,即利用構造函數繼承屬性,利用原型鏈繼承方法,融合它們的優點,避免缺陷,成為中最常用的繼承。 JavaScript是一門面向對象的設計語言,在JS里除了null和undefined,其余一切皆為對象。其中Array/Function/Date/RegExp是Object對象的特殊實例實現,Boolean/N...
摘要:理解繼承在中對繼承有了更友好的方式。總的來說的的實質和以前的繼承方式是一致的,但是有了更好的,更清晰的表現形式。 理解ES6繼承extends 1.在es6中對繼承有了更友好的方式。在下面的繼承中那到底在extends的時候做了什么,super()又是代表什么意思。 class People{ constructor(name, age) { this.name = name; ...
閱讀 2702·2023-04-25 14:59
閱讀 889·2021-11-22 11:59
閱讀 635·2021-11-17 09:33
閱讀 2468·2021-09-27 13:34
閱讀 3898·2021-09-09 11:55
閱讀 2321·2019-08-30 15:44
閱讀 1123·2019-08-30 14:06
閱讀 1925·2019-08-29 16:55