理解js中的原型鏈,prototype與__proto__的關系

說到prototype,就不得不先說下new的過程。

我們先看看這樣一段代碼:

1<script type="text/javascript">
2 var?Person =?function?() { };
3 var?p =?new?Person();
4</script>

很簡單的一段代碼,我們來看看這個new究竟做了什么?我們可以把new的過程拆分成以下三步:

<1> var p={}; 也就是說,初始化一個對象p。

<2> p.__proto__=Person.prototype;

<3> Person.call(p);也就是說構造p,也可以稱之為初始化p。

關鍵在于第二步,我們來證明一下:

1<script type="text/javascript">
2var?Person =?function?() { };
3var?p =?new?Person();
4alert(p.__proto__ === Person.prototype);
5</script>

這段代碼會返回true。說明我們步驟2的正確。

那么__proto__是什么?我們在這里簡單地說下。每個對象都會在其內部初始化一個屬性,就是__proto__,當我們訪問一個對象的屬性 時,如果這個對象內部不存在這個屬性,那么他就會去__proto__里找這個屬性,這個__proto__又會有自己的__proto__,于是就這樣 一直找下去,也就是我們平時所說的原型鏈的概念。

按照標準,__proto__是不對外公開的,也就是說是個私有屬性,但是Firefox的引擎將他暴露了出來成為了一個共有的屬性,我們可以對外訪問和設置。

好,概念說清了,讓我們看一下下面這些代碼:

1<script type="text/javascript">
2var?Person =?function?() { };
3 Person.prototype.Say =?function?() {
4 alert("Person say");
5}
6var?p =?new?Person();
7p.Say();
8</script>

這段代碼很簡單,相信每個人都這樣寫過,那就讓我們看下為什么p可以訪問Person的Say。

首先var p=new Person();可以得出p.__proto__=Person.prototype。那么當我們調用p.Say()時,首先p中沒有Say這個屬性, 于是,他就需要到他的__proto__中去找,也就是Person.prototype,而我們在上面定義了 Person.prototype.Say=function(){}; 于是,就找到了這個方法。

好,接下來,讓我們看個更復雜的。

01<script type="text/javascript">
02var?Person =?function?() { };
03 Person.prototype.Say =?function?() {
04 alert("Person say");
05}

?

06Person.prototype.Salary = 50000;

?

07var?Programmer =?function?() { };
08Programmer.prototype =?new?Person();
09Programmer.prototype.WriteCode =?function?() {
10 alert("programmer writes code");

?

11};

?

?

12Programmer.prototype.Salary = 500;

?

13var?p =?new?Programmer();
14p.Say();
15p.WriteCode();
16alert(p.Salary);
17</script>

我們來做這樣的推導:

var p=new Programmer()可以得出p.__proto__=Programmer.prototype;

而在上面我們指定了Programmer.prototype=new Person();我們來這樣拆分,var p1=new Person();Programmer.prototype=p1;那么:

p1.__proto__=Person.prototype;

Programmer.prototype.__proto__=Person.prototype;

由根據上面得到p.__proto__=Programmer.prototype。可以得到p.__proto__.__proto__=Person.prototype。

好,算清楚了之后我們來看上面的結果,p.Say()。由于p沒有Say這個屬性,于是去p.__proto__,也就是 Programmer.prototype,也就是p1中去找,由于p1中也沒有Say,那就去p.__proto__.__proto__,也就是 Person.prototype中去找,于是就找到了alert(“Person say”)的方法。

其余的也都是同樣的道理。

這也就是原型鏈的實現原理。

最后,其實prototype只是一個假象,他在實現原型鏈中只是起到了一個輔助作用,換句話說,他只是在new的時候有著一定的價值,而原型鏈的本質,其實在于__proto__!

