日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Javascript之 对象和原型

發(fā)布時(shí)間:2025/3/15 java 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Javascript之 对象和原型 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? ? 雖然Object構(gòu)造函數(shù)或?qū)ο笞置媪慷伎梢杂脕韯?chuàng)建單個(gè)對象,但這種方式有個(gè)弊端:使用同一個(gè)接口創(chuàng)建很多對象,會產(chǎn)生大量的重復(fù)代碼。為了解決這個(gè)問題,于是百家爭鳴,各種工廠模式的變體應(yīng)運(yùn)而生。

? ? ?1.工廠模式

? ? ? ? 這種模式是軟件工廠領(lǐng)域的廣為人知的設(shè)計(jì)模式,它抽象了創(chuàng)建具體對象的過程,用函數(shù)來封裝以特定接口創(chuàng)建對象的細(xì)節(jié),舉個(gè)栗子:

1 function createPerson(name,age,job){2 var o=new Object();3 o.name=name;4 o.age=age;5 o.job=job;6 o.sayname = function(){ 7 alert(this.name); 8 }; 9 return o; 10 } 11 12 var person1=createPerson("Sleipnir",23,"Software"); 13 var person2=createPerson("xiaoxiao",24,"Student");

? ? ? ?這個(gè)模式雖然可以無數(shù)次調(diào)用,解決了創(chuàng)建多個(gè)相似對象的問題,但沒有解決對象識別的問題(即怎樣知道一個(gè)對象的類型)

? ? ? 2.構(gòu)造函數(shù)模式

? ? ? ? 我們先用構(gòu)造函數(shù)模式把工廠模式的例子重寫一遍:

1 function Person(name,age,job){2 this.name=name;3 this.age=age;4 this.job=job;5 this.sayname = function(){6 alert(this.name); 7 }; 8 } 9 10 var person1=new Person("Sleipnir",23,"Software"); 11 var person2=new Person("xiaoxiao",24,"Student");

? ? ? ? 跟之前的工廠模式,我們可以看出區(qū)別:1.沒有在函數(shù)內(nèi)再創(chuàng)建對象

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2.直接將屬性和方法賦給了this對象

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 3.沒有return語句

? ? ? ? 在創(chuàng)建Person的實(shí)例時(shí),必須用到new操作符。以這種方式調(diào)用構(gòu)造函數(shù)會經(jīng)歷以下4個(gè)步驟:1.創(chuàng)建一個(gè)新對象??2.將構(gòu)造函數(shù)的作用域賦值給新對象(因此this就指向了這個(gè)新對象)?3.執(zhí)行構(gòu)造函數(shù)中的代碼(為新對象添加屬性和方法)?? 4.返回新對象

? ? ? ? 剛才說了,構(gòu)造函數(shù)勝于工廠模式的大方在于,它能解決實(shí)例的對象類型問題,將來可以將它的實(shí)例標(biāo)識為一種特定類型:

1 console.log(person1 instanceof Person); //true 2 console.log(person1 instanceof Object]); //true 3 console.log(person2 instanceof Person); //true 4 console.log(person2 instanceof Object); //true 5 console.log(Person instanceof Object); //true

? ? ? ? person1和person2之所以同時(shí)是Object的實(shí)例,是因?yàn)樗袑ο缶^承自O(shè)bject(下面會講到繼承)

? ? ? 2.1 調(diào)用構(gòu)造函數(shù)的方式

? ? ? ? ?上面已經(jīng)寫了Person的構(gòu)造函數(shù),我們來用幾種不同的方式調(diào)用:

1 //當(dāng)做構(gòu)造函數(shù)使用2 var person= new Person("Sleipnir",23,"Software");3 person.sayname(); //"Sleipnir"4 5 //作為普通函數(shù)使用6 Person("xiaoxiao",25,"Student"); //添加到全局window7 window.sayname(); //"xiaoxiao"8 9 //在另一個(gè)對象的作用域中調(diào)用 10 var o=new Object(); 11 person.call(o,"xiaoxiao",25,"Student"); 12 o.sayname(); //"xiaoxiao"

? ? ? ? ? ?第一種是當(dāng)做構(gòu)造函數(shù)使用,之前已經(jīng)提過,;第二種是作為普通函數(shù)調(diào)用,因?yàn)閠his對象都是指向全局對象,所以屬性和方法都被添加了window對象;第三種是在o對象的作用域中使用call()方法來調(diào)用Perso函數(shù)

? ? ? ? 2.2 構(gòu)造函數(shù)的問題

? ? ? ? ? ? ?構(gòu)造函數(shù)雖然不錯(cuò),但也有瑕疵。主要問題就是每個(gè)方法需要在每個(gè)實(shí)例上重新創(chuàng)建一遍,但是,如果在構(gòu)造函數(shù)里面創(chuàng)建Function實(shí)例或者在構(gòu)造函數(shù)外部定義函數(shù)來供構(gòu)造函數(shù)創(chuàng)建的實(shí)例調(diào)用的話,那我們所謂的構(gòu)造函數(shù)的全局作用域就名不副實(shí),自定義的引用類型包括定義的方法也就沒有封裝性可言了。

