Object
對象建立var person = new Object(); person.name = "Albert"; person.sayName = function(){ console.log(this.name); };
var person = { name : "Albert", sayName : function(){ console.log(this.name) } };
Object
和字面量建立的問題:建立不少對象的時候會產生大量重複代碼。javascript
function createPerson(name){ var o = new Object(); o.name = name; o.sayName = function(){ console.log(this.name) } return o; } var person = createPerson("Albert");
沒法識別對象類型,即沒法經過instanceof
和constructor
來識別對象類型:java
person instanceof ???; person.constructor == ???;
function Person(name){ this.name = name; this.sayName = function(){ console.log(this.name) } } var person = new Person("Albert"); console.log(person.constructor == Person)//true console.log(person instanceof Person)//true
每一個方法都要在每一個實例上從新建立一次,尤爲是函數,這樣每一個Person
的實例都包含了一個不一樣的sayName
的函數實例。node
注意1
構造函數沒有return
語句。要建立Person
的新實例,必須採用new
操做符,new
操做符大致上完成了一下4件事情:windows
建立一個新的對象(本例中Person
建立的新對象,記爲person);瀏覽器
將構造函數的做用域賦給新對象(this=>person);安全
執行構造函數中的代碼(Person中的this.name=name;this.say.....
);閉包
返回新對象app
注意2
構造函數也是函數,若是不經過new
操做符調用,則做用環境爲全局(瀏覽器中爲windows
,node環境中爲global
)函數
function Person(name){ this.name = name; this.sayName = function(){ console.log(this.name) } } Person("BB"); global.sayName()//BB console.log(global.name)//BB
function Person(name){} Person.prototype.name = "Albert"; Person.prototype.sayName = function(){ console.log(this.name) } var person = new Person(); console.log(Object.getPrototypeOf(person)==Person.prototype);//true
瀏覽器支持:IE9+,這樣全部的Person
實例共享name
屬性及sayName
函數this
注意1
對象的某個屬性是否來自實例,可經過hasOwnProperty()
來肯定,若是是在原型中,則返回false
。
判斷對象是否具有屬性,能夠經過in
操做符,例如console.log("name" in person)//true
來判斷,不管是在原型仍是實例中,都返回true
,經過for-in
循環時,實例及原型中均會被枚舉。
注意2
在定義原型時,若是用字面量代替爲prototype
屬性定義,則原型的constructor
屬性不會指向Person
。由於經過字面量定義,徹底重寫了默認的prototype
對象。可是此時instanceof
仍是可以返回正確的結果。
function Person(name){}; Person.prototype={ name : "Albert", sayName : function(){ console.log(this.name); } }; var person = new Person(); console.log(person instanceof Person);//true console.log(person.constructor == Person);//false console.log(person.constructor == Object);//true
因此能夠再補充定義:
Object.defineProperty(Person.prototype,"constructor",{ enumerable:false, value:Person })
注意3
在重定義原型前,不能建立對象實例,不然會形成實例的原型指向錯誤
function Person(name){}; var person = new Person(); Person.prototype={ name : "Albert", sayName : function(){ console.log(this.name); } }; person.sayName(); //error
此例中person
的原型被指向了Person
的默認原型,固調用sayName
函數會發生錯誤。
小問題:爲了省略構造函數傳遞初始化參數,全部的實例在默認狀況下都會去的想通的屬性值
原型屬性被全部實例共享(適合function
類型的值),而一般狀況下,引用類型(Array
、Object
)屬性值通常不但願對全部實例共享。
利用構造函數都是實例屬性和原型的共享特性,分別定義對應的內容,組合共同完成對象建立,並且該模式還支持想構造函數傳遞參數。
function Person(name){ this.name = name; this.friends = ["Bob","Harry"];//引用類型爲實例屬性 }; Person.prototype.sayName = function(){ console.log(this.name); };
將1.6中的組合封裝在一個構造函數中的模式。具體方法爲:檢查某個應該存在的方法是否有效來決定是否須要初始化原型。
function Person(name){ this.name = name; this.friends = ["Bob","Harry"];//引用類型爲實例屬性 //****ProtoType**** if(typeof this.sayName != "function"){ Person.prototype.sayName = function(){ console.log(this.name); }; } };
構造函數在不反回值的狀況下,默認會返回新對象實例。
而經過在函數末尾添加return
語句,能夠重寫new
後調用函數時的返回值。
function Person(name){ var o = new Object(); o.name = name; o.sayName = function(){ console.log(this.name); }; return o; }; var person = new Person("Albert"); console.log(person instanceof Person);//false
該函數除了使用new
操做符和把包裝函數取名叫「構造函數」之外,和工廠模式實際上是如出一轍的。
該模式屬於比較特殊的構造模式,可用於不容許修改原對象的狀況。
function SpecialArray(){ var values = new Array(); values.push.apply(values,arguments); values.toPipedString = function(){ return this.join("|"); }; return values }
durable
)構造函數模式該模式構造出來的對象沒有公共屬性,不適用this
對象,不適用new
操做符,適用於在一些安全環境中,可防止數據被其它應用(如Mashup
)改動(利用閉包特性),相似於寄生構造函數模式,單不適用this
和new
。
function Person(name){ var o = new Object(); //****定義私有變量和函數**** var _name = name; o.sayName = function(){ console.log(_name); }; return o; }; var person = Person("Albert");
這種模式中,除了sayName()
方法之外,沒有其它辦法訪問_name
的值。