<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] # 原型鏈類 當談到繼承時,JavaScript 只有一種結構:對象。每個實例對象(object)都有一個私有屬性(稱之為`__proto__`)指向它的原型對象(`prototype`)。該原型對象也有一個自己的原型對象(`__proto__`) ,層層向上直到一個對象的原型對象為 null。根據定義,null 沒有原型,并作為這個原型鏈中的最后一個環節。 幾乎所有 JavaScript 中的對象都是位于原型鏈頂端的Object的實例。 <br> <br> ## 創建對象有幾種方法 ### 字面量 ~~~ var o1 = {name: 'o1'}; // Object {name: "o1"} ~~~ <br> ### 構造函數 ~~~ var o2 = new Object({name: 'o2'}); // Object {name: "o1"} var M = function (name) { this.name = name; }; var o3 = new M('o3'); // M {name: "o3"} ~~~ <br> ### Object.create ~~~ var p = {name: 'p'}; var o4 = Object.create(p); // o4 {} ~~~ <br> ## 原型 ### prototype prototype屬性,別忘了一點,就是我們前面提到要牢記的兩點中的第二點,它是函數所獨有的,它是從一個函數指向一個對象。它的含義是函數的原型對象,也就是這個函數(其實所有函數都可以作為構造函數)所創建的實例的原型對象,由此可知:f1.__proto__ === Foo.prototype,它們兩個完全一樣。那prototype屬性的作用又是什么呢?它的作用就是包含可以由特定類型的所有實例共享的屬性和方法,也就是讓該函數所實例化的對象們都可以找到公用的屬性和方法。任何函數在創建的時候,其實會默認同時創建該函數的prototype對象。 > prototype是函數才會有的屬性 ~~~ function Person() { } Person.prototype.name = 'Kevin'; var person1 = new Person(); var person2 = new Person(); console.log(person1.name) // Kevin console.log(person2.name) // Kevin ~~~ <br> <br> ![](https://img.kancloud.cn/9e/54/9e54d8115a4886bc710e8d8547932899_1761x968.png) <br> <br> ### `__proto__` 這是每一個JavaScript對象(除了 null )都具有的一個屬性,叫__proto__,這個屬性會指向該對象的原型。 ~~~ function Person() { } var person = new Person(); console.log(person.__proto__ === Person.prototype); // true ~~~ <br> ![](https://img.kancloud.cn/fb/36/fb368aba91b6e44c57e528100cb2126c_1790x952.png) <br> > 第一,這里我們僅留下 __proto__ 屬性,它是對象所獨有的,可以看到__proto__屬性都是由一個對象指向一個對象,即指向它們的原型對象(也可以理解為父對象),那么這個屬性的作用是什么呢?它的作用就是當訪問一個對象的屬性時,如果該對象內部不存在這個屬性,那么就會去它的__proto__屬性所指向的那個對象(可以理解為父對象)里找,如果父對象也不存在這個屬性,則繼續往父對象的__proto__屬性所指向的那個對象(可以理解為爺爺對象)里找,如果還沒找到,則繼續往上找…直到原型鏈頂端null,再往上找就相當于在null上取值,會報錯(可以理解為,再往上就已經不是“人”的范疇了,找不到了,到此結束,null為原型鏈的終點),由以上這種通過__proto__屬性來連接對象直到null的一條鏈即為我們所謂的原型鏈。 其實我們平時調用的字符串方法、數組方法、對象方法、函數方法等都是靠__proto__繼承而來的。 <br> <br> ### constructor constructor屬性也是對象才擁有的,它是從一個對象指向一個函數,含義就是指向該對象的構造函數,每個對象都有構造函數(本身擁有或繼承而來,繼承而來的要結合__proto__屬性查看會更清楚點,如下圖所示),從上圖中可以看出Function這個對象比較特殊,它的構造函數就是它自己(因為Function可以看成是一個函數,也可以是一個對象),**所有函數和對象最終都是由Function構造函數得來,所以constructor屬性的終點就是Function這個函數**。 ~~~ function Person() { } var person = new Person(); console.log(Person === Person.prototype.constructor); // true console.log(Person === person.constructor); // true ~~~ 當獲取 person.constructor 時,其實 person 中并沒有 constructor 屬性,當不能讀取到constructor 屬性時,會從 person 的原型也就是 Person.prototype 中讀取,正好原型中有該屬性。 <br> ![](https://img.kancloud.cn/e8/1c/e81c502c9d50cd3d0d62ccc4719acc0b_1736x945.png) <br> ![](https://img.kancloud.cn/65/52/6552747f5dae4eeee59e8e75ada6b662_1040x603.png) <br> ### 實例與原型 當讀取**實例**的屬性時,如果找不到,就會查找與對象關聯的**原型**中的屬性,如果還查不到,就去找**原型的原型**,一直找到最頂層為止。 ~~~ function Person() { } Person.prototype.name = 'Kevin'; var person = new Person(); person.name = 'Daisy'; console.log(person.name) // Daisy delete person.name; console.log(person.name) // Kevin ~~~ <br> 在這個例子中,我們給實例對象 `person` 添加了 `name` 屬性,當我們打印 `person.name` 的時候,結果自然為 `Daisy`。 <br> 但是當我們刪除了` person` 的 `name` 屬性時,讀取 `person.name`,從 `person` 對象中找不到 `name` 屬性就會從 `person` 的原型也就是 `person.__proto__ `,也就是 `Person.prototype`中查找,幸運的是我們找到了 `name` 屬性,結果為 `Kevin`。 <br> <br> ### 原型的原型 在前面,我們已經講了原型也是一個對象,既然是對象,我們就可以用最原始的方式創建它,那就是: ~~~ var obj = new Object(); obj.name = 'Kevin' console.log(obj.name) // Kevin ~~~ 其實原型對象就是通過 `Object` 構造函數生成的,結合之前所講,實例的 `__proto__` 指向構造函數的 `prototype` ,所以我們再更新下關系圖: <br> ![](images/screenshot_1545753039539.png) <br> <br> ### 原型鏈 `Object.prototype.__proto__` 的值為 `null` 即 `Object.prototype` 沒有原型,所以查找屬性的時候查到 `Object.prototype` 就可以停止查找了。 <br> ~~~ console.log(Object.prototype.__proto__ === null) // true ~~~ <br> 圖中由相互關聯的原型組成的鏈狀結構就是原型鏈,也就是藍色的線。 <br> ![](https://box.kancloud.cn/d5145b0d9fc5e529fa9a7b035eaf4d1a_1024x272.png) <br> <br> ### 總結 1. 我們需要牢記兩點:①__proto__和constructor屬性是對象所獨有的;② prototype屬性是函數所獨有的,因為函數也是一種對象,所以函數也擁有__proto__和constructor屬性。 2. __proto__屬性的作用就是當訪問一個對象的屬性時,如果該對象內部不存在這個屬性,那么就會去它的__proto__屬性所指向的那個對象(父對象)里找,一直找,直到__proto__屬性的終點null,再往上找就相當于在null上取值,會報錯。通過__proto__屬性將對象連接起來的這條鏈路即我們所謂的原型鏈。 3. prototype屬性的作用就是讓該函數所實例化的對象們都可以找到公用的屬性和方法,即f1.__proto__ === Foo.prototype。 4. constructor屬性的含義就是指向該對象的構造函數,所有函數(此時看成對象了)最終的構造函數都指向Function <br> <br> ## instanceof ### 概念 `instanceof` 運算符用于測試 **構造函數** 的 `prototype` 屬性是否出現在對象的原型鏈中的**任何位置** ~~~ function M() {} var obj = new M() obj.__proto__ === M.prototype // true obj instanceof M // true M.prototype.__proto__ === Object.prototype // true M instanceof Object // true ~~~ <br> <br> ~~~ // 定義構造函數 function C(){} function D(){} var o = new C(); o instanceof C; // true,因為 Object.getPrototypeOf(o) === C.prototype o instanceof D; // false,因為 D.prototype不在o的原型鏈上 o instanceof Object; // true,因為Object.prototype.isPrototypeOf(o)返回true C.prototype instanceof Object // true,同上 C.prototype = {}; var o2 = new C(); o2 instanceof C; // true o instanceof C; // false,C.prototype指向了一個空對象,這個空對象不在o的原型鏈上. D.prototype = new C(); // 繼承 var o3 = new D(); o3 instanceof D; // true o3 instanceof C; // true 因為C.prototype現在在o3的原型鏈上 ~~~ <br> ![](https://box.kancloud.cn/3ee04ff512a68800c014b66de0f6b3f2_488x590.png) ### 判斷對象是否是某個構造函數的實例 ~~~ function M() {} var obj = new M() obj.__proto__.constructor === M //true obj.__proto__.constructor === Object //true ~~~ <br> <br> # 參考資料 * [JavaScript深入之從原型到原型鏈](https://github.com/mqyqingfeng/Blog/issues/2) * [繼承與原型鏈 | MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain) * [instanceof | MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/instanceof) * [深入理解javascript原型和閉包(5)——instanceof](https://www.cnblogs.com/wangfupeng1988/p/3979533.html) * [幫你徹底搞懂JS中的prototype、\_\_proto\_\_與constructor(圖解)](https://blog.csdn.net/cc18868876837/article/details/81211729)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看