? ? ? ? ? ? ?好在程序員們都是不服輸?shù)娜?#xff0c;歷史的車輪總是向前滾動,于是原型模式就登上歷史舞臺了。

? ? ? ? 3.原型模式

? ? ? ? ? ? 概念先不說,舉個(gè)栗子再解釋:

1 function Person(){2 }3 Person.prototype.name="Sleipnir";4 Person.prototype.age=23;5 Person.prototype.job="Software";6 Person.prototype.sayname=function(){ 7 alert(this.name); 8 }; 9 10 var person1=new Person(); 11 person1.sayname(); //"Sleipnir" 12 var person2=new Person(); 13 person2.sayname(); //"Sleipnir" 14 15 alert(person1.sayname==person2.sayname);

?

? ? ? ? ? 我們創(chuàng)建的每一個(gè)函數(shù)都有一個(gè)prototype(原型)屬性,這個(gè)屬性是個(gè)指針,指向一個(gè)對象。所以,prototype就是通過調(diào)用構(gòu)造函數(shù)而創(chuàng)建的那個(gè)對象實(shí)例的原型對象。上面例子中的person1和person2所擁有的屬性和方法都是來源于構(gòu)造函數(shù)的原型對象中的

? ? ? ? ? 想要理解原型模式,就要理解【構(gòu)造函數(shù)】【原型】【實(shí)例】這三種之間的關(guān)系,抽象出來簡單來說,原型是構(gòu)造函數(shù)的屬性,而實(shí)例是通過構(gòu)造函數(shù)的原型而創(chuàng)建的,實(shí)例和構(gòu)造函數(shù)沒有關(guān)系,原型里還有一個(gè)constructor是指向構(gòu)造函數(shù)的,constructor就是類似于指針的存在,構(gòu)造函數(shù)通過constructor的指針作用,就把原型和實(shí)例連接起來了。這也是最簡單的原型繼承關(guān)系。

? ? ? 3.1 訪問實(shí)例/原型的屬性

? ? ? ? ?有時(shí)候,我們根據(jù)原型創(chuàng)建的實(shí)例,這個(gè)實(shí)例里有一部分是原型的屬性,有一部分也是實(shí)例自己的屬性,于是就要判斷哪些屬性屬于原型,哪些屬性屬于實(shí)例自己

? ? ? ? ?有兩個(gè)方法:hasOwnProperty() 和 in操作符

? ? ? ? ?先看hasOwnProperty():

1 function Person(){2 }3 Person.prototype.name="Sleipnir";4 Person.prototype.age=23;5 Person.prototype.job="Software";6 Person.prototype.sayname=function(){ 7 alert(this.name); 8 }; 9 10 var person1=new Person(); 11 var person2=new Person(); 12 13 console.log(person1.hasOwnProperty("name")); //false 14 15 person1.name="xiaoxiao"; 16 console.log(person1.name); //"xiaoxiao" 17 console.log(person1.hasOwnProperty("name")); //true 18 19 console.log(person2.name); //"Sleipnir" 20 console.log(person2.hasOwnProperty("name")); //false 21 22 delete person1.name; 23 console.log(person1.name); //"Sleipnir" 24 console.log(person1.hasOwnProperty("name")); //false

? ? ? ?從代碼結(jié)果可以總結(jié)出來,hasOwnProperty()檢測的是實(shí)例屬性,如果是屬于實(shí)例的,返回true,否則返回false

? ? ? ?in操作符:

function Person(){ } Person.prototype.name="Sleipnir"; Person.prototype.age=23; Person.prototype.job="Software"; Person.prototype.sayname=function(){ alert(this.name); }; var person1=new Person(); var person2=new Person(); console.log(person1.hasOwnProperty("name")); //false console.log("name" in person1); //true person1.name="xiaoxiao"; console.log(person1.name); //"xiaoxiao" console.log(person1.hasOwnProperty("name")); //true console.log("name" in person1); //true console.log(person2.name); //"Sleipnir" console.log(person2.hasOwnProperty("name")); //false console.log("name" in person2); //true delete person1.name; console.log(person1.name); //"Sleipnir" console.log(person1.hasOwnProperty("name")); //false console.log("name" in person1); //true

? ? ? ? 通過互相比較,我們能看出來,直接使用in操作符是,無論屬性是實(shí)例自己的還是原型的,都會返回true

