簡單介紹 javascript 中 __proto__ 屬性的原理

來源:互聯網
上載者:User

標籤:javascript   proto   prototype   原形   原形鏈   

在 javascript 中我們會約定俗成,如果一個方法是被 new 出來使用的,那麼該方法名首字母通常會大寫,例如下面代碼塊中的 Person。(我們也可以把 Person 看成 java 或 c# 中的類)

var Person = function(name) {    this.name = name;}

在 javascript 中一個類被 new 出來的具體過程如下:

// 初始化一個對象 pvar p = new Person();
// 初始化一個對象 pvar p = {};p.__proto__ =  Person.prototype;Person.call(p);

以上兩段代碼的作用完全一樣,關鍵在第2段代碼的第2行,我們來證明一下:

var p = new Person();console.log(p.__proto__ ===  Person.prototype); // true

上面這段代碼返回的true,說明我們第2段代碼是正確的。

那麼__proto__是什嗎?
  • 簡單來說,在 javascript 中每個對象都會有一個 __proto__ 屬性,當我們訪問一個對象的屬性時,如果這個對象內部不存在這個屬性,那麼他就會去 __proto__ 裡找這個屬性,這個 __proto__ 又會有自己的 __proto__,於是就這樣一直找下去,也就是我們平時所說的原型鏈的概念。

  • 按照標準,__proto__ 是不對外公開的,但是 chrome 的引擎卻將他暴露了出來成為了一個公有屬性,我們可以對其進行訪問和賦值。但 ie 瀏覽器是不能訪問這個屬性的,所以不推薦大家直接操作這個屬性,以免造成瀏覽器安全色問題。

概念說清楚了,讓我們看段代碼:

var Person = function() {};Person.prototype.say = function() {    alert("Person say");}var p = new Person();p.say(); // Person say

這段代碼很簡單,相信每個人都這樣寫過,那就讓我們看下為什麼 p 可以訪問 Person 的 say。它等同於下面這段代碼:

var Person = function() {};Person.prototype.say = function() {    alert("Person say");}var p = {};p.__proto__ =  Person.prototype;Person.call(p);p.say(); // Person say

當我們調用 p.say() 時,p 中是沒有 say 屬性,於是到 p 的 __proto__ 屬性中去找,也就是 Person.prototype,而我們定義了 Person.prototype.say=function(){}; 於是,p 在 Person.prototype 中就找到了這個方法。
過程:p –> p.__proto__ === Person.prototype

接下來,讓我們看個更複雜的代碼。

var Person = function() {};Person.prototype.say = function() {    console.log("Person say");}Person.prototype.salary = 50000;var Programmer = function() {};Programmer.prototype = new Person();Programmer.prototype.writeCode = function() {    console.log("Programmer writes code");};Programmer.prototype.salary = 500;var p = new Programmer();p.say(); // Person sayp.writeCode(); // Programmer writes codeconsole.log(p.salary); // 500

大家先不要看下面的推導過程,自己試著推導一下。

var Person = function() {};Person.prototype.say = function() {    console.log("Person say");}Person.prototype.salary = 50000;var Programmer = function() {};Programmer.prototype = new Person();// 推導過程 --> // Programmer.prototype = {};// Programmer.prototype.__proto__ = Person.prototype;// Person.call(Programmer.prototype);Programmer.prototype.writeCode = function() {    console.log("Programmer writes code");};Programmer.prototype.salary = 500;var p = new Programmer();// 推導過程 --> // var p = {};// p.__proto__ = Programmer.prototype;// p.__proto__ = new Person();// p.__proto__.__proto__ = Pserson.prototype;// Person.call(p.__proto__);// Programmer.call(p);p.say(); // Person sayp.writeCode(); // Programmer writes codeconsole.log(p.salary); // 500

當我們調用 p.say() 時,p 中是沒有 say 屬性,於是到 p 的 __proto__ 屬性中去找,也就是 Programmer.prototype,此時 Programmer.prototype 是等於 new Person(),但 new Person() 中也沒有 say 屬性,於是又到 new Person().__proto__ 中找,此時 new Person().__proto__ 等於 Pserson.prototype 的,我們定義了 Person.prototype.say=function(){}; 所以,p 在 Person.prototype 中就找到了這個方法。
過程:
p –>
p.__proto__ === Programmer.prototype === new Person() –>
p.__proto__.__proto__ === Programmer.prototype.__proto__ === new Person().__proto__ === Pserson.prototype

調用 p.writeCode() 和 p.salary 也都是同樣的原理,大家自己推導。

重中之重,只要大家理解了下面段代碼,就能輕而易舉掌握 javascript 的原型鏈知識。

var Person = function(name) {    this.name = name;}// 初始化一個對象 pvar p = new Person();// 推導過程 --> // var p = {};// p.__proto__ =  Person.prototype;// Person.call(p);

參考資料:關於__proto__和prototype的一些理解

簡單介紹 javascript 中 __proto__ 屬性的原理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.