標籤:2-2 javascrip 有一個 原型對象 pre 檢測 重寫 大致 log
首先,在js裡,對象是由函數構建而成的。
建立對象的幾種模式
1.原廠模式
function person(name,age,job) { var o=new Object(); o.age=age; o.name=name; o.job=job; o.sayname=function () { console.log(this.name); } return o;}var person1=person("1",1,"1");person1.sayname();
//檢測對象什麼類型
console.log(person1 instanceof Object);//true
console.log(person1 instanceof person);//FALSE
原廠模式解決了建立多個相似對象的問題,但是不知道如何知道一個對象的類型。
2.建構函式模式
function person(name,age,job) { this.name=name; this.age=age; this.job=job; this.sayname=function () { console.log(this.name); }}var person1=new person("1",1,"1");person1.sayname();
console.log(person1 instanceof Object);//檢測對象什麼類型
console.log(person1 instanceof person);//都是true
與原廠模式不同點:
1.沒有顯式建立對象
2.屬性方法賦予給this對象
3.沒有return語句
建立對象使用new時,調用建構函式會有一下幾步
1.建立一個新對象
2.建構函式的範圍給新對象
3.執行建構函式的代碼
3.返回新對象
任何函數,只要通過new來調用,那麼他就可以作為建構函式,他的問題就是每個方法要在每個執行個體上重新構造一遍
上述sayname方法等同於下
this.sayname=new function("console.log(this.name)")
如果再建立對象person2
console.log(person1.sayname==person2.sayname) ;結果是FALSE
當然我們可以把這些函數放在外面,在建構函式內調用,但是這樣就毫無封裝性。3.
3.原型模式
每個函數都有一個prototype屬性
function person() {}person.prototype.name="1";person.prototype.age=12;person.prototype.sayname=function () { console.log(this.name);}var person1=new person();person1.sayname(); //1var person2=new person();person2.sayname(); //1
好處:讓所有執行個體共用他的屬性和方法
如果執行個體添加一個新屬性且新屬性與原型中的屬性重名,那麼就在執行個體中建立該屬性,該屬性會屏蔽掉原型中的該屬性。
function person() {}person.prototype.name="1";person.prototype.age=12;person.prototype.sayname=function () { console.log(this.name);}var person1=new person();person1.name="2";person1.sayname();delete person1.name;//刪除新添加的屬性person1.sayname(); //會顯示原型裡的屬性
接下來是重點:
function person() {}person.prototype={ name:"1", age:12, sayname:function () { console.log(this.name); }}var friend=new person();console.log(friend instanceof Object); //trueconsole.log(friend instanceof person); //trueconsole.log(friend.constructor == person); //falseconsole.log(friend.constructor == Object);//trueperson.prototype.sayhi=function () { console.log("hi");}friend.sayhi(); //hi
instanceof 判斷一個變數是不是屬於一個變數的執行個體。
constructor 屬性返回對建立此對象的數組函數的引用。
friend是person的一個執行個體
所以向person中添加 Protype時friend也可以引用。
原型的動態性:
function person() {}var friend=new person();console.log(friend instanceof Object); //trueconsole.log(friend instanceof person); //trueconsole.log(friend.constructor == person); //trueconsole.log(friend.constructor == Object); //trueconsole.log(friend.constructor); //【Function:person】person.prototype={ constructor:person, name:"1", age:12, sayname:function () { console.log(this.name); }}friend.sayname();//報錯
當執行到最後一句時會報錯,原因是我們重寫了整個原型對象。
大致就是這個樣子,person原本指向person Protype,在重寫原型對象後指向了new person Protype,但是friend仍然指向原來的person Protype,所以出現錯誤。
原型模式的問題:
function person() {}person.prototype={ constructor:person, friends:["a","b","c"]}var person1=new person();var person2=new person();person1.friends.push("d");console.log(person1.friends);//【a,b,c,d】console.log(person2.friends);//[a,b,c,d]
會發現person2的friends也會有d
針對包含參考型別值的屬性:
原因就是這個樣子,person1引用Protype,所以修改person1就修改了person2。
最常用的建立對象對象
--------------------組合使用建構函式模式和原型模式
因為建構函式模式new時會建立一個新對象,而原型模式就是用於定義方法和共用屬性。
function person(name) { this.name=name; this.friends=[‘a‘]}person.prototype={ constructor:person, sayname:function () { console.log(this.name); }}var person1=new person("1") ;var person2=new person("2") ;person1.friends.push("b");console.log(person1.friends);console.log(person2.friends);console.log(person1.friends==person2.friends);console.log(person1.sayname==person2.sayname);
結果:
[ ‘a‘, ‘b‘ ]
[ ‘a‘ ]
false
true
到這相信大家對JS構建對象有了一定的瞭解了!
JavaScript對象 -構建