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

學習javascript面向?qū)ο?理解javascript原型和原型鏈

 更新時間:2016年01月04日 10:27:28   作者:小火柴的藍色理想  
這篇文章主要介紹了javascript原型和原型鏈,學習javascript面向?qū)ο螅信d趣的小伙伴們可以參考一下

先看一張圖,梳理梳理。

一、基本概念  
【原型鏈】每個構(gòu)造函數(shù)都有一個對象,原型對象都包含一個指向構(gòu)造函數(shù)的指針,而實例都包含一個指向原型對象的內(nèi)部指針。那么,如果原型對象等于另一個原型的實例,此時的原型對象將包含一個指向另一個原型的指針,相應地,另一個原型中也包含著一個指向另一個構(gòu)造函數(shù)的指針。如果另一個原型又是另一個原型的實例,那么上述關(guān)系依然成立。如此層層遞進,就構(gòu)成了實例與原型的鏈條。
【原型對象】這個對象包含可以由特定類型的所有實例共享的屬性和方法。所有引用類型默認都繼承了Object,而這個繼承也是通過原型鏈實現(xiàn)的。所有函數(shù)的默認原型都是Object的實例,因此默認原型都會包含一個內(nèi)部指針,指向Object.prototype,這也正是所有自定義類型都會繼承toString()、valueOf()方法的原因
【構(gòu)造函數(shù)】構(gòu)造函數(shù)與其他函數(shù)的區(qū)別在于調(diào)用它們的方式不同。一般來說,函數(shù)只要通過new操作符來調(diào)用,那它就可以作為構(gòu)造函數(shù);如果不通過new操作符來調(diào)用,那它跟普通函數(shù)也不會有什么兩樣。
[注意]用戶自定義的函數(shù)和javascript中內(nèi)置的構(gòu)造函數(shù)可以當成構(gòu)造函數(shù)使用
【構(gòu)造函數(shù)的寫法】構(gòu)造函數(shù)始終應該以一個大寫字母開頭,而非構(gòu)造函數(shù)以一個小寫字母開頭。這個做法借鑒自其他OO語言,主要是為了區(qū)別于ECMAScript中的其他函數(shù);因為構(gòu)造函數(shù)本身也是函數(shù),只不過可以用來創(chuàng)建對象而已
【構(gòu)造函數(shù)的三種使用場景】
[a]當作構(gòu)造函數(shù)使用

var person = new Person("Nicholas",29,"software Engineer");
person.sayName();

[b]當作普通函數(shù)調(diào)用

Person("greg",27,"doctor");//添加到window
window.sayName();//"Greg"

[c]在另一個對象的作用域中調(diào)用

var o = new Object();
Person.call(o,"Kristen",25,"Nurse");
o.sayName();//"Kristen"

【prototype屬性】只要創(chuàng)建了一個新函數(shù),就會根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個prototype屬性,這個屬性指向函數(shù)的原型對象。
[注意]只有函數(shù)才有prototype屬性,object沒有prototype屬性
【constructor屬性】在默認情況下,所有原型對象都會自動獲得一個constructor(構(gòu)造函數(shù))屬性,這個屬性包含一個指向prototype屬性所在函數(shù)的指針
[注意]創(chuàng)建了自定義的構(gòu)造函數(shù)之后,其原型對象默認只會取得constructor屬性,至于其他方法則都是從Object繼承而來的
【_proto_和[[prototype]]】當調(diào)用構(gòu)造函數(shù)創(chuàng)建一個新實例后,該實例的內(nèi)部將包含一個指針(內(nèi)部屬性),指向構(gòu)造函數(shù)的原型對象。ECMA-262第5版管這個指針叫[[prototype]]。雖然在腳本中標準的方式訪問[[prototype]],但firefox\safari\chrome在每個對象上都支持一個屬性_proto_;而在其他實現(xiàn)中,這個屬性對腳本則是完全不可見的。這個連接存在于實例與構(gòu)造函數(shù)的原型對象之間,而不是存在于實例與構(gòu)造函數(shù)之間
二、基本操作  
【原型鏈查詢】每當代碼讀取某個對象的某個屬性時,都會執(zhí)行一次搜索,目標是具有給定名字的屬性。搜索首先從對象實例本身開始,如果在實例中找到了具有給定名字的屬性,則返回該屬性的值;如果沒有找到,則繼續(xù)搜索指針指向的原型對象,在原型對象中查找具有給定名字的屬性,如果找到了這個屬性,則返回該屬性的值。
【添加實例屬性】當為對象實例添加一個屬性時,這個屬性就會屏蔽原型對象中保存的同名屬性;換句話說,添加這個屬性只會阻止我們訪問原型中的那個屬性,但不會修改那個屬性,即使將這個屬性設置為null,也只會在實例中設置這個屬性,而不會恢復其指向原型的連接。不過,使用delete操作符則可以完全刪除實例屬性,從而讓我們能夠重新訪問原型中的屬性。
【原型的動態(tài)性】由于在原型中查找值的過程是一次搜索,因此我們對原型對象所做的任何修改都能立即從實例上反映出來,即使是先創(chuàng)建了實例后修改原型也照樣如此。
[注意]不推薦在產(chǎn)品化的程序中修改原生對象的原型

function Person(){};
var friend = new Person();
Person.prototype.sayHi = function(){
  alert('hi');
}
friend.sayHi();//"hi"  

