因爲 js 是解釋執行的語言, 那麼在代碼中出現的函數與對象, 若是重複執行, 那麼會建立多個副本, 消耗更多的內存, 從而下降性能java
function Foo( ... ){ this.name = name; this.age = age; this.sayHello = function(){ ... } }
new Foo()
建立出來的, 所以每個對象在建立的時候, 函數 sayHello 都會被建立一次function sayHello(){} function Foo(){ this.sayHello = sayHello; }
函數.prototype
引用, 這個特殊的對象是這個函數的原型屬性var f1 = new Foo(); var f2 = new Foo(); f1.sayHello(); // 若是 f1 沒有 sayHello, 那麼就會在 Foo.prototype 中去找 f2.sayHello(); // 若是 f2 沒有改方法, 那麼就會在 Foo.prototype 中去找
function Foo() {} Foo.prototype.sayHello = function () { console.log( ... ); }; var f1 = new Foo(); f1.sayHello(); var f2 = new Foo(); f2.sayHello(); f1.sayHello === f2.sayHello
function Person() {} Person.prototype.name = '張三'; var p = new Person();
function Person() {} Person.prototype.name = '張三'; var p1 = new Person(); var p2 = new Person(); p1.name = '李四'; console.log( p1.name ); console.log( p2.name );
* 在傳統的面嚮對象語言中( c, java ), 使用一個叫作類的東西定義模板, 而後使用模板建立對象 * 在構造方法中也具備相似功能, 叫作類
* 實例通常是指摸一個構造函數建立出來的對象, 叫作 XXX 構造函數的實例對象 * 實例就是對象, 對象是一個泛稱 * 實例與對象是一個近義詞
* 在 js 中, 鍵值對的集合被叫作對象 * 若是值爲數據( 非函數 ), 就稱該鍵值對爲屬性 property * 若是值爲函數( 方法 ), 就稱該鍵值對爲方法 method
* 傳統的面向對象的語言中使用類來實現繼承, 那麼就有父類, 子類 * 父類又稱爲基類, 子類有稱爲派生類 * 在 js 中, 經常被稱爲扶對象, 子對象, 基對象, 派生對象
* 原型對象就是構造函數的**原型屬性** * 簡稱原型
* 原型對象相對於構造函數建立的實例對象稱爲**原型對象** * 簡稱原型
* 構造函數建立的實例對象 繼承自 構造函數的原型屬性( 構造函數.prototype ) * 構造函數建立的實例對象 繼承自 該對象的原型對象 * 構造函數建立的實例對象與構造函數的原型屬性表示的對象是兩個不一樣的對象 * 原型中的成員, 能夠直接被實例對象調用 * 實例對象 "*含有*" 原型中的成員 * 實例對象 繼承自 原型 * 這樣的繼承就是 "原型繼承"
* 凡是對象都有構造函數 * {} => Object * [] => Array * /./ => Regexp * function... => Function
function Person() {} Person.prototype = { constructor: Person }; // 拆解 function Person() {} var o = {}; o.costructor = Person; // 屬性中就存儲着函數的地址 Person.prototype = o; Person = 123;
__proto__
屬性, 來表示使用實例對象引用原型, 早期是非標準的__proto__
屬性能夠容許使用實例對象直接訪問原型function Person() {} // 原型對象就是 Person.prototype // 那麼只有使用 構造函數 才能夠訪問它 var o = new Person(); // 之前不能直接使用 o 來訪問神祕對象 // 如今有了 __proto__ 後 // o.__proto__ 也能夠直接訪問原型對象( 兩個下劃線 ) // 那麼 o.__proto__ === Person.prototype
constructor
, 構造器 , 將該原型和該原型的構造函數聯繫起來__proto__
的做用
var o = new Person(); o.constructor.prototype;
function Foo() {} Foo.prototype.name = 'test'; var o1 = new Foo(); var o2 = new Foo(); o1.name = '張三'; // 不是修改原型中的 name 而是本身增長了一個 name 屬性 console.log( o1.name + ', ' + o2.name );
function Person(name){ this.name = name; } var P1 = new Person('Jim');