【前端芝士樹】Javascript的原型與原型鏈

【前端芝士樹】Javascript的原型、原型鏈以及繼承機制

前端的面試中經常會遇到這個問題,自己也是一直似懂非懂,趁這個機會整理一下

0. 為什么會出現原型和原型鏈的概念

1994年,網景公司(Netscape)發布了Navigator瀏覽器0.9版,但是剛開始的Js沒有繼承機制,更別提像同時期興盛的C++和Java這樣擁有面向對象的概念。在實際的開發過程中,工程師們發現沒有繼承機制很難解決一些問題,必須有一種機制能將所有的對象關聯起來。

Brendan Eich鑒于以上情況,但不想把Js設計得過為復雜,于是引入了new關鍵詞constructor構造函數來簡化對象的設計,引入了prototype函數對象來包含所有實例對象的構造函數的屬性和方法,引入了proto原型鏈的概念解決繼承的問題。

1. Javscript 函數和函數對象

var o1 = {}; 
var o2 =new Object();
var o3 = new f1();function f1(){}; 
var f2 = function(){};
var f3 = new Function('str','console.log(str)');
凡是直接或者間接通過 new Function() 創建的對象都是函數對象,其他的都是普通對象。

在上面的程序中,o1、o2、o3都是普通對象,f1、f2、f3都是函數對象。

2. 構造函數

function Person(name, age, job) {this.name = name;this.age = age;this.job = job;this.sayName = function() { alert(this.name) } 
}
var person1 = new Person('Zaxlct', 28, 'Software Engineer');
var person2 = new Person('Mick', 23, 'Doctor');
person1person2 都是 構造函數 Person 的實例。
實例的構造函數屬性(constructor)指向構造函數。

3. 原型對象

Person.prototype = {name:  'Zaxlct',age: 28,job: 'Software Engineer',sayName: function() {alert(this.name);}
}

每個函數對象都有一個 prototype 屬性,這個屬性就是函數的原型對象

每個對象都有 proto 屬性,但只有函數對象才有 prototype 屬性

clipboard.png

在默認情況下,所有的原型對象都會自動獲得一個 constructor(構造函數)屬性,這個屬性(是一個指針)指向 prototype 屬性所在的函數(Person)

Person.prototype.constructor == Person

而在Person這個對象進行實例化的時候,實際上是創建了一個它的實例對象并賦值給它的 prototype,所以得出以下結論:

原型對象(Person.prototype)是 構造函數(Person)的一個實例。

4. _proto_

JS 在創建對象(不論是普通對象還是函數對象)的時候,都有一個叫做__proto__ 的內置屬性,用于指向創建它的構造函數的原型對象,也就是prototype。

clipboard.png

Person.prototype.constructor == Person;
person1.__proto__ == Person.prototype;
person1.constructor == Person;

看下面一段代碼

Person.prototype.__proto__ === Object.prototype;

Person.prototype 是一個普通對象,我們無需關注它有哪些屬性,只要記住它是一個普通對象。
因為一個 普通對象的構造函數 === Object
所以 Person.prototype.__proto__ === Object.prototype

5. 原型鏈

原型鏈的形成是真正是靠__proto__ 而非prototype。
person1.__proto__ === Person.prototype;
Person.prototype.__proto__ === Object.prototype;
Object.prototype.__proto__ === null;
//Object.prototype.__proto__ === null,保證原型鏈能夠正常結束。Person.__proto__ === Function.prototype;
Object.__proto__ === Function.prototype;
Function.prototype.__proto__ === Object.prototype;

前面三項已經形成了一個原型鏈,那么后面代碼中Person和Object的__proto__都是Function.prototype呢?

所有函數對象的proto都指向Function.prototype,它是一個空函數(Empty function)
Number.__proto__ === Function.prototype  // true
Number.constructor == Function //trueBoolean.__proto__ === Function.prototype // true
Boolean.constructor == Function //trueString.__proto__ === Function.prototype  // true
String.constructor == Function //trueObject.__proto__ === Function.prototype  // true
Object.constructor == Function // trueFunction.__proto__ === Function.prototype // true
Function.constructor == Function //trueArray.__proto__ === Function.prototype   // true
Array.constructor == Function //trueRegExp.__proto__ === Function.prototype  // true
RegExp.constructor == Function //trueError.__proto__ === Function.prototype   // true
Error.constructor == Function //trueDate.__proto__ === Function.prototype    // true
Date.constructor == Function //true
所有的構造器都來自于 Function.prototype,甚至包括根構造器Object及Function自身。所有構造器都繼承了·Function.prototype·的屬性及方法。如length、call、apply、bind

