[Effective JavaScript 筆記]第30條:理解prototype、getPrototypeOf和__ptoto__之間的不同

来源:http://www.cnblogs.com/wengxuesong/archive/2016/06/13/5580231.html
-Advertisement-
Play Games

原型包括三個獨立但相關的訪問器。這三個單詞都是對單詞prototype做了一些變化。 C.prototype用於建立由new C()創建的對象的原型 Object.getPrototypeOf(obj)是ES5中用來獲取obj對象的原型對象的標準方法 obj.__proto__是獲取obj對象... ...


原型包括三個獨立但相關的訪問器。這三個單詞都是對單詞prototype做了一些變化。

  • C.prototype用於建立由new C()創建的對象的原型

  • Object.getPrototypeOf(obj)是ES5中用來獲取obj對象的原型對象的標準方法

  • obj.__proto__是獲取obj對象的原型對象的非標準方法

一個例子

要理解這些訪問器,我們拿一個典型的js數據類型作例子。
假設User構造函數需要通過new操作符來調用。它需要兩個參數,即姓名和密碼的哈希值,並將它們存儲在創建的對象中。
代碼如下:

function User(name,pwd){
    this.name=name;
    this.pwd=pwd;
}
User.prototype.toString=function(){
    return '[User '+this.name+']';
}
User.prototype.checkPwd=function(pwd){
    return hash(pwd)===this.pwd;
}
var u=new User('cedrusweng','$sdf99kaslf7');

根據上面的這個代碼我們可以畫出下麵這個圖,以表示各種關係。
我們每次在使用

function Fn(){
    
}

相當於調用下麵這樣

var fn=new Function([參數,]"函數體");

其中Function是一個構造函數,它的原型對象中包含我們之前講到過的call、apply、bind等屬性和方法。fn是Function的一個實例對象。
所以這裡的可以得到第一部分的圖
1465790019585
下麵再就構造函數User和它的原型對象之間的關係畫出一個圖
1465790054119

User函數帶有一個預設的prototype的屬性,其包含一個開始幾乎為空的對象。上面的例子中添加了兩個方法到原型對象中。當使用new操作符創建User的實例時,產生的對象u得到了自動分配的原型對象,該原型對象被存儲在User.prototype中。

最後來一張完整的圖
1465790103720

註意:new操作符調用構造函數,會產生一個新的對象實例,這個對象是以構造函數為模板,創建一份私有的性屬性和方法,所有的實例都會繼承原型對象。當訪問u.name時,u對象會首先在它的私有屬性中進行搜索,如果有則會返回,如果沒有,則會查找對象的原型對象。當訪問u.checkPwd時,私有屬性和方法不存在時,會返回存儲在User.prototype中的方法。

原型有關的方法

首先,構造函數的prototype屬性用來設置新實例的原型關係。
其次,ES5中的函數Object.getPrototypeOf()可以用於檢索現有對象的原型。
如上面的例子,可以使用下麵代碼來檢測對象u的原型對象。

Object.getPrototypeOf(u)===User.prototype;//true

最後,一些環境提供了非標準的方法檢索對象的原型,即特殊的__proto__屬性。這可作為在不支持ES5的Object.getPrototypeOf方法的環境中的一個相容方法。在這些環境中可以使用下麵代碼完成檢測

u.__proto__===User.prototype;//true

下麵畫一張圖,表明它們之間的關係
1465790241541

最後的說明

js程式員往往將User描述為一個類,儘管它跟一個函數差不多。js中的類本質上是一個構造函數與一個用於類(User.prototype)實例間共用方法的原型對象的結合。
下麵是一個User類的概念圖。
1465790380110
User函數給該類提供了一個公共的構造函數,而User.prototype是實例之間共用方法的一個內部實現。User和u的變通用法都不需要直接訪問原型對象。

