// 6.2.4 組合使用構造函數和原型模式————創建自定義對象的方法: function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.friends = ["Shelby", "C ...
// 6.2.4 組合使用構造函數和原型模式————創建自定義對象的方法:
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Shelby", "Court"];
}
Object.defineProperties(Person.prototype, {
"constructor": {
enumerable: false,
value: Person,
},
"sayName": {
enumerable: true,
value: function() {
console.log(this.name)
}
}
})
var person1 = new Person("Nicholas", 29, "Software Engineer");
// 6.2.5動態原型模式————將原型封裝到構造函數中:
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
// 只在第一次使用構造函數時if塊內的語句才會執行
if (typeof this.sayName.toLowerCase() != "function") {
Person.prototype.sayName = function() {
console.log(this.name);
}
}
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
// 6.2.6 寄生構造函數模式————用於為原生構造函數定義新的方法,避免污染原生構造函數
function Person(name, age, job) {
var obj = new Object();
obj.name = name;
obj.age = age;
obj.job = job;
obj.sayName = function() {
console.log(this.name);
}
return obj;
}
// 與工廠模式的區別是多了一個new操作符
var person1 = new Person("Nicholas", 29, "Software Engineer");
// ________________________________________________________________________
//寄生構造函數模式可以構造基於特殊對象(如數組)創建的具有指定方法的特殊對象
function SpecialArray() {
var values = new Array();
values.push.apply(values, arguments);
values.toPipedString = function() {
return values.join("|");
}
return values;
}
// 6.2.7 穩妥構造函數模式————將變數封裝到構造函數內部,不能通過對象屬性訪問,只能通過對象方法訪問
function Person(name, age, job) {
var obj = new Object();
obj.sayName = function() {
console.log(name);
}
return obj
}
var person1 = Person("jusing");
// 只能通過person1.sayName()方法訪問"jusing";person1對象實例中沒有name屬性
// 6.3.3 組合繼承模式(原型鏈+構造函數)
// !!!!!!!最常用的繼承方法!!!!!!!
//先定義超類型構造函數,綁定屬性
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
// 再定義超類型構造函數的原型,綁定方法;
SuperType.prototype.sayName = function() {
console.log(this.name);
}
// 定義子類型構造函數
function SubType(name, age) {
// 通過向子類型傳參,設置子類型實例的屬性值;
SuperType.call(this, name);
this.age = age;
}
// 將子類型的原型設置為超類型的對象實例
SubType.prototype = new SuperType();
Subtype.sayAge = function() {
console.log(this.age);
}
// 6.3.4 原型式繼承————直接以對象實例為原型創建構造函數並返回子類型對象實例
// ECMAScript為原型式繼承提供了原生方法: Object.create(obj, [A-V Object]),這個方法接受兩個參數,第一個是原型對象,第二個為鍵值對象(可選)
function object(obj) {
function F() {};
F.prototype = obj;
return new F();
}
var person = {
name: "jusing",
friends: ["Shelby", "Court", "Van"]
}
person1 = object(person);
// 6.3.5 寄生式繼承————在主要考慮對對象實例的繼承而不是自定義子類型對象的屬性時,簡單易用
function createAnother(obj) {
var clone = Object.create(obj);
// 增強對象的方法
clone.sayHi = function() {
console.log("Hi!");
}
return clone;
}
// 註意在使用寄生式繼承方法為對象添加方法時不能做到方法的復用,會浪費大量的資源
// 6.3.6 寄生組合式繼承————避免在超類型.prototype上創建多餘的屬性,還能保證原型鏈的不變。
// 這是開發人員普遍認為最完美的繼承方法
function inheritPrototype(subtype, supertype) {
// 創建超類型的原型對象作為子類型的原型
var prototype = Object.create(supertype.prototype);
// 將超類型的原型.constructor指向子類型構造函數
prototype.constructor = subType;
// 將子類型構造函數的原型指向超類型的原型
subType.prototype = prototype;
}
//先定義超類型構造函數,綁定屬性
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
// 再定義超類型構造函數的原型,綁定方法;
SuperType.prototype.sayName = function() {
console.log(this.name);
}
// 定義子類型構造函數
function SubType(name, age) {
// 通過向子類型傳參,設置子類型實例的屬性值;
SuperType.call(this, name);
this.age = age;
}
// 實現寄生組合繼承方法
inheritPrototype(SubType, SuperType);
// 為超類型的原型(此時已成為子類型構造函數的原型)添加方法
SubType.prototype.sayAge = function() {
console.log(this.age);
}
// 6.3.7 深度克隆————完全克隆一個引用值,但是不包括其原型鏈
function deepClone(origin, target) {
var target = target || {},
toStr = Object.prototype.toString,
arrStr = "[object Array]";
for(var prop in origin) {
// 過濾掉origin.prototype原型鏈上的屬性
if (origin.hasOwnProperty(prop)) {
// 針對origin上非null的對象屬性
if(origin[prop] !== "null" && typeof(origin[prop]) == "object") {
// 判斷是否為origin[prop]是否為數組對象
if(toStr.call(origin[prop]) == arrStr) {
target[prop] = [];
}
// 否則為對象
else {
target[prop] = {};
}
// 對數組與對象屬性進行遞歸方法
deepClone(origin[prop], target[prop]);
}
// 字元串等基本類型直接copy
else {
target[prop] = origin[prop];
}
}
}
return target;
}
// 7.4 私有變數————只能通過特權方法訪問函數內部變數
function MyObject() {
// 創建私有變數和私有函數
var privateVriable = 10;
function privateFunction() {
return false;
}
// 特權方法
this.publicMethod = function() {
console.log(privateVriable ++, privateFunction());
}
}
// 這種方法會導致特權方法重覆綁定,復用性不好
7.4.1 靜態私有變數————解決私有方法的復用性問題
(function() {
// 創建私有變數和私有函數
var privateVriable = 10;
function privateFunction() {
return false;
}
// 使用構造函數及原型綁定私有變數與函數
MyObject = function() {}; //這裡沒有用new操作符,將MyObject定義為全局變數,函數執行後可訪問
//原型
MyObject.prototype.publicMethod = function() {
console.log(privateVriable ++, privateFunction());
}
})
7.4.3 增強的模塊模式————私有變數、方法復用、對象增強
var singleton = function() {
var privateVriable = 10;
function privateFunction() {
return false;
}
var object = new CustomType();
object.publicProperty = true;
object.publicMethod = function() {
console.log(privateVriable ++, privateFunction());
}
return object;
}();