所以我們再舉一個原型鏈的例子

let num = new Number();
num.__proto__ === Number.prototype;
Number.prototype.__proto__ === Function.prototype;
Funtion.prototype.__proto__ === Object.prototype;
Object.prototype.__proto__ === null;

也可看下圖的實現,更直觀。
clipboard.png

ok, 所以明白為什么Number、String、Array這樣的對象實例能繼承到Object的屬性以及原型鏈是怎么一回事了吧。

參考文章
最詳盡的 JS 原型與原型鏈終極詳解,沒有「可能是」。
三張圖搞懂JavaScript的原型對象與原型鏈 - 水乙 - 博客園
Javascript繼承機制的設計思想 - 阮一峰的網絡日志

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

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

相關文章

神奇的幻方2015提高組d1t1

題目描述 幻方是一種很神奇的N*N矩陣:它由數字1,2,3,……,N*N構成,且每行、每列及兩條對角線上的數字之和都相同。 當N為奇數時,我們可以通過以下方法構建一個幻方: 首先將1寫在第一行的中間。 之后,按如下方式從小到大…

goldengate mysql_使用GoldenGate實現MySQL到Oracle的數據實時同步

step 1: 配置mysql修改配置文件my.ini#for goldengatelog-bin "C:/mysql/logbin/logbin.log"binlog-format ROWlog-bin-index "C:\mysql\logindex"binlog_cache_size32mmax_binlog_cache_size512mmax_binlog_size512m添加數據庫用戶ggs,具有…

C# 反射之Activator用法舉例

概述程序運行時,通過反射可以得到其它程序集或者自己程序集代碼的各種信息,包括類、函數、變量等來實例化它們,執行它們,操作它們,實際上就是獲取程序在內存中的映像,然后基于這個映像進行各種操作。Activa…

MyBatis批量插入

轉載于:https://blog.51cto.com/12701034/1929672

狐貍文│區塊鏈發展的正路

(圖片出自網絡,版權歸原作者所有)最近看了一本書:《美國增長的起落》。這本書是大部頭,但看起來很過癮。通過對這本書的閱讀,我更新了自己對區塊鏈發展的理解。這一年,“區塊鏈”很熱&#xff0…

mysql 一主一備_Mysql一個主一備

Mysql主從復制 -- 一主一備主從復制原理:Mysql的主從復制是mysql本身自帶的一個功能,不需要額外的第三方軟件可以實現,其復制功能并不是copy文件實現的,而是借助binlog日志文件里面的SQL命令實現的主從復制,可以理解為…

解決安裝Weblogic domain卡住問題(Primeton BPS)

這兩天一直有一個問題困擾我,在suse10weblogic(920,923,100,103)上安裝bpm產品失敗。有些版本是創建domain的時候卡在create security information上,有些版本卡在安裝包start weblogic上。但是在winXPweblogic10.3bpm安裝成功。 經過幾番GOOGLE,終于找到…

cocos2d-js 熱更新具體解釋(一)