提示

  • C.prototype屬性是new C()創建的對象的原型

  • Object.getPrototypeOf(obj)是ES5中檢索對象原型的標準函數

  • obj.__proto__是檢索對象原型的非標準方法

  • 類是由一個構造函數和一個關聯的原型組成的一種設計模式

附錄一:函數聲明

函數使用
var fn1=function(){};
var fn2=new Function('');
function fn3(){

}
這3種方式的函數,前面兩種都是屬性函數表達式,最後一種是函數聲明語法。函數實際上是對象,每個函數都是Function類型的實例,而且都與其他引用類型一樣具有屬性和方法。
具體可以看下圖來看對應的關係圖
1465791595254

函數表達式與函數聲明的區別

看到上面都是產生了函數的實例,但解析器會率先讀取函數聲明,並使其在執行任何代碼之前可用;函數表達式,則必須等到解析器執行到它所在的代碼行,才會真正被解釋。
可以根據函數表達式的特點,按條件給變數賦不同的函數表達式。

function createFn(a)
    var fn;
    if(a){
       fn=function(){console.log(1)}
    }else{
       fn=function(){console.log(2)}
    }
    return fn;
}
var fn1=createFn(true);
var fn2=createFn();
fn1();//1
fn2();//2

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、扁平化的設計風格。--淘寶 直接使用input。對其設置height。padding。使滑鼠居中又不會占滿輸入框。 2、背景是圖片的設計。--百度 試用span將input包裹起來。span設置背景。input設置margin。使用-webkit-appearance:none去除系統的預設樣式 ...
  • 1.filter()和not()方法 filter()和not()是一對反方法,filter()是過濾. filter()方法是針對元素自身。(跟has()方法有區別) 2.has()方法 has()方法表示的是包含的意思,它跟filter()方法是有區別的。has()方法有父子級關係。 3.nex ...
  • HTML5能為我們做的事兒很多,最為可口的就是語義化標簽的應用,如果你已經在Chrome或者其他支持HTML5的瀏覽器上用過它的牛x,那這篇文章對你一定有用,因為現在你也可以在IE上用到HTML5。 好吧!大前端今天的主題是:HTML5 Shiv 下麵是引用Google的html5.js文件,好處就 ...
  • HTML部分省略了,很簡單。 下麵是JavaScript ...
  • 手機涉及到填寫表單時,需要手機彈出自定義的輸入框,而非手機自帶的輸入鍵盤,如大寫數字等。 實現思路(考慮多種文本輸入形式): 首先,文本框獲取焦點時禁止手機彈出自帶的輸入鍵盤。 其次,顯示與關閉自定義的輸入鍵盤。 最後,點擊自定義的輸入鍵盤,做判斷使對應的input獲取值。 ...
  • ES5引入Object.getPrototypeOf函數作為獲取對象原型的標準API,但由於之前的很多js引擎使用了一個特殊的__proto__屬性來達到相同的目的。但有些瀏覽器並不支持這個__proto__屬性,所以並不是完全相容的。例如對於擁有null原型的對象,不同的環境結果就不同了。 ...
  • 眾所周知在前段的工作中註冊信息或獲取當前手機號信息等需求,我們基本上都要涉及到手機號驗證碼,在網路上搜索的案例雜亂無章,用的時候全是坑,真心不想用了,然後自己寫了一個獲取手機驗證碼的倒計時效果。有需求的伙伴們可以看看怎麼實現的。 如何獲取手機驗證碼? 小月不知道大家是利用什麼平臺去獲取驗證碼的,但是 ...
  • 前段時間做了一個項目,涉及到上傳本地圖片以及預覽的功能,正好之前瞭解過 html5(點擊查看更多關於web前端的有關資源) 可以上傳本地圖片,然後再網上看了一些demo結合自己的需求,終於搞定了。(PS : 不得不承認我這個人有多懶,沒有需求的時候我向來不主動去學習)。移動端完全支持哦!已測試。 下 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...