最詳盡的 JS 原型與原型鏈終極詳解,包你學廢!(一)

来源:https://www.cnblogs.com/coderjava/archive/2020/06/12/13099767.html
-Advertisement-
Play Games

一. 普通對象與函數對象 JavaScript 中,萬物皆對象!但對象也是有區別的。分為普通對象和函數對象,Object 、Function 是 JS 自帶的函數對象。下麵舉例說明 var o1 = {}; var o2 =new Object(); var o3 = new f1(); ​ fun ...


一. 普通對象與函數對象

JavaScript 中,萬物皆對象!但對象也是有區別的。分為普通對象和函數對象,Object 、Function 是 JS 自帶的函數對象。下麵舉例說明

 

 var o1 = {}; 
 var o2 =new Object();
 var o3 = new f1();
 ​
 function f1(){}; 
 var f2 = function(){};
 var f3 = new Function('str','console.log(str)');
 ​
 console.log(typeof Object); //function 
 console.log(typeof Function); //function  
 ​
 console.log(typeof f1); //function 
 console.log(typeof f2); //function 
 console.log(typeof f3); //function   
 ​
 console.log(typeof o1); //object 
 console.log(typeof o2); //object 
 console.log(typeof o3); //object

 

在上面的例子中 o1 o2 o3 為普通對象,f1 f2 f3 為函數對象。怎麼區分,其實很簡單,凡是通過 new Function() 創建的對象都是函數對象,其他的都是普通對象。f1,f2,歸根結底都是通過 new Function()的方式進行創建的。Function Object 也都是通過 New Function()創建的

一定要分清楚普通對象和函數對象,下麵我們會常常用到它。

二. 構造函數

我們先複習一下構造函數的知識:

 

 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');

 

上面的例子中 person1 和 person2 都是 Person 的實例。這兩個實例都有一個 constructor (構造函數)屬性,該屬性(是一個指針)指向 Person。 即:

 

   console.log(person1.constructor == Person); //true
   console.log(person2.constructor == Person); //true

 

我們要記住兩個概念(構造函數,實例): person1 和 person2 都是 構造函數 Person 的實例 一個公式: 實例的構造函數屬性(constructor)指向構造函數。

三. 原型對象

在 JavaScript 中,每當定義一個對象(函數也是對象)時候,對象中都會包含一些預定義的屬性。其中每個函數對象都有一個prototype 屬性,這個屬性指向函數的原型對象。(先用不管什麼是 __proto__ 第二節的課程會詳細的剖析)

 

 function Person() {}
 Person.prototype.name = 'Zaxlct';
 Person.prototype.age  = 28;
 Person.prototype.job  = 'Software Engineer';
 Person.prototype.sayName = function() {
   alert(this.name);
 }
   
 var person1 = new Person();
 person1.sayName(); // 'Zaxlct'
var person2 = new Person();
 person2.sayName(); // 'Zaxlct'
 ​
 console.log(person1.sayName == person2.sayName); //true

 

我們得到了本文第一個「定律」:

 

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

那什麼是原型對象呢? 我們把上面的例子改一改你就會明白了:

 

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

 

原型對象,顧名思義,它就是一個普通對象(廢話 = =!)。從現在開始你要牢牢記住原型對象就是 Person.prototype ,如果你還是害怕它,那就把它想想成一個字母 A: var A = Person.prototype


在上面我們給 A 添加了 四個屬性:name、age、job、sayName。其實它還有一個預設的屬性:constructor

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

上面這句話有點拗口,我們「翻譯」一下:A 有一個預設的 constructor 屬性,這個屬性是一個指針,指向 Person。即: Person.prototype.constructor == Person


在上面第二小節《構造函數》里,我們知道實例的構造函數屬性(constructor)指向構造函數person1.constructor == Person

這兩個「公式」好像有點聯繫:

 

 person1.constructor == Person
 Person.prototype.constructor == Person

 

person1 為什麼有 constructor 屬性?那是因為 person1 是 Person 的實例。 那 Person.prototype 為什麼有 constructor 屬性??同理, Person.prototype (你把它想象成 A) 也是Person 的實例。 也就是在 Person 創建的時候,創建了一個它的實例對象並賦值給它的 prototype,基本過程如下:

 

 
var A = new Person();
  Person.prototype = A;
 // 註:上面兩行代碼只是幫助理解,並不能正常運行

 

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


原型對象其實就是普通對象(但 Function.prototype 除外,它是函數對象,但它很特殊,他沒有prototype屬性(前面說道函數對象都有prototype屬性))。看下麵的例子:

 

  function Person(){};
  console.log(Person.prototype) //Person{}
  console.log(typeof Person.prototype) //Object
  console.log(typeof Function.prototype) // Function,這個特殊
  console.log(typeof Object.prototype) // Object
  console.log(typeof Function.prototype.prototype) //undefined

 

