js--原型和原型鏈相關問題
前言
閱讀本文前先來思考一個問題,我們在 js 中建立一個變數,我們並沒有給這個變數新增一些方法,比如 toString() 方法,為什麼我們可以直接使用這個方法呢?如以下程式碼,帶著這樣的問題,我們來學習本節的原型和原型鏈的一些知識。
正文
** 1.建構函式建立物件問題**
function Person(name, age) { this.name = name; this.age = age; this.sayName = function () {
console.log(this.name);
};
} var person = new Person("xiaoming", 18);
person.sayName(); // xiaoming
當使用建構函式建立物件person時,即使用new運算子構造一個例項物件的時候,首先會建立一塊新的記憶體空間,標記為person例項,執行建構函式會建立一個物件,會將物件的原型指向建構函式的 prototype 屬性,然後執行上下文中的this指向這個物件,最後再執行整個函式,如果返回值不是物件,則返回新建的物件,建立的物件有一個建構函式 constructor 屬性。其實質就是建立一個 object 引用型別的例項,然後把例項儲存在變數 person 中。
總結 :new 運算子呼叫建構函式經歷了以下四步:
(1)建立一個新物件;
(2)將建構函式的作用域賦值給新物件(因此 this 指向這個新物件);
(3)執行建構函式中的程式碼(為這個構造的新物件新增屬性);
(4)返回這個新物件。
2.原型相關問題
我們建立的每個函式都有一個 prototype 屬性,這個屬性是一個指標,指向一個物件,而這個物件包含了透過該建構函式例項的物件所共享的屬性和方法。那麼,prototype 就是透過呼叫建構函式而建立的那個物件例項的原型物件。
function Person() {}
Person.prototype.name = "xioming";
Person.prototype.sayHello = function () {
console.log(this.name);
}; var person1 = new Person();
person1.sayHello(); //xiaoming
var person2 = new Person();
person2.sayHello(); //xiaoming
上面的程式碼,我們將 sayHello() 方法和所有屬性直接新增到了 Person 的 prototype 屬性中,建構函式變成了空函式,透過此建構函式建立的新物件例項,具有相同的屬性和方法,與純建構函式建立的物件不同的是所有例項共享了這些屬性和方法。
(1)理解原型物件
無論什麼時候,只要建立一個新函式,就會根據一種特定的規則為該函式建立一個 prototype 屬性,這個屬性指向函式的原型物件,預設情況下,所有原型物件都會自動獲得一個 constructor (建構函式)屬性,這個屬性包含一個指向 prototype 屬性所在函式的指標。例如上面的例子中 Person.prototype.constructor 指向 Person,同樣,我們可以繼續為原型物件新增別的屬性和方法。建立了自定義建構函式之後,其原型只會取得constructor屬性,其他方法都是透過從object繼承而來,當呼叫建構函式建立一個新例項後,該例項內部會包含一個指標指向建構函式的原型物件,這個指標叫 proto ,因此可以透過下面的圖來表示上面例子的程式碼。
因此透過上面的圖不難得出,js 中獲取原型的方法有如下三種:
(1)person1.proto
(2)Object.getPrototype(person1)
(3)person1.constructor.prototype
同樣可以透過 isPrototypeOf() 方法來確定物件之間是否存在原型關係,Person.prototype.isPrototypeOf( person1 )返回值為 true 。當然也可以如下使用Object.getPrototype(person1).name返回值為“ xiaoming ”。再來看下下面的這段程式碼:
function Person() {}
Person.prototype.name = "xioming";
Person.prototype.sayHello = function () {
console.log(this.name);
}; var person1 = new Person();
person1.name="xiaohong" console.log(person1.name);//“xiaohong”
透過上面的程式碼不難得出物件屬性的訪問順序,每當程式碼中讀取某個物件的屬性是,都會執行一次搜尋,目標是給定名字的屬性,搜尋首先從物件例項本身開始,如果在例項中找到了具有給定名字的屬性,則返回該屬性的值,如果沒有找到,則會繼續搜尋__proto__指標指向的原型物件,在原型物件中找到具有相同名字的屬性。雖然可以透過物件例項訪問儲存在原型物件中的值,但是不能透過獨享例項重新原型中的值,如果我們在例項中新增一個屬性,而該屬性與原型中的屬性同名,那麼就在例項中建立該屬性,該屬性就會遮蔽原型物件中的那個屬性。即新增了同名屬性後,這個屬性就會阻止我們訪問原型中的屬性。即使我們把這個屬性值設定為null,也只會在例項中訪問這個屬性,不會恢復對原型的同名屬性的訪問,要想恢復,只能使用 delete 運算子完全刪除該例項屬性。因此,官方也提供了一個 hasOwnProperty() 方法來判斷該屬性是否屬於例項物件,如果是則返回 true,否則返回 false 。
最後總結得出原型,建構函式,例項物件三者之間的關係如下:
(2)原型與 in 運算子
使用 in 運算子有兩種情況,一種是直接使用,另外一種是 for- in迴圈中使用,在單獨使用的時候,in 運算子會在透過物件能夠訪問屬性的時候返回 true ,無論該屬性存在於物件例項還是原型物件中。“name” in person1 返回 true ,因此結合 hasOwnProperty() 方法可以判斷屬性是存在於自身例項中,還是存在於原型物件中。使用 for-in 迴圈時,返回的是所有能夠在物件中可以訪問,可以列舉的屬性,其中既包含例項中的有包含原型中的,tostring(),valueOf()…但是由於瀏覽器版本限制,這種方式不推薦使用。
要取得物件上所有可列舉的例項屬性,可以透過 Object.keys() 方法,該方法接收一個物件作為引數,返回一個包含所有可列舉屬性的字串陣列。
(3)原型的原型關係如下圖:
2.原型鏈
理解原型鏈之前,先來看如下程式碼:
function Person() {}
Person.prototype.name = "xioming";
Person.prototype.sayHello = function () {
console.log(this.name);
}; var person1 = new Person();
console.log(person1.toString()); //[object Object]
這就是剛開始講到的,為什麼每一個物件都包含 tostring() 這個方法呢,有了原型的瞭解,這裡用到原型鏈,當我們訪問一個物件的屬性或者方法時,如果這個物件例項內部不存在這個屬性或者方法,那麼他會在原型物件裡找這個同名屬性或者方法,這個原型物件又有自己的原型,於是這麼一層一層找下去,也就產生了原型鏈這個概念,原型鏈的盡頭一般來說都是 Object.prototype ,所有者就產生了新建的物件都會存在 toString() 等方法。
總結
以上就是本文的全部內容,希望給讀者帶來些許的幫助和進步,方便的話點個關注,小白的成長之路會持續更新一些工作中常見的問題和技術點。
作者:丶Serendipity丶
原文出處:https://www.cnblogs.com/zaishiyu/p/14673223.html
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2331/viewspace-2797831/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 原型和原型鏈原型
- 面試題之原型、原型鏈、和繼承面試題原型繼承
- JS原型和原型鏈JS原型
- 原型和原型鏈梳理原型
- 理解原型和原型鏈原型
- ? 圖解原型和原型鏈圖解原型
- 圖解原型和原型鏈圖解原型
- 白話原型和原型鏈原型
- 關於原型和原型鏈的精闢解讀原型
- JS原型相關JS原型
- 原型和原型鏈的深入探索原型
- 【前端面試】原型和原型鏈前端面試原型
- javascript原型和原型鏈詳解JavaScript原型
- 深入理解原型和原型鏈原型
- 從問題入手,深入瞭解JavaScript中原型與原型鏈JavaScript原型
- 《JavaScript 闖關記》之原型及原型鏈JavaScript原型
- 重新認識原型和原型鏈三原型
- 重新認識原型和原型鏈一原型
- 重新認識原型和原型鏈二原型
- 如何理解JavaScript的原型和原型鏈?JavaScript原型
- 深入理解原型物件和原型鏈原型物件
- 徹底搞懂JavaScript原型和原型鏈JavaScript原型
- JS基礎-函式、物件和原型、原型鏈的關係JS函式物件原型
- 關於javascript的原型和原型鏈,看我就夠了(一)JavaScript原型
- 關於javascript的原型和原型鏈,看我就夠了(二)JavaScript原型
- 關於javascript的原型和原型鏈,看我就夠了(三)JavaScript原型
- 原型與原型鏈原型
- 前端面試題10----原型、原型鏈前端面試題原型
- js難點精解-----原型和原型鏈的關係和應用JS原型
- 徹底搞懂原型、原型鏈和繼承原型繼承
- 原型和原型鏈的抽筋拔骨原型
- JS 中原型和原型鏈深入理解JS原型
- JavaScript 原型及原型鏈JavaScript原型
- JavaScript原型與原型鏈JavaScript原型
- 原型物件與原型鏈原型物件
- JavaScript 原型 與 原型鏈JavaScript原型
- javascript——原型與原型鏈JavaScript原型
- JS 原型與原型鏈JS原型