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

                ## **原型** 我們創建的每個函數都有一個 prototype(原型)屬性,這個屬性是一個指針,指向一個對象, 使用原型對象的好處是可以 讓所有對象實例共享它所包含的屬性和方法。換句話說,不必在構造函數中定義對象實例的信息,而是 可以將這些信息直接添加到原型對象中,如下面的例子所示 : ~~~ function Person() { } Person.prototype.name = '小四' Person.prototype.age = 24 Person.prototype.sayName = function () { console.log(this.name) } var person1 = new Person() person1.sayName() // 小四 var person2 = new Person() person2.sayName() // 小四 console.log(person1.sayName === person2.sayName); //true ~~~ > 在此,我們將 sayName()方法和所有屬性直接添加到了 Person 的 prototype 屬性中,構造函數 變成了空函數。即使如此,也仍然可以通過調用構造函數來創建新對象,而且新對象還會具有相同的屬 性和方法。但與構造函數模式不同的是,新對象的這些屬性和方法是由所有實例共享的。換句話說, person1 和 person2 訪問的都是同一組屬性和同一個 sayName()函數。 > 原型:去改寫對象下面公用的方法或屬性,讓同樣公用的東西在內存當中只存在一份,好處就是提高性能。比較抽象。 學習方法:把原型看做css中的class,普通方法看做css中的style。 style和class比較: style優先級高于class style樣式沒有辦法復用 #### **原型改寫示例** ``` var arr = [1,2,3,4,5]; var arr1 = [11,21,31,41,51]; Array.prototype.sum = function () { var result = 0; for (var i=0;i<this.length;i++) { result+=this[i]; } return result; } console.log(arr.sum()); console.log(arr1.sum()); ``` ### **理解原型對象** - 無論什么時候,只要創建了一個新函數,就會根據一組特定的規則為該函數創建一個 prototype 屬性,這個屬性指向函數的原型對象。在默認情況下,所有原型對象都會自動獲得一個 constructor (構造函數)屬性,這個屬性包含一個指向 prototype 屬性所在函數的指針。就拿前面的例子來說, Person.prototype. constructor 指向 Person。而通過這個構造函數,我們還可繼續為原型對象 添加其他屬性和方法。 - 創建了自定義的構造函數之后,其原型對象默認只會取得 constructor 屬性;至于其他方法,則 都是從 Object 繼承而來的。當調用構造函數創建一個新實例后,該實例的內部將包含一個指針(內部 屬性),指向構造函數的原型對象,就是__proto__(隱式原型對應圖中的[[ Prototype ]]); ![](https://i.vgy.me/0QmAK2.png) > 這幅圖展示了 Person 構造函數、Person 的原型屬性以及 Person 現有的兩個實例之間的關系。 在此,Person.prototype指向了原型對象,而Person.prototype.constructor又指回了Person。 原型對象中除了包含 constructor 屬性之外,還包括后來添加的其他屬性。Person 的每個實例—— person1 和 person2 都包含一個內部屬性,該屬性僅僅指向了 Person.prototype;換句話說,它們 與構造函數沒有直接的關系。此外,要格外注意的是,雖然這兩個實例都不包含屬性和方法,但我們卻 可以調用 person1.sayName()。這是通過查找對象屬性的過程來實現的。 ~~~ console.log(person1.__proto__ === Person.prototype) // true ~~~ > 每當代碼讀取某個對象的某個屬性時,都會執行一次搜索,目標是具有給定名字的屬性。搜索首先 從對象實例本身開始。如果在實例中找到了具有給定名字的屬性,則返回該屬性的值;如果沒有找到, 則繼續搜索指針指向的原型對象,在原型對象中查找具有給定名字的屬性。如果在原型對象中找到了這 個屬性,則返回該屬性的值。也就是說,在我們調用 person1.sayName()的時候,會先后執行兩次搜 索。首先,解析器會問:“實例 person1 有 sayName 屬性嗎?”答:“沒有。”然后,它繼續搜索,再 問:“person1 的原型有 sayName 屬性嗎?”答:“有。”于是,它就讀取那個保存在原型對象中的函 數。當我們調用 person2.sayName()時,將會重現相同的搜索過程,得到相同的結果。而這正是多個 對象實例共享原型所保存的屬性和方法的基本原理。 ### **重寫原型中的值** 雖然可以通過對象實例訪問保存在原型中的值,但卻不能通過對象實例重寫原型中的值。如果我們 在實例中添加了一個屬性,而該屬性與實例原型中的一個屬性同名,那我們就在實例中創建該屬性,該 屬性將會屏蔽原型中的那個屬性。來看下面的例子。 ~~~ function Person() { } Person.prototype.name = '小四' Person.prototype.age = 24 Person.prototype.job = "Software Engineer" Person.prototype.sayName = function () { console.log(this.name) } var person1 = new Person() var person2 = new Person() person1.name = "豬八戒"; console.log(person1.name); //"豬八戒"——來自實例 console.log(person2.name); //"小四"——來自原型 ~~~ 在這個例子中,person1 的 name 被一個新值給屏蔽了。但無論訪問[person1.name](http://person1.name/)還是訪問[person2.name](http://person2.name/)都能夠正常地返回值,即分別是"豬八戒"(來自對象實例)和"小四"(來自原型)。 當在 console.log()中訪問[person1.name](http://person1.name/)時,需要讀取它的值,因此就會在這個實例上搜索一個名為 name 的屬性。這個屬性確實存在,于是就返回它的值而不必再搜索原型了。當以同樣的方式訪問 person2. name 時,并沒有在實例上發現該屬性,因此就會繼續搜索原型,結果在那里找到了 name 屬性。 當為對象實例添加一個屬性時,這個屬性就會屏蔽原型對象中保存的同名屬性;換句話說,添加這 個屬性只會阻止我們訪問原型中的那個屬性,但不會修改那個屬性。即使將這個屬性設置為 null,也 只會在實例中設置這個屬性,而不會恢復其指向原型的連接。不過,使用 delete 操作符則可以完全刪 除實例屬性,從而讓我們能夠重新訪問原型中的屬性,如下所示。 ~~~ function Person() { } Person.prototype.name = '小四' Person.prototype.age = 24 Person.prototype.job = "Software Engineer" Person.prototype.sayName = function () { console.log(this.name) } var person1 = new Person() var person2 = new Person() person1.name = "豬八戒"; console.log(person1.name); //"豬八戒"——來自實例 console.log(person2.name); //"小四"——來自原型 delete person1.name; console.log(person1.name); // 小四 --- 來自原型 ~~~ > 在這個修改后的例子中,我們使用 delete 操作符刪除了[person1.name](http://person1.name/),之前它保存的"小四" 值屏蔽了同名的原型屬性。把它刪除以后,就恢復了對原型中 name 屬性的連接。因此,接下來再調用[person1.name](http://person1.name/)時,返回的就是原型中 name 屬性的值了。 #### **提問一下,看看有沒有睡覺的** ``` var arr = []; arr.number = 10; Array.prototype.number = 20; console.log(arr.number); // 10 普通方法優先級高于原型方法 ``` > 解讀:首先解析器會問:“實例arr上有number屬性嗎?” 答:“有”,那么就停止查找,,因為實例比構造函數優先級高。
                  <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>

                              哎呀哎呀视频在线观看