Prototype之我的看法

 prototype

js 的對象比較

因爲 js 是解釋執行的語言, 那麼再代碼中出現函數與對象若是重複執行, 會建立多個副本javascript

  1. 在代碼中重複執行的代碼容易出現重複的對象
  2. 建立一個 Person 構造函數, 以建立 對象. 要求有 name, age, gender 和 sayHello
  3. 代碼出現的錯誤
     // 1 function Person() { var o = {}; o.name = ... return o; } // 2 function Person () { name: .... age: .... ... }// 1 function Person() { var o = {}; o.name = ... return o; } // 2 function Person () { name: .... age: .... ... }
  4. 傳統的構造方法的定義方式會影響性能, 容易形成多個對象有多個方法副本. 應該講方法單獨抽取出來. 讓全部的對象共享該方法.
  5. 能夠考慮將方法所有放到外面可是有安全隱患
    • 在開發中會引入各類框架或庫. 自定義的成員越多, 出現命名衝突的概率越大
    • 可能在開發中會有多個構造函數. 每個構造函數應該有多個方法. 那麼就會變得不容易維護.
  6. 任意一個對象都會默認的連接到它的原型中
    • 建立一個函數. 會附帶的建立一個特殊的對象. 該對象使用 函數.prototype 引用. 稱其爲函數的原型屬性.
    • 每個由該函數做爲構造函數建立的對象, 都會默認的鏈接到該對象上.
    • 在該對象訪問某一個方法或屬性的時候, 若是該對象中沒有, 就會到這個神祕對象中去查找.

傳統構造函數的問題

 function Foo() { this.sayHello = function () { } }function Foo() { this.sayHello = function () { } }
  1. 因爲對象是調用 new Foo() 所建立出來的. 所以每個對象在建立的時候, 函數 sayHello 都會被建立一次
  2. 那麼每個對象都含有一個獨立的, 不一樣的, 可是功能邏輯同樣的函數. 好比: {} == {}
  3. 在代碼中方法就會消耗性能. 最典型的資源就是內存.
  4. 這裏最好的辦法就是將函數體放在構造函數以外. 那麼在構造函數中只須要引用該函數便可
     function sayHello () {} function Foo () { this.say = sayHello; }function sayHello () {} function Foo () { this.say = sayHello; }
  5. 會在開發中變得困難: 引入框架危險, 代碼繁冗很差維護. 解決辦法就是外面的函數若是不佔用名字. 並且在函數旗下就行了.
  6. 每個函數在定義的時候, 有一個神祕對象被建立出來.
  7. 每個由構造函數建立的對象都會默認的鏈接到該神祕對象上.
     var f1 = new Foo(); var f2 = new Foo(); f1.sayHello(); // 若是 f1 沒有 sayHello, 那麼就會在 Foo.prototype 中去找 f2.sayGoodBye(); // 若是 f2 沒有改方法, 那麼就會在 Foo.prototype 中去找var f1 = new Foo(); var f2 = new Foo(); f1.sayHello(); // 若是 f1 沒有 sayHello, 那麼就會在 Foo.prototype 中去找 f2.sayGoodBye(); // 若是 f2 沒有改方法, 那麼就會在 Foo.prototype 中去找
  8. 由構造函數建立出來的衆多對象共享一個對象, 就是 構造函數.prototype
  9. 只須要將共享的東西, 重複會多佔用內存的東西放到 構造函數.prototype 中, 那麼全部的對象就能夠共享了.java

     function Foo() {} Foo.prototype.sayHello = function () { console.log( ... ); }; var f1 = new Foo(); f1.sayHello(); var f2 = new Foo(); f2.sayHello(); f1.sayHello === f2.sayHellofunction Foo() {} Foo.prototype.sayHello = function () { console.log( ... ); }; var f1 = new Foo(); f1.sayHello(); var f2 = new Foo(); f2.sayHello(); f1.sayHello === f2.sayHello
  10. 練習: 寫一個構造函數 Student, 要求有 name, age, gender, sayHello, study. 要求構造函數帶參數.

