摘要:就是通過調用構造函數而創建的那個對象實例的原型對象。與寄生構造函數模式類似,使用穩妥構造函數模式創建的對象與構造函數之間也沒有什么關系,因此操作符對這種對象也沒有什么意義
雖然Object構造函數或對象字面量都可以用來創建單個對象,但是這些方法有明顯的缺點:使用同一個接口創建很多對象,會產生大量重復代碼。因此人們開始使用工廠模式。
工廠模式這種模式抽象了創建具體對象的過程
function createPerson(name,age){ var o = new Object(); o.name = name; o.age = age; o.sayName = function(){ alert(this.name); }; return o; } var person1 = new createPerson("liaojin",18); var person2 = new createPerson("xiaoguan",20);
函數createPerson()能夠根據接受的參數來構建一個包含所有必要信息的Person對象。可以無數次的調用這個函數,而每次它都會返回一個包含兩個屬性以個方法的對象。工廠模式雖然解決了創建多個相似對象的問題,但卻沒有解決對象識別的問題(即怎樣知道一個對象的類型)。
構造函數模式使用構造函數將上述例子重寫
function Person(name,age){ this.name = name; this.age = age; this.sayName = function(){ alert(this.name); }; } var person1 = new Person("liaojin",18); var person2 = new Person("xiaoguan",20);
在這個例子中,Person()函數取代了createPerson()函數。注意到Person()中的代碼與createPerson()的不同之處:
1.沒有顯示的創建對象
2.直接將屬性和方法賦值給了this對象
3.沒有return語句
要創建Person新實例,必須使用new操作符。這種方式會經理以下四個步驟:
1.創建一個新對象
2.將構造函數的作用域賦給新對象(因此this就指向了這個新對象)
3.執行構造函數中的代碼(為這個新對象添加屬性)
4.返回新對象
person1和person2分別保存著Person的一個不同實例。這兩個對象都有一個constructor屬性,該屬性指向Person。
alert(person1.constructor == Person);//true alert(person2.constructor == Person);//true
對象的constructor屬性最初是用來表示對象類型的,但是檢測對象類型還是instanceof更可靠一些。這個例子中創建的所有對象即是Object的實例,同時也是Person的實例。
創建自定義的構造函數意味著將來可以將它的實例標識為一種特定的類型;person1和person2之所以同時是Object的實例,是因為所有對象均繼承自Object.
將構造函數當做函數
構造函數與其他函數唯一的區別就在于調用他們的方式不同。
任何函數只要通過new操作符來調用,那他就可以作為構造函數;而任何函數如果不通過new操作符來調用,那他跟普通函數沒有區別。
如上述例子中的Person()函數可以通過下列任何一種方式來調用。
//當做構造函數調用 var person = new Person("liaojin",18); person.sayName();//liaojin //作為普通函數調用 Person("lihua",12); window.sayName();//lihua //在另一個對象的作用域調用 var o = new Object(); Person.call(o,"xiaoguan",20); o.sayName();//xiaoguan
構造函數的問題
構造函數模式雖然好用,但是也有缺點。使用構造函數的主要問題,就是每個方法都要在每個實例上重新創建一遍。如同this.sayName =new function(){alert(this.name);};在上面的構造函數中sayName()的方法,person1和person2雖然都調用了這個方法,但是調用的并不是同一個Function實例。因此不同實例的同名函數是不相等的
alert(person1.sayName == person2.sayName);//false
然而創建兩個完成同樣任務的Function實例的確沒有必要;因此可以通過吧函數定義轉移到構造函數外部來解決這個問題
function Person(name,age){ this.name = name; this.age = age; this.sayName = sayName; } function sayName(){ alert(this.name); } var person1 = new Person("liaojin",18); var person2 = new Person("xiaoguan",20);
在構造函數內部,我們將sayName屬性設置為指向全局的sayName函數,由于sayName包含的是指向函數的指針,person1,person2共享了一個sayName函數,解決了兩個函數做同樣一件事的問題。
可是隨即有產生了新的問題:在全局作用域定義的函數實際上只能被某個對象調用,這讓全局函數優點名不副實。如果對象需要定義很多方法,那么就需要定義多個全局函數,于是自定義的引用類型就沒有封裝性可言了,因此產生了原型模式。
我們所創建的每個函數都有一個prototype屬性,這個屬性是一個指針,指向一個對象,而這個對象的用途就是包含可以由特定類型的所有實例共享的屬性和方法。prototype就是通過調用構造函數而創建的那個對象實例的原型對象。可以讓所有對象的實例共享它所包含的屬性和方法。
function Person(){} Person.prototype.name = "liaojin"; Person.prototype.age = 18; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); Person1.sayName();//liaojin var person2 = new Person(); Person2.sayName();//liaojin alert(person1.sayName == person2.sayName);//true組合使用構造函數模式和原型模式
構造函數用于定義實例屬性,而原型模式用于定義方法和共享的屬性。這樣每個實例都會有自己的實例屬性的副本,但同時又共享著對方法的引用,最大限度地節省了內存。
function Person(name,age){ this.name = name; this.age = age; this.friends = ["lucy","lily"]; } Person.prototype = { constructor:Person, sayName:function(){ alert(this.name); } } var person1 = new Person("liaojin",18); var person2 = new Person("xiaoguan",20); person1.friends.push("lihua"); alert(person1.friends);//lucy,lily,lihua alert(person2.friends);//lucy,lily alert(person1.friends == person2.friends);//false alert(person1.sayName == person2.sayName);//true動態原型模式
有其他面向對象經驗開發的人員看到獨立的構造函數和原型時,很可能會肥腸困惑,動態原型模式就是解決這個問題的一個方案。
function Person(name,age){ this.name = name; this.age = age; } if(typeof this.sayName != "function"){ Person.prototype.sayName = function(){ alert(this.name); }; }
這里只在sayName()方法不存在的情況下才會將它添加到原型中。這段代碼只會在初期調用才會執行。
寄生構造函數模式這個模式可以在特殊的情況下用來為對象創建構造函數。假設我們想創建一個具有額外方法的特殊數組。由于不能直接修改Array構造函數,因此可以使用這個模式。
function SpecialArray(){ var values = new Array(); values.push.apply(values,arguments); values.toPipedString = function(){ return this.join("|"); }; return values; } var colors = new SpecialArray["red","blue","green"]; alert(colors.toPipedString());//red|blue|green
說明:關于寄生構造函數模式,首先返回的對象與構造函數或者與構造函數的原型屬性之間沒有關系;構造函數返回的對象與在構造函數外部創建的對象沒有什么不同。因此不能依賴instanceof操作符來確定對象的類型。
穩妥構造函數模式所謂穩妥對象,指的是沒有公共屬性,而且其方法也不引用this的對象。穩妥對象最適合在一些安全的環境中(禁止使用this和new的環境),或者在防止數據被其他應用程序改動時使用。與寄生構造函數類似的模式;但有兩點不同:1.新創建對象的實例方法不引用this;2.不使用new操作符調用構造函數;
function Person(name,age){ var o = new Object(); o.sayName = function(){ alert(name); }; return o; } //使用 var friend = Person("liaojin",18); friend.sayName();//liaojin
這樣變量person中保存的是一個穩妥對象,而除了調用sayName()方法外,沒有別的方法可以訪問其數據成員,即使有其他代碼會給這個對象添加方法或數據成員,但也不可能有別的辦法訪問傳入到構造函數中的原始數據,非常適合在某些安全執行環境下使用。
與寄生構造函數模式類似,使用穩妥構造函數模式創建的對象與構造函數之間也沒有什么關系,因此instanceof操作符對這種對象也沒有什么意義
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95645.html
摘要:對象在中,除了數字字符串布爾值這幾個簡單類型外,其他的都是對象。那么在函數對象中,這兩個屬性的有什么區別呢表示該函數對象的原型表示使用來執行該函數時這種函數一般成為構造函數,后面會講解,新創建的對象的原型。這時的函數通常稱為構造函數。。 本文原發于我的個人博客,經多次修改后發到sf上。本文仍在不斷修改中,最新版請訪問個人博客。 最近工作一直在用nodejs做開發,有了nodejs,...
摘要:注意句柄棧并不是調用棧中的一部分,但句柄域卻在棧中。一個依賴于構造函數和析構函數來管理下層對象的生命周期。對象模板用來配置將這個函數作為構造函數而創建的對象。 如果你已經閱讀過了上手指南,那么你已經知道了如何作為一個單獨的虛擬機使用 V8 ,并且熟悉了一些 V8 中的關鍵概念,如句柄,域 和上下文。在本文檔中,還將繼續深入討論這些概念并且介紹其他一些在你的 C++ 應用中使用 V8 的...
摘要:對象的分類內置對象原生對象就是語言預定義的對象,在標準定義,有解釋器引擎提供具體實現宿主對象指的是運行環境提供的對象。不過類型是中所有類型的父級所有類型的對象都可以使用的屬性和方法,可以通過的構造函數來創建自定義對象。 對象 javaScript中的對象,和其它編程語言中的對象一樣,可以比照現實生活中的對象來理解。在JavaScript中,一個對象可以是一個單獨擁有屬性和類型的實體。和...
摘要:在最開始的時候,原型對象的設計主要是為了獲取對象的構造函數。同理數組通過調用函數通過調用原型鏈中描述了原型鏈的概念,并將原型鏈作為實現繼承的主要方法。 對象的創建 在JavaScript中創建一個對象有三種方式。可以通過對象直接量、關鍵字new和Object.create()函數來創建對象。 1. 對象直接量 創建對象最直接的方式就是在JavaScript代碼中使用對象直接量。在ES5...
摘要:當談到語言與其他編程語言相比時,你可能會聽到一些令人困惑東西,其中之一是工廠函數和構造函數。好的,讓我們用構造函數做同樣的實驗。當我們使用工廠函數創建對象時,它的指向,而當從構造函數創建對象時,它指向它的構造函數原型對象。 showImg(https://segmentfault.com/img/bVbr58T?w=1600&h=900); 當談到JavaScript語言與其他編程語言...
摘要:在中函數是一等對象,它們不被聲明為任何東西的一部分,而所引用的對象稱為函數上下文并不是由聲明函數的方式決定的,而是由調用函數的方式決定的。更為準確的表述應該為當對象充當函數的調用函數上下文時,函數就充當了對象的方法。 引言:當理解了對象和函數的基本概念,你可能會發現,在JavaScript中有很多原以為理所當然(或盲目接受)的事情開始變得更有意義了。 1.JavaScript...
閱讀 2007·2021-09-22 16:05
閱讀 9314·2021-09-22 15:03
閱讀 2885·2019-08-30 15:53
閱讀 1702·2019-08-29 11:15
閱讀 911·2019-08-26 13:52
閱讀 2353·2019-08-26 11:32
閱讀 1806·2019-08-26 10:38
閱讀 2567·2019-08-23 17:19