1. 程式人生 > >javascript原型鏈追根溯源

javascript原型鏈追根溯源

寫在前面

上篇文章詳細解釋了一下prototype與__proto__兩個屬性的差異與聯絡。這裡涉及到原型鏈的概念,所以我就又生出了疑問,javascript中既然所有東西都是物件,而他們又是相互繼承的關係,子又生孫,孫又生子,無窮匱也,那他們的源頭又在哪裡,換句話說,他們共同的祖先在哪裡。所以,這回我通過對Function與Object兩個物件的實驗,試圖弄清這個事兒。

兩個老祖先:Function.prototype與Object.prototype

我把我通過實驗得到的結論畫成了類圖,只想知道結論的朋友看這張圖就可以了。這個圖裡有兩個物件是所有物件的始祖,Object.prototype與Function.prototype,它倆是這篇文章的主角,如下:

類圖

原型鏈的盡頭:大祖宗Object.prototype

請記住,Object.prototype是一切物件原型的盡頭,在javascript中,如果你不故意把__proto__賦值成null,那只有Object.prototype這一個物件的__proto__天然就是null。

console.log(Object.prototype.__proto__ === null);//true

我想既然Object.prototype.__proto的值天然是null,那我人工給它賦值會怎麼樣,我就很邪惡的嘗試了一下:

Object.prototype.__proto__ = {A:'a'
}; console.log(Object.prototype.__proto__);

結果報了一大堆很噁心的錯誤:

Error: Cyclic __proto__ value
    at Object.__proto__ (native)
    at Object.<anonymous> (/Users/myc/Code/test/index.js:1:90)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module
.js:355:32) at Function.Module._load (module.js:310:12) at Function.Module.runMain (module.js:501:10) at startup (node.js:129:16) at node.js:814:3

大概應該就是Object.__proto__是本地方法,不能更改之類的,看來javascript肯定還是有內部機制保護它的。

接著我又嘗試了一下去給其他的物件的__proto__賦值,都沒有報錯,包括Function.prototype.__proto__。

Function.prototype.__proto__ = {A:"a"};
Function.__proto__ = {A:"a"};
Object.__proto__ = {A:"a"};

Object.prototype的兒子們

Object.prototype最重要的一個兒子應該就算是Function.prototype了,它應該算是整個javascript家族裡的二祖宗,我們後面細說。這裡我們先記住Function.prototype繼承自Object.prototype。

console.log(Function.prototype.__proto__ === Object.prototype);//true

作為大祖宗,Object.prototype還有很多比較正常的兒子們,那就是我們自行建立的object型別物件,它們的原型直接繼承自Object.prototype。如下程式碼可以佐證:

var A = {};
var B = new Object();
console.log(A.__proto__ === Object.prototype);//true
console.log(B.__proto__ === Object.prototype);//true

Object.prototype的type是object

console.log(typeof Object.prototype)//object

記住,用typeof來判斷Object.prototype時,型別為object。

function型別的始祖:二祖宗Function.prototype

作為家族中的二祖宗,其也是子嗣眾多,下面我們一一道來。

Function與Object

Function.prototype最重要的兩個兒子應該就是Function與Object了。

console.log(Function.__proto__ === Function.prototype);//true
console.log(Object.__proto__ === Function.prototype);//true

這裡如果不太清楚會比較繞,你會發現Function.__proto__Function.prototype指向同一個物件。其實,這個地方,只需要清楚Object.prototype、Function.prototype、Object、Function是四個不同的物件就不會亂了,再結合我前面畫的類圖。

這裡還需要注意一點Function與Object的型別都是function,這裡也許看上去比較彆扭,但只需分清,Function與Object都只是一個描述符或者叫變數名,object與function是兩個型別名。

Function與Object可以分別作為建構函式建立function型別的物件與object的物件。

var fun = new Function();
var obj = new Object();

其他內建引用物件

javascript中還有其他的幾個內建引用物件,Array、Date、Error、RegExp,它們的__proto__都指向Function.prototype。它們各自創建出來的物件都指向它們本身的prototype。

console.log(Array.__proto__ === Function.prototype);//true
console.log(Date.__proto__ === Function.prototype);//true
console.log(Error.__proto__ === Function.prototype);//true
console.log(RegExp.__proto__ === Function.prototype);//true

自己定義的函式

我們自行建立的函式,其原型都是Function.protopyte。

var A = function(){};
var B = new Function();
console.log(A.__proto__ === Function.prototype);//true
console.log(B.__proto__ === Function.prototype);//true

Function.prototyte的type是function

Function.prototype的型別是function,這裡有一點比較特殊,它是唯一一個沒有prototype屬性的function型別物件。

console.log(typeof Function.prototype)//function
console.log(Function.prototype.prototype)//undefined

Object.prototype與Function.prototype中的屬性

可以用Object.getOwnPropertyNames將一個物件的屬性用陣列輸出,這裡我們也可以用它來輸出Object.prototype與Function.prototype的屬性。

console.log(Object.getOwnPropertyNames(Function.prototype));
console.log(Object.getOwnPropertyNames(Object.prototype));

孤傲的null

如果你用typeof判斷null,他的型別也是object。不過他不具備任何屬性,也沒有原型。你在其下訪問任何東西都會報錯,這應該也是javascript的某種保護機制。

總結

當我們把原型鏈向上追溯的時候,會發現最上游的幾個物件相互引用的似乎有點兒亂,但如果你細想想,都是有道理的。這裡主要就涉及四個物件:Object.prototype、Function.prototype、Object、Function。分別把它們的prototype與__proto__屬性的指向搞清,就能理清楚這個關係。

相關推薦

javascript原型追根溯源