Function.prototype 為什麼是函數對象呢?

 

  var A = new Function ();
  Function.prototype = A;

 

上文提到凡是通過 new Function( ) 產生的對象都是函數對象。因為 A 是函數對象,所以Function.prototype 是函數對象。

那原型對象是用來做什麼的呢?主要作用是用於繼承。舉個例子:

 

   var Person = function(name){
     this.name = name; // tip: 當函數執行時這個 this 指的是誰?
   };
   Person.prototype.getName = function(){
     return this.name;  // tip: 當函數執行時這個 this 指的是誰?
   }
   var person1 = new person('Mick');
   person1.getName(); //Mick

 

從這個例子可以看出,通過給 Person.prototype 設置了一個函數對象的屬性,那有 Person 的實例(person1)出來的普通對象就繼承了這個屬性。具體是怎麼實現的繼承,就要講到下麵的原型鏈了。

小問題,上面兩個 this 都指向誰?

 

 
 var person1 = new person('Mick');
   person1.name = 'Mick'; // 此時 person1 已經有 name 這個屬性了
   person1.getName(); //Mick  

 

故兩次 this 在函數執行時都指向 person1。


總結

在這裡我給大家準備了很多的學習資料免費獲取,包括但不限於技術乾貨、大廠面試題系列、技術動向、職業生涯等一切有關程式員的分享.

web前端小白進階方法筆記,學習資料,面試題和視頻,項目源碼免費領取,通過努力追到自己的女神,走向人生巔峰

 


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

-Advertisement-
Play Games
更多相關文章
  • electron-vue報錯:Webpack ReferenceError: process is not defined 博客說明 文章所涉及的資料來自互聯網整理和個人總結,意在於個人學習和經驗彙總,如有什麼地方侵權,請聯繫本人刪除,謝謝! 問題截圖 問題說明 在搭建electron的項目的時候出 ...
  • 前置 點擊按鈕切換搜索引擎 搜索框跟隨切換改變樣式 使用 vue 最快了 template 為了方便擴展,使用 v-for 迴圈渲染出按鈕,綁定切換搜索引擎的 method , 傳入不同名稱以區別搜索引擎。按鈕的樣式也動態綁定。 輸入框動態綁定樣式,在點擊按鈕切換搜索引擎時,搜索框綁定的樣式對應的 ...
  • Vue 3尚未正式發佈,但是維護者已經發佈了Beta版本,供我們的參與者嘗試並提供反饋。 如果你想知道Vue 3的主要功能和主要變化是什麼,那麼我將在這篇文章中重點介紹一下,告訴你使用Vue 3 beta 9創建一個簡單的應用程式。 我將介紹儘可能多的新內容,包括fragments,teleport ...
  • 0. 前言 也許我們通過 jquery 的迴圈方法進行數組遍歷,但是當不符合條件時,怎麼跳出當前迴圈?(即用each方法內,當不滿足條件時想break跳出迴圈體,想continue繼續執行下一個迴圈遍歷),我們經常會習慣JS中的break何continue,但是使用之後沒有效果,因為在JQuery中 ...
  • Webpack 5的模塊聯邦提供載入部分編譯好的代碼能力,這個似乎會成為微前端架構的標準實現。 Webpack只是我分享的一小點,我是08年出道的高級前端架構師,有問題或者交流經驗可以進我的扣扣裙 519293536 我都會儘力幫大家哦 引言 在當前的微前端實現中,我們需要通過一系列的技巧去實現。正 ...
  • 摘要 數據是我們每天都在接觸的東西,我們需要清晰的瞭解去瞭解數據的變化趨勢,就需要讓數據可視化。最近在接觸學習antd的社區精選組件,上一篇文章主要是講了高德地圖的應用,這次我們就來分享下G2Plot在react中實現可視化數據圖表的簡單應用。 Ant Design Charts的使用方法 安裝 n ...
  • 摘要 平常生活中,地圖導航是必不可少的,最近在學習Ant Design,瞭解了下社區的精選組件,看到了與地圖相關的精品組件庫,高德地圖組件庫。所以記錄下這次高德地圖的使用心得,既可以提升自己的業務多樣性,也可以分享給需要的小伙伴。 React-Amap用法 安裝 npm install --save ...
  • 本文主要介紹如何通過CLI命令行(也就是終端或者cmd打開的那個shell視窗)實現 js和 css 的合併壓縮。 uglifyjs 合併壓縮 js: 1.安裝node 這一步就不多說了,下載node自行安裝。 2.安裝 uglifyjs 全局安裝: npm install -g uglify-js ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...