globalSayHello()
就是這樣的一個方法。function globalSayHello() { console.log("hello"); } function Person() { var o = {}; o.sayHello = globalSayHello; return o; } var p1 = new Person(); var p2 = new Person(); p1.sayHello == p2.sayHello; // true
針對以上狀況,能夠將方法所有放到外面,好比,將sayHello()
單獨定義到全局中,代碼以下:javascript
function sayHello() {//TODO}
可是這麼作會有以下安全隱患java
任意一個對象,都會默認鏈接到它的原型中數組
函數.prototype
引用,稱其爲函數的原型屬性。強調一下是原型屬性
function Person() {} var p = new Person(); /*p就是由Person函數做爲構造函數建立出來的對象*/ /*在 Chrome 瀏覽器的 watch 中可使用以下方式查看結構*/ p._proto_ == Person.prototype // true
function Person(name) { this.name = name; } /* 在原型中定義了 printName() 方法 */ Person.prototype.printName = function () { console.log(this.name); }; var p = new Person("z4"); p.printName() /** * 構造函數 Person 中沒有 printName() 這個方法 * 當 p 對象調用這個方法的時候,會先去構造方法中 * 查找,若是找不到,會去原型中查找。 */
從調試工具中能夠看到,p
對象中是不存在 printName()
方法的,此方法是在 __proto__
對象中存在的
瀏覽器
var f1 = new Foo(); var f2 = new Foo(); /* 若是 f1 中沒有 sayHello 方法,就會去 Foo.prototype 中查找 */ f1.sayHello(); /* 若是 f2 中沒有 sayGood 方法,就會去 Foo.prototype 中查找 */ f2.sayGood();
構造函數.prototype
構造函數.prototype 中
,那麼全部的對象就能夠共享了var arr = []; for(var i = 0; i < 4; i++) { arr.push({}); arr.push(function() {}) } console.log(arr[0] == arr[2]); //false console.log(arr[1] == arr[3]); //false /** * 分析: * 數組中每次新 push 的 {} 都是一個新的對象 * 因此 arr[0] == arr[2] 是 false * 同理,每次 push 的 function(){} 也是一個新的對象,因此也不相等 */ function createPerson() { var o = {}; o.sayHello = function () { console.log("hello"); }; return o; } var p1 = createPerson(); var p2 = createPerson(); console.log(p1 == p2); //false console.log(p1.sayHello == p2.sayHello); //false /** * 分析: * 每次執行 createPerson() 方法時 * o對象老是一個新的對象,因此 p1 == p2 是 false * 同理,sayHello 方法每次也是一個新的對象 */
如今考慮一個問題,這樣建立出的對象是否很浪費資源,好比 sayHello
對象(方法也是一個對象),每次執行 createPerson()
方法都會建立一個都具備相同的功能,這樣是一種資源的浪費。安全
function globalSayHello() { console.log("hello"); } function createPerson() { var o = {}; o.sayHello = globalSayHello; return o; } var o1 = createPerson(); var o2 = createPerson(); console.log(o1.sayHello == o2.sayHello); //true /** * 分析: * globalSayHello 賦值給 o.sayHello , 每次執行 createPerson() 方法時 * o.sayHello 指向的都是同一個對象,因此結果是 true,這樣就解決了資源浪 * 費的問題,由於不管執行多少次 createPerson() 方法, o.sayHello 指向的 * 是同一個對象。 */
使用以上方式有個問題就是會定義不少的成員變量,每一個方法都是一個成員變量。這也是在重複對象
中提到的安全隱。可使用原型來解決這個問題。框架
function Person(name) { this.name = name; } /* 在原型中定義了 printName() 方法 */ Person.prototype.printName = function () { console.log(this.name); }; var p = new Person("王二麻"); var p1 = new Person("李四"); console.log(p.printName == p1.printName) //true /** * 不管建立多少個對象,printName 都只有一個,都是指向的同一個引用,因此 * 資源浪費的問題解決了,還有將方法定義在原型屬性中,也減小了一個成員變 * 量。若是須要定義多個方法,均可以定義在原型屬性中,也能夠採用下面的方式 * 給原型屬性賦值。 */ Person.prototype = { say: function () { return "hello"; }, hobby: function () { return "javascript"; } } var p2 = new Person("田七"); console.log(p2.say() + " " + p2.hobby()); //hello javascript
神祕對象針對構造函數稱爲原型屬性
函數
神祕對象與構造函數所建立出來的對象也有必定關係工具
原型對象
對象繼承自其原型性能
構造函數的原型屬性
該對象的原型對象
構造函數建立的對象
與構造函數的原型屬性表示的對象
是兩個不一樣
的對象