轉載于:https://www.cnblogs.com/chengjun/p/5237288.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/272274.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/272274.shtml
英文地址,請注明出處:http://en.pswp.cn/news/272274.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C#抓取網頁HTML內容

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Net; using System.Text; using System.IO; using System.Text.RegularExpressions; namespace Web { /// <summary> /// 公共方法類 /// </summary> p…

項目一感應垃圾桶(Wemos)

硬件材料&#xff1a; Wemos D1、SG90舵機、HC-SR04、杜邦線若干、蜂鳴器3.3V&#xff08;可有可無&#xff09; 軟件材料&#xff1a; arduino IDE編譯器、USB轉串口驅動 Wemos D1&#xff1a; 特性&#xff1a; 基于ESP-8266EX及arduino做的一個融合arduino兼容&#xff0…

docker刪除本地所有鏡像

docker rmi -f ${docker images -qa}

PAT1069. The Black Hole of Numbers

//這是到水題&#xff0c;之前因為四位數的原因一直不能A&#xff0c;看了別人的程序&#xff0c;才明白&#xff0c;不夠四位的時候沒考慮到&#xff0c;坑啊。。。。。臉打腫 #include<cstdio>#include<algorithm>using namespace std;int main(){ //freopen(&qu…

WiFi避障小車

硬件清單&#xff1a; Wemos D1&#xff08;支持AP模式也就是路由模式和STA模式也就是上網設備&#xff09;、超聲波模塊、小車、L9110s步進電機控制器 軟件&#xff1a; eclipse、arduino IDE WiFi配置參考博文 ESP8266WiFi庫: 從上圖中可以看出ESP8266WiFi庫主要包含Stati…

yum常用命令整理

yum命令的形式一般如下。要說明的是以下演示中所使用到的PACKAGE、GROUP都是變量&#xff0c;需要保證運行yum命令的主機能連接外網&#xff0c;否則大部分命令將由于沒有網絡連接而不能輸出結果。yum [options] [command] [package]#以下演示中大寫的單詞是變量1.安裝操作yum …

CSS3 2D 轉換

CSS3 2D 轉換 先看兼容性 transform屬性向應用元素應用2d 或者 3d裝換&#xff1b;該屬性允許我們進行旋轉&#xff0c;縮放&#xff0c;移動或者傾斜&#xff1b; 基本語法&#xff1a; transform: none|transform-functions;transform-function&#xff1a;這東東有n的函數可…

程序猿最喜歡說的30句話

雖然代碼總會有這個那個問題&#xff0c;但程序猿卻總有謎一般的從容和自信。上圖來自&#xff1a;《當程序出問題時程序員最喜歡說的30句話》來看看程序猿經常說的話&#xff1a;1、在我的電腦上是正常的啊。。。2、不可能出現這種情況的3、快了&#xff0c;已經完成了90%。4、…

linux環境下Ncurses實現貪吃蛇游戲

游戲說明&#xff1a; linux環境下基于Ncurses圖形庫的C語言小游戲。 Ncurses介紹&#xff1a; Ncurses(new curses)是一套編程庫&#xff0c;它提供了一系列的函數以便使用者調用它們去生成基于文本的用戶界面。 Ncurses是一個能提供功能鍵定義(快捷鍵),屏幕繪制以及基于文本…

韓順平循序漸進學java 第13講 抽象類.接口

13.1抽象類 13.1.1 概念 當父類的一些方法不能確定時&#xff0c;可以用abstract關鍵字來修飾該方法&#xff0c;稱為抽象方法&#xff0c;用abstract來修飾該類&#xff0c;稱為抽象類。 13.1.2 抽象類-深入討論 抽象類是java中一個比較重要的類&#xff1a; 1、用abstract關鍵…

C#實現簡體繁體轉換代碼示例

//簡體轉繁體 public static string _ConvertChinTrad(string strInput) { EncodeRobert edControl new EncodeRobert(); string strResult ""; if (strInput null) return strResult; if (strInput.ToString().Length > 1) strResult edControl.SCTCConvert(…

java基礎JDK的安裝和環境變量的配置

JRE和JDK&#xff1a; JRE是java程序運行時環境&#xff0c;包含JVM&#xff08;相當于java在不同操作系統上運行時java和操作系統之間的翻譯&#xff0c;保證java程序的跨平臺&#xff09;和運行時所需要的核心庫。所以我們想要運行一個已有的java程序&#xff0c;那么只需要…

C#通過SMTP發送郵件代碼示例

1、新建SMTP.cs類庫文件 public class SMTP { /// <summary> /// SMTP服務器 /// </summary> public string smtp { get; set; } /// <summary> /// SMTP服務器端口 /// </summary> public int port { get; set; } /// <summary> /// 發件人 ///…

docker下載tomact

docker run -it -p 8080:8080 tomcat 比如下載tomcat,你現在去訪問&#xff0c;先訪問docker里面的tomcat, 左邊的8080是對外暴露的服務端口&#xff0c;對應著右邊的8080是tomact的實際端口 下載tomcat 啟動tomcat docker run -it -p 8080:8080 tomcat

Wijmo 2016年藍圖

2015年很快就過去了&#xff0c;這是 Wijmo 重要的一年&#xff0c;尤其是對 Wijmo5。脫離傳統的小部件&#xff0c;重新寫一套 JS 控件&#xff0c;現在看來這個決定是正確的。用 TypeScript 寫 Wijmo5&#xff0c;意味著我們沒有任何依賴&#xff0c;不再需要 jQuery&#xf…

IDEA安裝和運行HelloWorld

IDEA安裝&#xff1a; IDEA中Hello World步驟&#xff1a; ① ②點擊創建空項目&#xff0c;下一步 ③ ④在打開后會彈出以下界面&#xff0c;然后點擊新建模塊 ⑤點擊新建模塊后出現以下界面&#xff0c;選擇java并選擇JDK的安裝路徑。 ⑥然后修改模塊名稱&#xff0c;點擊…

C#獲取電腦IP、MAC地址示例代碼

/// <summary> /// 使用 C# 自帶的類庫實現計算機信息獲取 /// </summary> public class DefaultDeviceInfo { public virtual string GetCpuId() { try { string cpuInfo " "; ManagementClass cimobject new ManagementClass("Win32_Processor…

docker運行隨機分配端口

docker run -d -it -P tomcat -P這個是大寫的P&#xff0c;表示隨機分配端口 執行后可以看到32768為隨機分配的端口&#xff0c;8080是tomcat端口 測試成功