常見錯誤

  1. 寫 構造函數.prototype 的時候, 將屬性也加到裏面.
     function Person() {} Person.prototype.name = '張三'; var p = new Person();function Person() {} Person.prototype.name = '張三'; var p = new Person();
  2. 賦值的錯誤安全

     function Person() {} Person.prototype.name = '張三'; var p1 = new Person(); var p2 = new Person(); p1.name = '李四'; console.log( p1.name ); console.log( p2.name ); // 若是是訪問數據, 當前對象中若是沒有該數據就到構造函數的原型屬性中去找 // 若是是寫數據, 當對象中有該數據的時候, 就是修改值; 若是對象沒有該數據, 那麼就添加值function Person() {} Person.prototype.name = '張三'; var p1 = new Person(); var p2 = new Person(); p1.name = '李四'; console.log( p1.name ); console.log( p2.name ); // 若是是訪問數據, 當前對象中若是沒有該數據就到構造函數的原型屬性中去找 // 若是是寫數據, 當對象中有該數據的時候, 就是修改值; 若是對象沒有該數據, 那麼就添加值

原型相關的概念

  1. 關於面向對象的概念
    • 類 class: 在 js 中就是構造函數
      • 在傳統的面嚮對象語言中, 使用一個叫作類的東西定義模板. 而後使用模板建立對象.
      • 在構造方法中也具備相似的功能. 所以稱其爲類
        // 在 java 中, 最小的代碼單位是 類 class Program { // 成員 }// 在 java 中, 最小的代碼單位是 類 class Program { // 成員 }
    • 實例 ( instance ) 與對象 ( object )
      • 實例通常是指某一個構造函數建立出來的對象. 咱們成爲 xxx 構造函數的實例
      • 實例就是對象. 對象是一個泛稱.
      • 實例與對象是一個近義詞
    • 鍵值對與屬性和方法
      • 在 js 中鍵值對的集合稱爲對象
      • 若是值爲數據( 非函數 ), 就稱該鍵值對爲屬性 property
      • 若是值爲函數( 方法 ), 就稱該鍵值對爲方法 method
    • 父類與子類
      • 傳統的面嚮對象語言中使用類來實現繼承. 那麼就有父類, 子類的概念
      • 父類又稱爲基類, 子類又稱爲派生類
      • 在 js 中經常稱爲父對象, 子對象. 基對象, 派生對象.
  2. 原型相關的概念
    • 神祕對象針對構造函數稱爲 "原型屬性"
      • 神祕對象就是構造函數的原型屬性
      • 簡稱原型
    • 神祕對象與構造函數所建立出來的對象也有必定關係
      • 關係是什麼
      • 神祕對象針對構造函數建立出來的對象稱爲 "原型對象"
      • 簡稱原型
    • 對象繼承自其原型
      • 構造函數建立的對象 繼承自 構造函數的原型屬性
      • 構造函數建立的對象 繼承自 該對象的原型對象
      • 構造函數所建立出來的對象與構造函數的原型屬性表示的對象是兩個不一樣的對象
        • 原型中的成員, 能夠直接被實例對象所使用
        • 也就是說實例對象直接 "含有" 原型中的成員
        • 所以 實例對象 繼承自 原型
        • 這樣的繼承就是 "原型繼承"
  3. 一些問題
    • {} 構造函數是什麼?
    • 凡是字面量的對象都有構造函數
      • {} Object
      • [] Array
      • /./ RegExp
      • function ... Function

如何使用原型

爲何使用原型?框架

  1. 利用對象的動態特性
    • 構造函數.prototype.XXX = vvvv;
  2. 利用直接替換
     Student.prototype = { sayHello: function () {}, study: function () {} };Student.prototype = { sayHello: function () {}, study: function () {} };
相關文章
相關標籤/搜索