JS中原型鏈的理解

来源:http://www.cnblogs.com/DF-fzh/archive/2016/06/27/5619319.html
-Advertisement-
Play Games

在談原型鏈之前,我們首先要瞭解自定義函數與 Function 之間是什麼關係,而構造函數、原型和實例之間又存在什麼千絲萬縷的關係呢?其實,所有的函數都是 Function 的實例。在構造函數上都有一個原型屬性 prototype,該屬性也是一個對象;那麼在原型對象上有一個 constructor 屬 ...


  在談原型鏈之前,我們首先要瞭解自定義函數與 Function 之間是什麼關係,而構造函數、原型和實例之間又存在什麼千絲萬縷的關係呢?其實,所有的函數都是 Function 的實例。在構造函數上都有一個原型屬性 prototype,該屬性也是一個對象;那麼在原型對象上有一個 constructor 屬性,該屬性指向的就是構造函數;而實例對象上有一個 _proto_  屬性,該屬性也指向原型對象,並且該屬性不是標準屬性,不可以用在編程中,該屬性用於瀏覽器內部使用。

1    // _proto_
2 在函數里有一個屬性prototype
3 由該函數創建的對象預設會連接到該屬性上
4     //prototype 與 _proto_ 的關係
5 _proto_是站在對象角度來說的
6 prototype 是站在構造函數角度來說的

  下麵,我們來看圖說話。

1、構造函數、原型和實例之間的關係         ①+Object     ②+Function+Object+Array

  

  瞭解這些之後,我們再來討論什麼是原型鏈。說白了,其實就是有限的實例對象和原型之間組成有限鏈,就是用來實現共用屬性和繼承的。下麵,我們看代碼說話。

 1    var obj = new Object();
 2 對象是有原型對象的
 3 原型對象也有原型對象 
 4    obj._proto_._proto_._proto_
 5 原型對象也有原型對象,對象的原型對象一直往上找,會找到一個null
 6 // 原型鏈示例
 7    var arr = [];
 8    arr -> Array.prototype ->Object.prototype -> null
 9    var o = new Object();
10    o -> Object.prototype -> null;
function Foo1(){
   this.name1 = '1';
}
function Foo2(){
   this.name2 = '2';
}
Foo2.prototype = new Foo1();
function Foo3(){
   this.name = '3';
}
Foo3.prototype = new Foo2();
var foo3 = new Foo3();
console.dir(foo3);

  接下來就是繼承問題了。

2、繼承 

 1)原型繼承

 1  function Animal(name){
 2        this.name = name;
 3    }
 4    function Tiger(color){
 5        this.color = color;
 6    }
 7 //   var tiger = new Tiger('yellow');
 8 //   console.log(tiger.color);
 9 //   console.log(tiger.name);  //undefined
10 //      Tiger.prototype = new Animal('老虎');   //一種方式
11    Object.prototype.name = '大老虎';   //第二種方式
12         var tiger = new Tiger('yellow');
13         console.log(tiger.color);
14         console.log(tiger.name);
  值得註意的是,這裡存在兩個主要的問題: ①它不方便給父級類型傳遞參數;②父級類型當中的引用類型被所有的實例共用

    2)ES5 提供了Object.create() 方法來實現繼承

 1 ————做相容
 2   //shim墊片
 3     function create(obj){
 4         if(Object.create){
 5             return Object.create(obj);
 6         }else{
 7             function Foo(){}
 8             Foo.prototype = obj;
 9             return new Foo();
10         }
11     }

  這種方法是ES5的新特性,其實就是複製繼承。

    3)拷貝繼承
1 var obj = {};
2 obj.extend = function(obj){
3     for(var k in obj){
4       this[k] = obj[k];
5     }
6 }
     4)借用構造函數繼承 ——被借用的構造函數中原型上的成員沒有被借過來
 1 function Animal(name){
 2     this.name = name;
 3 }
 4 function Mouse(nickname){
 5     Animal.call(this,'老鼠');
 6     this.nickname = nickname;
 7 }
 8 var m = new Mouse('傑瑞');
 9 console.log(m.name);
10 console.log(m.nickname);

   存在的問題:可以解決原型繼承當中傳參問題,但是父類型當中的原型對象上的成員(屬性和方法)不能被繼承到

    5)組合繼承 ——prototype對象是有動態性的
 1 function Person(name){
 2    this.name = name;
 3 }
 4 Person.prototype.showName = function(){
 5    console.log(this.name);
 6 }
 7 function Student(name,age){
 8    Person.call(this,name);
 9    this.age = age;
10 }
11 Student.prototype = new Person();
12 Student.prototype.contructor = Student;
13 Student.prototype.showAge = function(){
14     console.log(this.age);
15 }
16 var stu = new Student('張三',12);
17 stu.showName();
18 stu.showAge();

