欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談javascript中的prototype和__proto__的理解

 更新時(shí)間:2019年04月07日 10:18:19   作者:慕斯不想說(shuō)話  
這篇文章主要介紹了淺談javascript中的prototype和__proto__的理解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

在工作中有時(shí)候會(huì)看到prototype和__proto__這兩個(gè)屬性,對(duì)這兩個(gè)屬性我一直比較蒙圈,但是我通過(guò)查閱相關(guān)資料,決定做一下總結(jié)加深自己的理解,寫(xiě)得不對(duì)的地方還請(qǐng)各位大神指出。

  1. 跟__proto__屬性相關(guān)的兩個(gè)方法
  2. 判斷屬性是存在實(shí)例對(duì)象中,還是存在原型對(duì)象中的方法
  3. 獲取或遍歷對(duì)象中屬性的幾種方法

1、prototype

每個(gè)函數(shù)都有一個(gè)prototype屬性,該屬性是一個(gè)指針,指向一個(gè)對(duì)象。 而這個(gè)對(duì)象的用途是包含由特定類型的所有實(shí)例共享的屬性和方法。使用這個(gè)對(duì)象的好處就是可以讓所有實(shí)例對(duì)象共享它所擁有的屬性和方法

2、 __proto__

每個(gè)實(shí)例對(duì)象都有一個(gè)__proto__屬性,用于指向構(gòu)造函數(shù)的原型對(duì)象。__proto__屬性是在調(diào)用構(gòu)造函數(shù)創(chuàng)建實(shí)例對(duì)象時(shí)產(chǎn)生的。

function Person(name, age, job){ 
 this.name = name;
 this.age = age;
 this.job = job;
 this.sayName = function(){
 console.log(this.name);
 }; // 與聲明函數(shù)在邏輯上是等價(jià)的
}
var person1=new Person("Nicholas",29,"Software Engineer");
console.log(person1);
console.log(Person);
console.log(person1.prototype);//undefined
console.log(person1.__proto__);
console.log(Person.prototype);
console.log(person1.__proto__===Person.prototype);//true

輸出結(jié)果如下:

總結(jié):

1、調(diào)用構(gòu)造函數(shù)創(chuàng)建的實(shí)例對(duì)象的prototype屬性為"undefined",構(gòu)造函數(shù)的prototype是一個(gè)對(duì)象。

2、__proto__屬性是在調(diào)用構(gòu)造函數(shù)創(chuàng)建實(shí)例對(duì)象時(shí)產(chǎn)生的。

3、調(diào)用構(gòu)造函數(shù)創(chuàng)建的實(shí)例對(duì)象的__proto__屬性指向構(gòu)造函數(shù)的prototype。

4、在默認(rèn)情況下,所有原型對(duì)象都會(huì)自動(dòng)獲得一個(gè)constructor(構(gòu)造函數(shù))屬性,這個(gè)屬性包含一個(gè)指向prototype屬性所在函數(shù)的指針。

下圖展示了使用Person構(gòu)造函數(shù)創(chuàng)建實(shí)例后各個(gè)對(duì)象之間的關(guān)系

上圖展示了 Person 構(gòu)造函數(shù)、 Person 的原型屬性以及 Person現(xiàn)有的兩個(gè)實(shí)例之間的關(guān)系。

3、 跟__proto__屬性相關(guān)的兩個(gè)方法

isPrototypeOf():雖然在所有實(shí)現(xiàn)中都無(wú)法訪問(wèn)到__proto__,但可以通過(guò) isPrototypeOf()方法來(lái)確定對(duì)象之間是否存在這種關(guān)系。

alert(Person.prototype.isPrototypeOf(person1)); //true
 alert(Person.prototype.isPrototypeOf(person2)); //true

Object.getPrototypeOf():在所有支持的實(shí)現(xiàn)中,這個(gè)方法返回__proto__的值。例如:

alert(Object.getPrototypeOf(person1) == Person.prototype); //true
 alert(Object.getPrototypeOf(person1).name); //"Nicholas"

注意:雖然可以通過(guò)對(duì)象實(shí)例訪問(wèn)保存在原型中的值,但卻不能通過(guò)對(duì)象實(shí)例重寫(xiě)原型中的值。如果我們?cè)趯?shí)例中添加了一個(gè)屬性,而該屬性與實(shí)例原型中的一個(gè)屬性同名,那我們就在實(shí)例中創(chuàng)建該屬性,該屬性將會(huì)屏蔽原型中的那個(gè)屬性。請(qǐng)看下面的例子:

function Person(){
 }
 Person.prototype.name = "Nicholas";
 Person.prototype.age = 29;
 Person.prototype.job = "Software Engineer";
 Person.prototype.sayName = function(){
 alert(this.name);
 };
 var person1 = new Person();
 var person2 = new Person();
 person1.name = "Greg";
 alert(person1.name); //"Greg"—— 來(lái)自實(shí)例
 alert(person2.name); //"Nicholas"—— 來(lái)自原型

4、 判斷屬性是存在實(shí)例對(duì)象中,還是存在原型對(duì)象中,有以下方法

hasOwnProperty():可以檢測(cè)一個(gè)屬性是存在于實(shí)例中,還是存在于原型中。返回值為true表示該屬性存在實(shí)例對(duì)象中,其他情況都為false。

in 操作符:無(wú)論該屬性存在于實(shí)例中還是原型中。只要存在對(duì)象中,都會(huì)返回true。但是可以同時(shí)使用 hasOwnProperty()方法和 in 操作符,就可以確定該屬性到底是存在于對(duì)象中,還是存在于原型中。

var person1 = new Person();
 var person2 = new Person();
 alert(person1.hasOwnProperty("name")); //false
 alert("name" in person1); //true
 person1.name = "Greg";
 alert(person1.name); //"Greg" —— 來(lái)自實(shí)例
 alert(person1.hasOwnProperty("name")); //true
 alert("name" in person1); //true
 alert(person2.name); //"Nicholas" —— 來(lái)自原型
 alert(person2.hasOwnProperty("name")); //false
 alert("name" in person2); //true
 delete person1.name;
 alert(person1.name); //"Nicholas" —— 來(lái)自原型
 alert(person1.hasOwnProperty("name")); //false
 alert("name" in person1); //true

5、 獲取或遍歷對(duì)象中屬性的幾種方法

for-in:通過(guò)for-in循環(huán)的返回的是能夠被訪問(wèn)的、可枚舉的屬性,不管該屬性是在實(shí)例中,還是存在原型中。

function Person(name, age, job) {
		this.name = name;
		this.age = age;
		this.job = job;	
	}
	Person.prototype={
		sayName:function(){
			return this.name;
		}
	}
	var p=new Person("李明",30,"詩(shī)人");
	for(var prop in p){
		console.log(prop);//name、age、job、sayName
	}
 console.log(Object.keys(p));//["name", "age", "job"]
 console.log(Object.keys(Person.prototype));//["sayName"]
 console.log(Object.getOwnPropertyNames(Person.prototype))
 // ["constructor", "sayName"] 

Object.keys():取得實(shí)例對(duì)象上所有可枚舉的屬性。 Object.getOwnPropertyNames(): 獲取實(shí)例對(duì)象所有屬性,無(wú)論它是否可枚舉。

注意:使用對(duì)象字面量來(lái)重寫(xiě)整個(gè)原型對(duì)象時(shí),本質(zhì)上完全重寫(xiě)了默認(rèn)的 prototype 對(duì)象,因此 constructor 屬性也就變成了新對(duì)象的 constructor 屬性(指向 Object 構(gòu)造函數(shù)),不再指向 Person。但是可以通過(guò)在重寫(xiě)原型對(duì)象時(shí)指定constructor屬性,使之還是指向原來(lái)的constructor。此時(shí),盡管 instanceof 操作符還能返回正確的結(jié)果,但通過(guò) constructor 已經(jīng)無(wú)法確定對(duì)象的類型了。