本文將會具體解說cocos2d-js下的熱更新機制。這篇內容先給大家介紹一下兩個manifest文件就當熱身了。首先介紹project.manifest: 舉個樣例 {"packageUrl" : "http://192.168.1.108/games/dragon_gold","remoteManifestUrl" : "…

Qt之水平/垂直布局(QBoxLayout、QHBoxLayout、QVBoxLayout)

簡述 QBoxLayout可以在水平方向或垂直方向上排列控件,由QHBoxLayout、QVBoxLayout所繼承。 QHBoxLayout:水平布局,在水平方向上排列控件,即:左右排列。 QVBoxLayout:垂直布局,在垂直方向上排列控…

Optaplanner終于支持多線程并行運行 - Multithreaded incremental solving

Optaplanner 7.9.0.Final之前,啟動引擎開始對一個Problem進行規劃的時候,只能是單線程進行的。也就是說,當引擎對每一個possible solution進行分數計算的過程中,細化到每個步驟(Caculation),都只能排隊在同一個線程中依…

python棋盤格_干貨必看 | Python的turtle庫之經典棋盤格

國際棋盤格是一個由9橫9縱的線組成的格子正方形,用Python的turtle庫進行繪制的時候,先做9橫9縱的線,再填上灰色小正方形,這就可以完成一個棋盤格了,下面是具體的操作步驟。(一)整體代碼1、import turtleimport turtle2…

一位技術老人給.NET初學者的一些建議

.NET平臺應用領域眾多,隨著這些年的不斷更新迭代,日趨臻善,也受到越來越多的開發者青睞。自從2000 年6 月22 日 微軟推出Microsoft.NET 戰略 ,至今已有22載,這些年新技術,新框架層出不窮,目不暇…

android 本地數據庫sqlite的封裝

單機android sqlite數據庫的實現,這個數據庫可與程序一起生成在安裝包中一、下載sqlite3.exe文件二、運行 cmd 轉到sqlite3.exe 所在目錄 運行 sqlite3.exe 數據庫名.db然后會出現sqlite>的命令提示符輸入創建表的語句, create table 表名&#xf…

ResourceManager中的Resource Estimator框架介紹與算法剖析

歡迎大家前往騰訊云社區,獲取更多騰訊海量技術實踐干貨哦~ 本文由宋超發表于云社區專欄 本文首先介紹了Hadoop中的ResourceManager中的estimator service的框架與運行流程,然后對其中用到的資源估算算法進行了原理剖析。 一. Resource Estimator Service…

幾十款 WPF 控件 - UI 庫,總有一款適合你

幾十款 WPF 控件 - UI 庫,總有一款適合你獨立觀察員 2022 年 10 月 16 日引言眾所周知,使用 WPF 框架能夠開發出功能強大、界面美觀的桌面端應用。能夠達到這個效果,各種 WPF 的控件庫、UI 庫功不可沒。所以,想著能不能收集一下目…

mysql將系統權限授予用戶_mysql創建用戶并授予權限

1、create schema [數據庫名稱] default character set utf8 collate utf8_general_ci;--創建數據庫采用create schema和create database創建數據庫的效果一樣。2、create user ‘[用戶名稱]‘‘%‘ identified by ‘[用戶密碼]‘;--創建用戶密碼8位以上,包括&#…

Android Studio導出jar包

Eclipse直接有個Export,可以直接導出jar包。AS相對Eclipse變化很大,編譯腳本變成了Gradle,各種導包操作都有差異。 下面是AS導出jar的過程: 第一步,修改app下的build.grade。 apply plugin: com.android.application修改為 apply …

GitHub Actions構建鏡像并部署服務

目的通過GitHub的Actions來(白嫖)部署.Net服務到阿里云服務器。環境準備需要一個阿里云服務器并且該服務器還安裝了docker環境,如果環境安裝不清楚可以查看之前的文章。創建鏡像倉庫在阿里云的容器鏡像服務中,創建一個鏡像倉庫用來存儲我們測試的鏡像&am…

20165232 緩沖區溢出漏洞實驗

緩沖區溢出漏洞實驗 實驗準備 實驗環境需要32位的Linux系統,需要下載安裝一些用于編譯 32 位 C 程序的軟件包,代碼如下: $ sudo apt-get update$ sudo apt-get install -y lib32z1 libc6-dev-i386$ sudo apt-get install -y lib32readline-gp…

使用qt的qtcore庫怎么包含_GitHub - coologic/QtCoreExamples: QtCore模塊相關類庫范例

QtCoreExamplesQtCore模塊相關類庫范例QJsonExampleQt進行Json文件讀寫范例QXmlExampleQt使用QXmlStreamReader/QXmlStreamWriter類進行XML文件讀寫范例非不是使用QtXML模塊QSharedMemoryExampleQt使用QSharedMemory實現共享內存QSettingsExample(Blog)Qt使用QSettings配置讀寫…