? ? ? ? 我們來定義一個(gè)函數(shù),組合使用hasOwnProperty()和in操作符:

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? function hasPrototypeProperty(object,name){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?return !object.hasOwnProperty(name)&&(name in object);?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

1 function Person(){2 }3 Person.prototype.name="Sleipnir";4 Person.prototype.age=23;5 Person.prototype.job="Software";6 Person.prototype.sayname=function(){ 7 alert(this.name); 8 }; 9 function hasPrototypeProperty(object,name){ 10 return !object.hasOwnProperty(name)&&(name in object); 11 } 12 var person=new Person(); 13 console.log(hasPrototypeProperty(person,"name")); //true 14 15 person.name="xiaoxiao"; 16 console.log(hasPrototypeProperty(person,"name")); //false

? ? ? 3.2? 更簡單的原型語法

? ? ? ? ?使用Person.prototype一個(gè)個(gè)定義屬性太繁瑣,于是我們可以用對象字面量給原型定義屬性:

1 function Person(){2 }3 Person.prototype={4 constructor:Person,5 name:"Sleipnir",6 age:23, 7 job:"Software", 8 sayname: function(){ 9 alert(this.name); 10 } 11 };

? ? ? ? ?這里要注意,constructor要設(shè)置為Person,不然就會切斷原型與實(shí)例之間的關(guān)系了

? ? ?3.3 原型模式的問題

? ? ? ? ?原型模式省略了為構(gòu)造函數(shù)傳遞初始化參數(shù)這一環(huán)節(jié),結(jié)果所有實(shí)例在默認(rèn)情況下都取得了相同的屬性值。

? ? ? ? ?原型模式的問題在于其共享的本質(zhì),我們來看一個(gè)由于這個(gè)原因而引起問題的栗子:

function Person(){}Person.prototype={constructor:Person,name:"Sleipnir",age:23,job:"Software",friends:["zhangsan","lisi"], sayname: function(){ alert(this.name); } }; var person1=new Person(); var person2=new Person(); person1.friends.push("van"); console.log(person1.friends); //"zhangsan,lisi,van" console.log(person2.friends); //"zhangsan,lisi,van" console.log(person1.friends===person2.friends); //true

? ?這個(gè)例子中,friends是個(gè)引用類型的數(shù)組,由于在原型中已經(jīng)定義了,所以在實(shí)例中做修改時(shí),修改的值也會映射到其原型,然后原型又會同時(shí)將數(shù)據(jù)更新加載到其他實(shí)例中,這也體現(xiàn)了原型的動態(tài)性。但這種效果并不是我們想要的。

? 實(shí)際需求是,原型幫我們定義一部分公共屬性和方法,然后實(shí)例自己也有獨(dú)立的屬性和方法,基于這種情況,便有了下面的模式。

? ? 4.組合使用構(gòu)造函數(shù)模式和原型模式

? ? ? ?在這種模式下,構(gòu)造函數(shù)用于定義實(shí)例屬性,原型模式用于定義方法和共享的屬性。結(jié)果,每個(gè)實(shí)例都有了自己的一份實(shí)例屬性的副本,同時(shí)也共享著對方法的引用,最大限度地節(jié)省內(nèi)存,同時(shí)這種模式還支持向構(gòu)造函數(shù)傳遞參數(shù),可謂集兩種模式之長,我們來看看用這個(gè)方式重寫的上面的例子:

1 function Person(name,age,job){2 this.name=name;3 this.age=age;4 this.job=job;5 this.friends=["zhangsan","lisi"];6 } 7 Person.prototype={ 8 constructor:Person, 9 sayname: function(){ 10 alert(this.name); 11 } 12 } 13 14 var person1=new Person("Sleipnir",23,"Software"); 15 var person2=new Person("xiaoxiao",25,"Student"); 16 17 person1.friends.push("van"); 18 console.log(person1.friends); //"zhangsan,lisi,van" 19 console.log(person2.friends); //"zhangsan,lisi" 20 console.log(person1.fgriends===person2.friends); //false 21 console.log(person1.sayname===person2.sayname); //true

? ? ? ? 這種構(gòu)造模式和原型混合的模式,是目前使用最多的一種方法,可以說,這是用來定義引用類型的一種默認(rèn)模式。

?

? ?5.動態(tài)原型模式

? ? ? ?這種模式是解決了在構(gòu)造器中查看并初始化原型的問題,它的動態(tài)性在于,在構(gòu)造器中檢查一下原型中是否存在某個(gè)方法,如果不存在,就建立下,建立一次就行了,一勞永逸,這就是其方便之處,我們同樣來看個(gè)例子:

1 function Person(name,age,job){2 this.name=name;3 this.age=age;4 this.job=job;5 6 //檢查原型中是否有方法7 if(typeof this.sayname!="function"){8 Person.prototype.sayname=function(){ 9 alert(this.name); 10 }; 11 } 12 }

?

? ??

轉(zhuǎn)載于:https://www.cnblogs.com/sleipnir-0430/p/8562948.html

總結(jié)

以上是生活随笔為你收集整理的Javascript之 对象和原型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。