【重寫原型】調(diào)用構(gòu)造函數(shù)時會為實例添加一個指向最初原型的[[prototype]]指針,而把原型修改為另外一個對象就等于切斷了構(gòu)造函數(shù)與最初原型之間的聯(lián)系。實例中的指針僅指向原型,而不指向構(gòu)造函數(shù)。
三、基本方法  
[1]isPrototypeOf():判斷實例對象和原型對象是否存在于同一原型鏈中,只要是原型鏈中出現(xiàn)過的原型,都可以說是該原型鏈所派生的實例的原型

function Person(){};
var person1 = new Person();
var person2 = new Object();
console.log(Person.prototype.isPrototypeOf(person1));//true
console.log(Object.prototype.isPrototypeOf(person1));//true
console.log(Person.prototype.isPrototypeOf(person2));//false
console.log(Object.prototype.isPrototypeOf(person2));//true

[2]ECMAScript5新增方法Object.getPrototypeOf():這個方法返回[[Prototype]]的值

function Person(){};
var person1 = new Person();
var person2 = new Object();
console.log(Object.getPrototypeOf(person1)); //Person{}
console.log(Object.getPrototypeOf(person1) === Person.prototype); //true
console.log(Object.getPrototypeOf(person1) === Object.prototype); //false
console.log(Object.getPrototypeOf(person2)); //Object{}  

[3]hasOwnProperty():檢測一個屬性是否存在于實例中

function Person(){
  Person.prototype.name = 'Nicholas';
}
var person1 = new Person();
//不存在實例中,但存在原型中
console.log(person1.hasOwnProperty("name"));//false
//不存在實例中,也不存在原型中
console.log(person1.hasOwnProperty("no"));//false
person1.name = 'Greg';
console.log(person1.name);//'Greg'
console.log(person1.hasOwnProperty('name'));//true
delete person1.name;
console.log(person1.name);//"Nicholas"
console.log(person1.hasOwnProperty('name'));//false  

[4]ECMAScript5的Object.getOwnPropertyDescriptor():只能用于取得實例屬性的描述符,要取得原型屬性的描述符,必須直接在原型對象上調(diào)用Object.getOwnPropertyDescription()方法

function Person(){
  Person.prototype.name = 'Nicholas';
}
var person1 = new Person();
person1.name = 'cook';
console.log(Object.getOwnPropertyDescriptor(person1,"name"));//Object {value: "cook", writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(Person.prototype,"name"));//Object {value: "Nicholas", writable: true, enumerable: true, configurable: true}

[5]in操作符:在通過對象能夠訪問給定屬性時返回true,無論該屬性存在于實例還是原型中

function Person(){}
var person1 = new Person();
person1.name = 'cook';
console.log("name" in person1);//true
console.log("name" in Person.prototype);//false
var person2 = new Person();
Person.prototype.name = 'cook';
console.log("name" in person2);//true
console.log("name" in Person.prototype);//true

[6]同時使用hasOwnProperty()方法和in操作符,來確定屬性是否存在于實例中

//hasOwnProperty()返回false,且in操作符返回true,則函數(shù)返回true,判定是原型中的屬性
function hasPrototypeProperty(object,name){
  return !object.hasOwnProperty(name) && (name in object);
}
function Person(){
  Person.prototype.name = 'Nicholas';
}
var person1 = new Person();
console.log(hasPrototypeProperty(person1,'name'));//true
person1.name = 'cook';
console.log(hasPrototypeProperty(person1,'name'));//false
delete person1.name;
console.log(hasPrototypeProperty(person1,'name'));//true
delete Person.prototype.name;
console.log(hasPrototypeProperty(person1,'name'));//false

[7]ECMAScript5的Object.keys()方法:接收一個對象作為參數(shù),返回一個包含所有可枚舉屬性的字符串數(shù)組
[注意]一定要先new出實例對象再使用該方法,否則為空

function Person(){
  Person.prototype.name = 'Nicholas';
  Person.prototype.age = 29;
  Person.prototype.job = 'Software Engineer';
  Person.prototype.sayName = function(){
    alert(this.name);
  }  
};
var keys = Object.keys(Person.prototype);
console.log(keys);//[]
var p1 = new Person();
p1.name = "Rob";
p1.age = 31;
var keys = Object.keys(Person.prototype);
console.log(keys);//["name","age","job","sayName"]
var p1Keys = Object.keys(p1);
console.log(p1Keys);//["name","age"]

[8]ECMAScript5的Object.getOwnPropertyNames()方法:接收一個對象作為參數(shù),返回一個包含所有屬性的字符串數(shù)組
[注意]一定要先new出實例對象再使用該方法,否則只有constructor

function Person(){
  Person.prototype.name = 'Nicholas';
  Person.prototype.age = 29;
  Person.prototype.job = 'Software Engineer';
  Person.prototype.sayName = function(){
    alert(this.name);
  }  
};
var keys = Object.getOwnPropertyNames(Person.prototype);
console.log(keys);//["constructor"]
var p1 = new Person();
var keys = Object.getOwnPropertyNames(Person.prototype);
console.log(keys);//["constructor", "name", "age", "job", "sayName"]

希望本文所述對大家學習javascript程序設計有所幫助。

相關(guān)文章

最新評論