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

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                >[success] # 關于繼承 1. 在 JavaScript 中,是通過**遍歷原型鏈**的方式,**來訪問對象的方法和屬性**,簡單的說就是**我自身沒有我就通過'_\_proto__' 找到我的構造函數的'prototype'上**,構造函數原型對象沒有他就去找**構造函數上'_\_proto__' 鏈接的原型對象**一直都沒找到的情況下,最后找到**null 終止** 2. 在原型鏈上查找屬性**比較耗時**,**對性能有副作用**,這在性能要求苛刻的情況下很重要。另外試圖訪問**不存在**的屬性時**會遍歷整個原型鏈**。 ~~~ function Person (name) { this.name = name; } var lily = new Person("Lily"); ~~~ ![](https://img.kancloud.cn/63/35/633542452800c63cd9a3443f1739ae09_760x225.png) 3. **js屬性遮蔽**可以理解成就近原則 ~~~ function A (name) { this.name = name } A.prototype.name = "原型對象上的name 屬性" const a = new A('w') console.log(a.name); // w ~~~ * 會找離自身最近屬性對應值 ![](https://img.kancloud.cn/e0/87/e087200e6073f09ad0d25d86719d0825_292x128.png) >[danger] ##### hasOwnProperty -- 屬性是否是原型對象上 1. 證明打印是自己的而不是原型對象**prototype**上的,使用**hasOwnProperty**返回的是**true** 則使用的是實例對象自己的,**false**怎相反 ~~~ function Person() {} // 每一個函數都有一個原型屬性prototype // 他們都會指向實例對象因此在Person這個 // 構造函數的prototype加屬性即可創建的對象共享 Person.prototype.name = 'wang' const p1 = new Person() // 當前的name 到底是p1的還是 Person的 console.log(p1.hasOwnProperty('name')) const p2 = new Person() p2.name = 'p2' // 當前的name 到底是p1的還是 Person的 console.log(p2.hasOwnProperty('name')) 打印結果: false true ~~~ >[info] ## 繼承幾種方式 >[danger] ##### 原型鏈繼承 1. 這種繼承新實例無法向**父類構造函數傳參** 2. 所有新實例都會共享父類實例的屬性,會產生的問題兩個實例使用的是**同一個原型對象**。它們的內存空間是共享的,如果屬性是**引用類型**當一個發生變化的時候,另外一個也隨之進行了**變化** 3. 通過直接打印對象是看不到這個屬性的,因為我們將父類直接new 生成對象掛在到原型鏈上,其實當調用時候自身沒有的都會去掛在對象去找本事其真正本身屬性都是共享屬性 ~~~ // 第一種 原型鏈繼承 function Parent(){ this.name="parent"; this.play = [1,2,3] } function Child(){ this.type="child"; } Child.prototype = new Parent(); const child1 = new Child() const child2 = new Child() child1.play.push(12345) console.log(child1.play,child2.play); // [ 1, 2, 3, 12345 ] [ 1, 2, 3, 12345 ] ~~~ >[danger] ##### 構造函數繼承 1. 此通過 **apply()和call()** 方法 改變函數執行時this 指向,單獨聲明時候并不會執行只有當new Child 時候此時執行然后給當前this 調用了一個賦值屬性的封裝方法 ~~~ function a(obj){ obj.name = "w" obj.age = 12 } const z = {} a(z) ~~~ 2. 這種問題弊端只繼承了父類構造函數的屬性,沒有繼承父類原型的屬性,因此導致下面的'child.getName()' 調用會報錯 ~~~ function Parent(age){ this.name="parent"; this.age = age this.play = [1,2,3] } Parent.prototype.getName = function(){ return this.name } function Child(age){ // ;(function(){ // this.name = "zzz" // this.play = [1,2,3] // }).call(this) // 上面注釋方法和下面等同 Parent.call(this,age) this.type="child"; } const child1 = new Child(1) const child2 = new Child(10) child1.play.push(12345) console.log(child1.play,child2.play); // [ 1, 2, 3, 12345 ] [ 1, 2, 3 ] // 報錯 // console.log(child.getName()) ~~~ >[danger] ##### 組合繼承 1. 上面兩種各自有對方不能解決的問題,將這兩種組合形成繼承,弊端就是下面的'Parent' 會執行兩次,分別在構造函數時候執行一次在原型鏈上執行一次浪費性能開銷 1.1. 一次在創建子類原型的時候; 1.2. 一次在子類構造函數內部(也就是每次創建子類實例的時候); 2. **所有的子類實例事實上會擁有兩份父類的屬性** 2.1. 一份在當前的實例自己里面(也就是person本身的),另一份在子類對應的原型對象中(也就是person.\_\_proto\_\_里面),這兩份屬性我們無需擔心訪問出現問題,因為默認一定是訪問實例本身這一部分的(就近原則) ![](https://img.kancloud.cn/ae/86/ae86d331c13b660c411843c7e8ab5e6c_519x208.png) ~~~ // 第一種 原型鏈繼承 function Parent(age){ this.name="parent"; this.age = age this.play = [1,2,3] } Parent.prototype.getName = function(){ return this.name } function Child(age){ Parent.call(this,age) this.type="child"; } // 執行一次 Child.prototype = new Parent() // 手動掛上構造器,指向自己的構造函數 Child.prototype.constructor = Child; const child1 = new Child(1) // 觸發函數執行了第二次Parent = 》Parent.call(this,age) const child2 = new Child(10) child1.play.push(12345) console.log(child1.play,child2.play); // [ 1, 2, 3, 12345 ] [ 1, 2, 3 ] ~~~ >[danger] ##### 原型繼承 **道格拉斯·克羅克福**德在一篇文章中介紹了一種實現繼承的方法,**這種方法并沒有使用嚴格意義上的構造函數**。它的想法**是借助原型可以基于已有的對象創建新對象,同時還不必因此創建自定義類型**。為了達到這個目的,他給出了如下函數。 ~~~ function object(o){ function F() {} F.prototype = o; return new F(); } ~~~ 在object()函數內部,**先創建了一個臨時性的構造函數,然后將傳入的對象作為這個構造函數的原型,最后返回了這個臨時類型的一個新實例**。**從本質上講,object()對傳入其中的對象執行了一次淺復制**。 克羅克福德主張的**這種原型式繼承**,**要求你必須有一個對象可以作為另一個對象的基礎**。 1. ECMAScript5通過新增 **Object.create()** 方法規范化了原形式繼承這個方法接收兩個參數:一是用作新對象原型的對象、二是為新對象定義額外屬性的對象(可選參數),將這個方法拆解可以寫作下面 ~~~ Object.myCreate = function (obj, properties) { var F = function () {} F.prototype = obj if (properties) { Object.defineProperties(F, properties) } return new F() } ~~~ 2. 如圖相當于都掛載到原型了導致數據共享問題,無法實現復用,屬于自己的屬性需要給create 第二個方法傳參 ![](https://img.kancloud.cn/a9/87/a987a206097614bbb15624df9bde4c5d_421x150.png) 3. 這類思想就是脫離之前構造函數的想法,而是直接給對象做繼承,雖然每次偽造了一個 構造函數但對其包裝并未暴露 ~~~ let parent4 = { name: "parent4", friends: ["p1", "p2", "p3"], getName: function() { return this.name; } }; let person4 = Object.create(parent4); person4.name = "tom"; person4.friends.push("jerry"); let person5 = Object.create(parent4); person5.friends.push("lucy"); console.log(person4.name); console.log(person4.name === person4.getName()); console.log(person5.name); console.log(person4.friends); console.log(person5.friends); 打印結果: tom true parent4 [ 'p1', 'p2', 'p3', 'jerry', 'lucy' ] [ 'p1', 'p2', 'p3', 'jerry', 'lucy' ] ~~~ >[danger] ##### 寄生式繼承 1. **寄生式(Parasitic)繼承是與原型式繼承緊密相關的一種思想**, 并且同樣由道格拉斯·克羅克福德(Douglas Crockford)提出和推廣的,不同在于**手動去增加當前實例的屬性和方法**,寄生式繼承的思路是結合原型類繼承和**工廠模式**的一種方式 ~~~ let parent5 = { name: "parent5", friends: ["p1", "p2", "p3"], getName: function() { return this.name; } }; function clone(original) { let clone = Object.create(original); clone.getFriends = function() { return this.friends; }; return clone; } let person5 = clone(parent5); console.log(person5.getName()); console.log(person5.getFriends()); ~~~ >[danger] ##### 寄生組合繼承 1. 組合繼承是比較理想的繼承方式, 但是存在兩個問題: 1.1. 構造函數會被調用兩次: 一次在創建子類型原型對象的時候, 一次在創建子類型實例的時候. 1.2. 父類型中的屬性會有兩份: 一份在原型對象中, 一份在子類型實例中 2. **Object.create** 可以掛載原型,這樣直接將父類的原型掛載給當前**Child.prototype= new Parent()** 相對于這種相當于少執行一次父類的實例,在利用call 將父類的屬性在當前子類的構造函數掛載會來,在這個時候有個疑問為什么不**Child.prototype= Parent.property** 這樣的話兩者內存共享子類也可以修改父類**new Parent()** 本身就是為了創建一個新的不影響的**Object.create**本質也是創建的新對象 3. 是否可以直接對象的隱式原型去綁定,也就是 ~~~ const c = new Child() c.__proto__ = Parent.property ~~~ 這樣問題就是`__proto__` 并不是js 提供只是瀏覽器提供所以這種用法未來會出現兼容性問題 ~~~ function clone (parent, child) { // 這里改用 Object.create 就可以減少組合繼承中多進行一次構造的過程 child.prototype = Object.create(parent.prototype); child.prototype.constructor = child; } function Parent6() { this.name = 'parent6'; this.play = [1, 2, 3]; } Parent6.prototype.getName = function () { return this.name; } function Child6() { Parent6.call(this); this.friends = 'child5'; } clone(Parent6, Child6); Child6.prototype.getFriends = function () { return this.friends; } let person6 = new Child6(); console.log(person6); console.log(person6.getName()); console.log(person6.getFriends()); ~~~ >[info] ## 參考 [參考文章](http://www.hmoore.net/cyyspring/html_js_cs/725347) [六種繼承](https://www.cnblogs.com/Grace-zyy/p/8206002.html) [參考拉勾教育文章鏈接](https://kaiwu.lagou.com/course/courseInfo.htm?courseId=601#/detail/pc?id=6176)
                  <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>

                              哎呀哎呀视频在线观看