寫在前面 上篇文章詳細解釋了一下prototype與__proto__兩個屬性的差異與聯絡。這裡涉及到原型鏈的概念,所以我就又生出了疑問,javascript中既然所有東西都是物件,而他們又是相互繼承的關係,子又生孫,孫又生子,無窮匱也,那他們的源頭又在哪裡,

JavaScript--原型

doctype .html 構造函數 har www 關系 例子 cnblogs cto 原型鏈 一.構造函數與原型鏈的關系 博客中:http://www.cnblogs.com/shuiyi/p/5305435.html 的圖 例子:

JavaScript學習總結(十七)——Javascript原型的原理

學習總結 swp 是個 個人 {} 內存地址 ret nlb SDR 一、JavaScript原型鏈   ECMAScript中描述了原型鏈的概念,並將原型鏈作為實現繼承的主要方法。其基本思想是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。在JavaScript中

JavaScript——原型 — instanceof

type prototype his col 屬於 con pri ole console //構造函數 function Fn (name,age) { this.name = name; } //顯示原型 Fn.prototype.alertName = f

javascript原型繼承

UNC 返回值 object def fin java tostring cti 指向 當定義一個函數的時候,函數對象就會默認帶一個prototype對象屬性。 通過new去構造一個對象(obj),它的原型會指向構造器的prototype屬性(foo.prototype)。

明白JavaScript原型和JavaScrip繼承

creat oms 訪問 函數的原型 form eat sub rms amp 原型鏈是JavaScript的基礎性內容之一。其本質是JavaScript內部的設計邏輯。 首先看一組代碼: 1 <script type="text/javascript"&g

JavaScript原型和繼承

eat 過渡 存在 es6 向上 reset 保護 foo 創建 1.概念   JavaScript並不提供一個class的實現,在ES6中提供class關鍵字,但是這個只是一個語法糖,JavaScript仍然是基於原型的。JavaScript只有一種結構:對象。每

淺談 JavaScript 原型

概述 在 JavaScript 中有種說法叫 “萬物皆物件”,就是說無論是建構函式建立的例項,建構函式本身、原型物件、陣列、函式本質上都是物件,都擁有 __proto__ 屬性,即隱式原型,所有函式都擁有 prototype屬性,即顯式原型(僅限函式),原型物件

詳談JavaScript原型

轉自部落格園:https://www.cnblogs.com/chengzp/p/prototype.html                           &

深入理解JavaScript原型與繼承

原型鏈 原型鏈一直都是一個在JS中比較讓人費解的知識點,但是在面試中經常會被問到,這裡我來做一個總結吧,首先引入一個關係圖: 一.要理解原型鏈,首先可以從上圖開始入手,圖中有三個概念: 1.建構函式: JS中所有函式都可以作為建構函式,前提是被new操作符操作; function P

JavaScript 原型 實戰

最近看到這麼一道題 如何讓下面的程式碼執行: const a = [1, 2, 3, 4, 5]; // Implement this a.multiply(); console.log(a); // [1, 2, 3, 4, 5, 1, 4, 9, 16, 25] 執

如何理解JavaScript原型?

原理 每一個物件都是有原型的 , 用物件的 prototype() 就可以得到物件的原型 , 在得到物件原型之後就可以獲取原型的原型 , 直到得到的是一個null為止 , 這個過程被稱作原型鏈 首先原型也是物件,也叫原型物件 . 原型可以擴充套件建

JavaScript原型與繼承操作例項總結

本文例項講述了JavaScript原型鏈與繼承操作。分享給大家供大家參考,具體如下: 1. JavaScript繼承 JavaScript繼承可以說是發生在物件與物件之間,而原型鏈則是實現繼承的主要方法; 1.1 原型鏈 利用原型讓一引用型別繼承另一個引用型別的屬性和方法。

深入解析javascript原型

首先我們要弄清楚幾個概念: 一、函式物件和普通物件 我們定義的function,其實是Function物件的一個例項,如:function a(name){this.name=name}相當於var a=new Function('name','this.name=nam

JavaScript原型與繼承內容總結

總結 第三天: 1. JavaScript繼承 JavaScript繼承可以說是發生在物件與物件之間,而原型鏈則是實現繼承的主要方法; 1.1 原型鏈 利用原型讓一引用型別繼承另一個引用型別的屬性和方

Javascript原型詳解

js建立之初,正值java大行其道,面向物件程式設計春風正盛,js借鑑了java的物件機制,但僅是看起來像,也就是js的建構函式,如下: function People(age) { this.age = age; this.getAge = function

淺談JavaScript原型繼承方式與閉包

JavaScript中的繼承方式有兩種,一種是通過call或apply方法借用建構函式,另一種方法則是通過原型來繼承。這篇文章用於梳理自己關於prototype繼承的知識點,也略微涉及一點點閉包的概念。 關於原型 在JavaScript中每當我們建立一個Fu

JavaScript 原型與繼承

4.3 linu mod 管理員 art 狀態 ado 最好的 -s 用戶權限的相關命令: 權限類型: 01 讀 read r 4 02 寫 write w 2 03 執行 excute x 1 組權限: 開發組:將所有開發人員添加到一個組中,這個組中所有人就有

Javascript原型梳理

-s 徹底 意義 代碼 key nbsp 當前 ring 語言 先來個簡單的代碼: function Info(name, age){ this.name = name; this.age = age; this.message = function (

圖解javascript原型

圖解javascript原型鏈 作者: HerryLo 本文永久有效連結: https://github.com/AttemptWeb...... 原型鏈和原型物件是js的核心,js以原型鏈的形式,保證函式或物件中的方法、屬性可以讓向下傳遞,按照面向物件的說法,這就是繼承。而js通過原型鏈才得以實現