object instanceof constructor:檢測(cè) constructor.prototype 是否存在于參數(shù) object 的原型鏈上。

function Person() {}
 var friend2 = new Person();
 Person.prototype = {
 	//constructor : Person,
 	name: "Nicholas",
 	age: 29,
 	job: "Software Engineer",
 	sayName: function() {
 		alert(this.name);
 	}
 };
 var friend = new Person();
 console.log(friend2 instanceof Object); //true
 console.log(friend2 instanceof Person); //false,
 console.log(friend2.constructor == Person); //true
 console.log(friend2.constructor == Object); //false
 
 console.log(friend instanceof Object); //true
 console.log(friend instanceof Person); //true
 console.log(friend.constructor == Person); //false
 console.log(friend.constructor == Object); //true

由于原型的動(dòng)態(tài)性,調(diào)用構(gòu)造函數(shù)時(shí)會(huì)為實(shí)例添加一個(gè)指向最初原型的Prototype指針,而把原型修改為另外一個(gè)對(duì)象就等于切斷了構(gòu)造函數(shù)與最初原型之間的聯(lián)系??聪旅娴睦?/p>

function Person(){
 }
 var friend = new Person();
 Person.prototype = {
 constructor: Person,
 name : "Nicholas",
 age : 29,
 job : "Software Engineer",
 sayName : function () {
  alert(this.name);
 }
 };
 var friend2=new Person();
 friend.sayName(); //Uncaught TypeError: friend.sayName is not a function 
 friend2.sayName();//Nicholas
 console.log(friend instanceof Person);//false
 console.log(friend instanceof Object);//true
 console.log(friend2 instanceof Person);//true

結(jié)果分析:這是因?yàn)閒riend1的prototype指向的是沒(méi)重寫(xiě)Person.prototype之前的Person.prototype,也就是構(gòu)造函數(shù)最初的原型對(duì)象。而friend2的prototype指向的是重寫(xiě)Person.prototype后的Person.prototype。如下圖所示

 

6、 原型鏈

基本思想是利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法。最直觀的表現(xiàn)就是讓原型對(duì)象等于另一個(gè)類型的實(shí)例。

function SuperType(){
 this.property = true;
 }
 SuperType.prototype.getSuperValue = function(){
 return this.property;
 };
 function SubType(){
 this.subproperty = false;
 }
 //繼承了 SuperType
 SubType.prototype = new SuperType();
 SubType.prototype.getSubValue = function (){
 return this.subproperty;
 };
 var instance = new SubType();
 alert(instance.getSuperValue()); //true

SubType.prototype = new SuperType();這句代碼使得原來(lái)存在于 SuperType 的實(shí)例中的所有屬性和方法,現(xiàn)在也存在于 SubType.prototype 中。使得instance的constructor指向了SuperType。

console.log(instance.constructor===SuperType);//true

總結(jié): 訪問(wèn)一個(gè)實(shí)例屬性時(shí),首先會(huì)在實(shí)例中搜索該屬性。如果沒(méi)有找到該屬性,則會(huì)繼續(xù)搜索實(shí)例的原型。在通過(guò)原型鏈實(shí)現(xiàn)繼承的情況下,搜索過(guò)程就得以沿著原型鏈繼續(xù)向上。在找不到屬性或方法的情況下,搜索過(guò)程總是要一環(huán)一環(huán)地前行到原型鏈末端才會(huì)停下來(lái)。

就拿上面的例子來(lái)說(shuō),調(diào)用 instance.getSuperValue()會(huì)經(jīng)歷4個(gè)搜索步驟:

  1. 搜索instance實(shí)例;
  2. 搜索 SubType.prototype;
  3. 搜索SuperType的實(shí)例;
  4. 搜索 SuperType.prototype,最后一步才會(huì)找到該方法。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論