<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                對于有基于類的語言經驗 (如 Java 或 C++) 的開發人員來說,JavaScript 有點令人困惑,因為它是動態的,并且本身不提供一個`class`實現。(在 ES2015/ES6 中引入了`class`關鍵字,但只是語法糖,JavaScript 仍然是基于原型的)。 當談到繼承時,JavaScript?只有一種結構:對象。每個實例對象(object?)都有一個私有屬性(稱之為\_\_proto\_\_)指向它的原型對象(**prototype**)。該原型對象也有一個自己的原型對象(\_\_proto\_\_) ,層層向上直到一個對象的原型對象為`null`。根據定義,`null`沒有原型,并作為這個**原型鏈**中的最后一個環節。 幾乎所有 JavaScript 中的對象都是位于原型鏈頂端的[`Object`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object "Object 構造函數創建一個對象包裝器。")的實例。 盡管這種原型繼承通常被認為是JavaScript的弱點之一,但是原型繼承模型本身實際上比經典模型更強大。例如,在原型模型的基礎上構建經典模型相當簡單。 ## 基于原型鏈的繼承 JavaScript 對象是動態的屬性“包”(指其自己的屬性)。JavaScript 對象有一個指向一個原型對象的鏈。當試圖訪問一個對象的屬性時,它不僅僅在該對象上搜尋,還會搜尋該對象的原型,以及該對象的原型的原型,依次層層向上搜索,直到找到一個名字匹配的屬性或到達原型鏈的末尾。 ~~~ // 讓我們從一個自身擁有屬性a和b的函數里創建一個對象o: let f = function () { this.a = 1; this.b = 2; } /* 你要這么寫也沒區別 function f(){ this.a = 1; this.b = 2; } */ let o = new f(); // {a: 1, b: 2} // 在f函數的原型上定義屬性 f.prototype.b = 3; f.prototype.c = 4; // 不要在f函數的原型上直接定義 f.prototype = {b:3,c:4};這樣會直接打破原型鏈 // o.[[Prototype]] 有屬性 b 和 c (其實就是o.__proto__或者o.constructor.prototype) // o.[[Prototype]].[[Prototype]] 是 Object.prototye. // 最后o.[[Prototype]].[[Prototype]].[[Prototype]]是null // 這就是原型鏈的末尾,即 null, // 根據定義,null 沒有[[Prototype]]. // 綜上,整個原型鏈如下: // {a:1, b:2} ---> {b:3, c:4} ---> Object.prototye---> null console.log(o.a); // 1 // a是o的自身屬性嗎?是的,該屬性的值為1 console.log(o.b); // 2 // b是o的自身屬性嗎?是的,該屬性的值為2 // 原型上也有一個'b'屬性,但是它不會被訪問到.這種情況稱為"屬性遮蔽 (property shadowing)" console.log(o.c); // 4 // c是o的自身屬性嗎?不是,那看看原型上有沒有 // c是o.[[Prototype]]的屬性嗎?是的,該屬性的值為4 console.log(o.d); // undefined // d是o的自身屬性嗎?不是,那看看原型上有沒有 // d是o.[[Prototype]]的屬性嗎?不是,那看看它的原型上有沒有 // o.[[Prototype]].[[Prototype]] 為 null,停止搜索 // 沒有d屬性,返回undefined ~~~ 給對象設置屬性會創建自有屬性。獲取和設置屬性的唯一限制是內置 getter 或 setter 的屬性。 ### 繼承方法 JavaScript 并沒有其他基于類的語言所定義的“方法”。在 JavaScript 里,任何函數都可以添加到對象上作為對象的屬性。函數的繼承與其他的屬性繼承沒有差別,包括上面的“屬性遮蔽”(這種情況相當于其他語言的方法重寫)。 當繼承的函數被調用時,this指向的是當前繼承的對象,而不是繼承的函數所在的原型對象。 ~~~ var o = { a: 2, m: function(){ return this.a + 1; } }; console.log(o.m()); // 3 // 當調用 o.m 時,'this'指向了o. var p = Object.create(o); // p是一個繼承自 o 的對象 p.a = 4; // 創建 p 的自身屬性 a console.log(p.m()); // 5 // 調用 p.m 時, 'this'指向 p. // 又因為 p 繼承 o 的 m 函數 // 此時的'this.a' 即 p.a,即 p 的自身屬性 'a' ~~~ ### `語法結構創建的對象` ~~~ var o = {a: 1}; // o 這個對象繼承了Object.prototype上面的所有屬性 // o 自身沒有名為 hasOwnProperty 的屬性 // hasOwnProperty 是 Object.prototype 的屬性 // 因此 o 繼承了 Object.prototype 的 hasOwnProperty // Object.prototype 的原型為 null // 原型鏈如下: // o ---> Object.prototype ---> null var a = ["yo", "whadup", "?"]; // 數組都繼承于 Array.prototype // (Array.prototype 中包含 indexOf, forEach等方法) // 原型鏈如下: // a ---> Array.prototype ---> Object.prototype ---> null function f(){ return 2; } // 函數都繼承于Function.prototype // (Function.prototype 中包含 call, bind等方法) // 原型鏈如下: // f ---> Function.prototype ---> Object.prototype ---> null ~~~ ### ### `構造器創建的對象` 在 JavaScript 中,構造器其實就是一個普通的函數。當使用new來作用這個函數時,它就可以被稱為構造方法(構造函數)。 ~~~ function Graph() { this.vertices = []; this.edges = []; } Graph.prototype = { addVertex: function(v){ this.vertices.push(v); } }; var g = new Graph(); // g是生成的對象,他的自身屬性有'vertices'和'edges'. // 在g被實例化時,g.[[Prototype]]指向了Graph.prototype. ~~~ ### `` `Object.create`?創建的對象`` ECMAScript 5 中引入了一個新方法:Object.create(),可以調用這個方法來創建一個新對象。新對象的原型就是調用 create 方法時傳入的第一個參數: ~~~ var a = {a: 1}; // a ---> Object.prototype ---> null var b = Object.create(a); // b ---> a ---> Object.prototype ---> null console.log(b.a); // 1 (繼承而來) var c = Object.create(b); // c ---> b ---> a ---> Object.prototype ---> null var d = Object.create(null); // d ---> null console.log(d.hasOwnProperty); // undefined, 因為d沒有繼承Object.prototype ~~~ ### `` `class`?關鍵字創建的對象`` ECMAScript6 引入了一套新的關鍵字用來實現[class](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes)。使用基于類語言的開發人員會對這些結構感到熟悉,但它們是不同的。JavaScript 仍然基于原型。這些新的關鍵字包括?[`class`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/class "class?聲明創建一個基于原型繼承的具有給定名稱的新類。"),[`constructor`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/constructor "構造函數 constructor?是用于創建和初始化類中創建的一個對象的一種特殊方法。"),[`static`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/static "類(class)通過?static?關鍵字定義靜態方法。不能在類的實例上調用靜態方法,而應該通過類本身調用。這些通常是實用程序方法,例如創建或克隆對象的功能。"),[`extends`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/extends "extends關鍵字用于類聲明或者類表達式中,以創建一個類,該類是另一個類的子類。")和[`super`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/super "super關鍵字用于訪問和調用一個對象的父對象上的函數。")。 ~~~ "use strict"; class Polygon { constructor(height, width) { this.height = height; this.width = width; } } class Square extends Polygon { constructor(sideLength) { super(sideLength, sideLength); } get area() { return this.height * this.width; } set sideLength(newLength) { this.height = newLength; this.width = newLength; } } var square = new Square(2); ~~~ ### `性能` 在原型鏈上查找屬性比較耗時,對性能有副作用,這在性能要求苛刻的情況下很重要。另外,試圖訪問不存在的屬性時會遍歷整個原型鏈。 遍歷對象的屬性時,原型鏈上的**每個**可枚舉屬性都會被枚舉出來。要檢查對象是否具有自己定義的屬性,而不是其原型鏈上的某個屬性,則必須使用所有對象從Object.prototype繼承的?[hasOwnProperty](https://developer.mozilla.org/zh-CN/docs/JavaScript/Reference/Global_Objects/Object/hasOwnProperty)?方法。下面給出一個具體的例子來說明它: ~~~ console.log(g.hasOwnProperty('vertices')); // true console.log(g.hasOwnProperty('nope')); // false console.log(g.hasOwnProperty('addVertex')); // false console.log(g.__proto__.hasOwnProperty('addVertex')); // true ~~~ [hasOwnProperty](https://developer.mozilla.org/zh-CN/docs/JavaScript/Reference/Global_Objects/Object/hasOwnProperty)?是 JavaScript 中處理屬性并且不會遍歷原型鏈的方法之一。(另一種方法:[Object.keys()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/keys)) 注意:檢查屬性是否[undefined](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/undefined)還不夠。該屬性可能存在,但其值恰好設置為undefined。 prototype是用于類的,而?Object.getPrototypeOf()?是用于實例的(instances),兩者功能一致。
                  <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>

                              哎呀哎呀视频在线观看