【原型繼承+借用構造函數繼承】它的特點就是屬性每個實例一份,方法共用

 

【小結】套用一句很粗暴的話,所謂原型鏈就是找媽的一種行為方式,就可以理解為人是人他媽生的,妖是妖他媽生的。原型鏈的核心其實就只有一個:屬性共用和獨立的控制,當你的對象實例需要獨立的屬性,所有做法的本質都是在對象實例裡面創建屬性。若不考慮太多,你大可以在Person裡面直接定義你所需要獨立的屬性來覆蓋掉原型的屬性。總之,使用原型繼承的時候,要對於原型中的屬性要特別註意,因為他們都是牽一發而動全身的存在。現在最常用的方法是組合模式。

1、原型鏈

    1)構造函數、原型和實例的關係

        ①構造函數都有一個屬性prototype,這個屬性是一個對象(Object的實例)         ②原型對象prototype裡面有一個constructor屬性,該屬性指向原型對象所屬的構造函數         ③實例對象都有一個_proto_屬性,該屬性也指向構造函數的原型對象,它是一個非標準屬性,不可以用於編程,它是用於瀏覽器自己使用的     2)prototype與_proto_的關係

 

        ①prototype是構造函數的屬性

        ②_proto_是實例對象的屬性

                    ——這兩者都指向同一個對象

    【總結】i)函數也是對象,對象不一定是函數;

            ii)對象的本質:無序的鍵值對集合;鍵值對當中的值可以是任意數據類型的值

            iii)對象就是一個容器,這個容器當中放的是(屬性和方法)

    3)屬性搜索

      ①在訪問對象的某個成員的時候會先在對象中找是否存在

      ②如果當前對象中沒有就在構造函數的原型對象中找

      ③如果原型對象中沒有找到就到原型對象的原型上找

      ④知道Object的原型對象的原型是null為止

2、Function

——所有函數都是Function的實例

    ①本地對象:獨立於宿主環境(瀏覽器)的對象——包括Object、Array、Date、RegExp、Function、Error、Number、String、Boolean

    ②內置對象——包括Math、Global(window,在js中就是全局變數),使用的時候不需要new

    ③宿主對象——包括自定義對象、DOM、BOM


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

-Advertisement-
Play Games
更多相關文章
  • 原則:動靜分離,分級緩存,主動失效。 Web 開發中,介面會被分為以下幾類: 純靜態頁面。打死我都不會修改的頁面。很長一段時間內,基本上不會修改。比如:關於我們。 純動態頁面。實時性,個性化要求比較高。頁面變化很大,或者每個用戶看到的都不一樣,比如:朋友圈。 短時靜態頁面。在一定時間內基本不會變化, ...
  • 使用構造函數 基本思想: 在子類型構造函數的內部調用超類型構造函數。 使用apply()和call()方法可以在新創建的對象上執行構造函數。 function SuperType() { this.colors = ["red", "blue", "green"]; } function SubTy ...
  • 我們對於滑鼠經過圖標切換效果這個神奇效果並不陌生,那麼怎麼用代碼實現呢? html: 圖片: 註意: 1、超鏈接<a>是行內元素,不能直接定義寬度和高度,所以需要使用display:block;將其轉換為塊元素。 2、背景圖像預設相對於盒子的左上角對齊。當滑鼠經過時,需要將背景圖像相對於盒子的底部對 ...
  • ...
  • 對象屬性無序性 js對象是一個無序屬性集合。var obj={}; obj.a=10; obj.b=30; 屬性a和屬性b並沒有誰前誰後之說。for...in迴圈,先輸出哪個屬性都有可能。獲取和設置不同的屬性與順序無關,都會以大致相同的效率產生相同的結果。也就是說訪問屬性a和訪問屬性b,沒有哪個訪... ...
  • 如果某項請求發送到您的伺服器要求顯示您網站上的某個網頁(例如,用戶通過瀏覽器訪問您的網頁或 Googlebot 抓取網頁時),伺服器將會返回 HTTP 狀態代碼以響應請求。 此狀態代碼提供關於請求狀態的信息, 告訴 Googlebot 關於您的網站和請求的網頁的信息。 一些常見的狀態代碼包括: 20 ...
  • 一、可以利用flex來佈局一個div在另一個div裡面水平垂直居中 如:html代碼: <div class="container"> <div class="box"> </div> </div> css代碼: .container{ width:600px; height:400px; bord ...
  • html代碼: <div> <img src="BC0C62C1B1962A8A.jpg"> </div> css代碼: img{ clip-path:polygon(50% 0%,100% 50%,50% 100%,0% 50%); -webkit-clip-path: polygon(50% 0 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...