一、什麼是原型模式
在js中,建立物件的方式有工廠模式和建構函式模式等; 而建構函式模式最大的問題在於:建構函式中的每個方法都需要在例項物件中重新建立一遍,不能復用,所以為了解決這乙個問題,就需要使用原型模式來建立物件。
原型模式是把所有例項共享的方法和屬性放在乙個叫做prototype(原型)的屬性中 ,在建立乙個函式時都會有個prototype屬性, 這個屬性是乙個指標,指向乙個物件,是通過呼叫建構函式而建立的那個物件例項的原型物件。
// 建構函式
function person() {};
// 原型屬性prototype
person.prototype.name = '張三';
person.prototype.sayname = function() ;
let person1 = new person();
person1.sayname(); //張三
let person2 = new person();
person2.sayname(); // 張三
console.log(person1.sayname == person2.sayname); //true
原型與in操作符
hasownproperty()方法可以檢測乙個屬性是否存在於例項物件中,
// 建構函式
function person() ;
person.prototype.name = 「張三」;
let person1 = new person();
console.log(person1.hasownproperty(『name』)); // false
console.log(person1.hasownproperty(『age』)); // true
in操作符的使用可以分為兩類,單獨使用和在for-in迴圈使用,在單獨使用時,in操作符會在通過物件能夠訪問給定屬性時返回true,無論該屬性存在於例項中還是原型中。
// 建構函式
function person() {}
person.prototype.name = 『zhang』;
let person1 = new person();
console.log(『name』 in person1); // true
person1.age = 14;
console.log(『age』 in person1); // true
同時使用hasownproperty()方法和in操作符,可以確定該屬性時在原型上還是在存在於物件中。
// 建構函式
function person() {}
function hasprototypeproperty(object, name)
person.prototype.name = 「張三」;
let person = new person();
console.log(hasprototypeproperty(person, 『name』)); // true
console.log(hasprototypeproperty(person, 『age』)); // false
使用for-in迴圈時,返回的是所有能夠通過物件訪問的、可列舉的屬性,其中即包含存在於例項中的屬性,也包含與存在原型中的屬性。
let o = ;
for(let key in o)
要取得物件上所有可列舉的例項屬性,可以使用object.keys()方法,接收乙個物件作為引數,返回乙個包含所有可列舉屬性的字串陣列。
如果想得到所有例項屬性。無論是否可列舉,都可以使用object.getownpropertynames()方法。
更簡單的原型語法
為了減少不必要的輸入和從視覺上更好的封裝原型的功能,常見的做法是用乙個包含所有屬性和方法的物件字面量來重寫整個原型物件。
// 建構函式
function person() {};
person.prototype = ,
name: 『張三』,
};通過這個方式會導致原型物件中的constructor屬性不在指向person了。如果constructor的值真的很重要,可以像下面這樣特意將它設定回適當的值。
// 建構函式
function person() {};
person.prototype = ,
name: 『張三』,
};但是通過這種方式會導致物件的[[enumerable]]特性被設定為ture,預設情況下,constructor屬性時不可列舉的,可以通過object.defineproperty()解決這個問題。
// 建構函式
function person() {};
person.prototype = ,
name: 『張三』,
};object.defineproperty(person.prototype, 「constructor」,
原型的動態性
當對原型物件所做的任何修改都能夠立即從例項上反應出來。
function person() {};
var friend = new person();
person.prototype.sayhi = function() ;
friend.sayhi(); // hi
但是如果是重寫整個原型物件,那麼情況就不一樣了。呼叫建構函式時會為例項新增乙個指向最初原型的[[prototype]]指標,而把原型修改為另外乙個物件 就相當於切斷了建構函式與最初原型之間的聯絡。 例項中的指標僅指向原型,而不是指向建構函式。
// 建構函式
function person() {};
var friend = new person();
person.prototype =
};friend.sayhi(); // uncaught typeerror: friend.sayhi is not a function
建立了乙個person的例項,然後又重寫了其原型物件。但是在使用sayhi()時發生了錯誤,這個時候例項所指向的原型物件是乙個新的物件。重寫原型物件切斷了現有原型與之前已經存在的物件例項直接的聯絡。所以報錯了。
原生物件的原型
原型模式的重要性不僅體現在建立自定義型別方面,就連所有原生的引用型別,都採用這種模式,所有的原生引用型別(object、array、string)等,都在其建構函式的原型上定義了方法。可以像修改自定義物件的原型一樣修改原生物件的原型。
二、原型模式的缺點
對於包含引用型別值的屬性來說,所有例項在預設的情況下都會取得相同的屬性值。
// 建構函式
function person() {};
// 原型屬性prototype
person.prototype =
let person1 = new person();
let person2 = new person();
person1.friends.push(『王五』);
console.log(person1.friends); // [「張三」, 「李四」, 「王五」]
console.log(person2.friends); // [「張三」, 「李四」, 「王五」]
由於friends存在於person的原型物件中,所以person1對friends的修改也會通過person2反應出來,但是例項物件一般都是要有屬於自己的全部屬性,正因為如此,很少有人單獨使用原型模式來建立物件。
js中建立物件方式 原型模式
一 什麼是原型模式 在js中,建立物件的方式有工廠模式和建構函式模式等 而建構函式模式最大的問題在於 建構函式中的每個方法都需要在例項物件中重新建立一遍,不能復用,所以為了解決這乙個問題,就需要使用原型模式來建立物件。原型模式是把所有例項共享的方法和屬性放在乙個叫做prototype 原型 的屬性中...
js建立物件 原型模式
原型模式是用來建立物件的,它是在建構函式建立物件基礎上,為了實現資料的共享,這種共享包括屬性的共享,也包括方法的共享。既然原型模式是在建構函式模式的基礎上改進的,那麼這種模式會既有建構函式的特點又有原型模式的特點。關於原型模式的使用方法用一句話總結 不需要共享的資料寫在建構函式中,需要共享的資料寫在...
原型模式 建立物件
原型模式 操作 先建立好乙個原型物件,然後通過clone 原型物件來建立新的物件。這就免去了類建立時重複的初始化操作。原型模式適用於大物件的建立。如果每次new 就會消耗很大,原型模式僅需要記憶體拷貝即可。index.php 中 prototype new imooc canvas prototyp...