1. 寫出 構(gòu)造函數(shù)模式瞪醋、混合模式稽寒、模塊模式、工廠模式趟章、單例模式、發(fā)布訂閱模式的范例慎王。
-
構(gòu)造函數(shù)模式
寫一個(gè)函數(shù)蚓土,把私有屬性綁定到函數(shù)內(nèi)部的this
上,
把一些私有方法寫到函數(shù)的原型鏈上, 然后通過new
關(guān)鍵字來創(chuàng)建一個(gè)實(shí)例對(duì)象赖淤。
function Pepole(name, age) {
this.name = name;
this.age = age;
}
Pepole.prototype.sayName = funcion() {
return this.name;
};
var student = new Pepole("xsnowholy", 22);
console.log(student);
-
混合模式
建立在構(gòu)造函數(shù)模式的基礎(chǔ)上蜀漆,實(shí)現(xiàn)子類繼承父類的屬性和方法,子類可以在擴(kuò)展屬性和方法咱旱。
var Person = function(name, age) {
this.name = name;
this.age = age;
};
Person.prototype.sayName = function(){
console.log(this.name);
}
var Student = function(name, age, score) {
Person.call(this, name, age);
this.score = score;
};
//Student.prototype = Object.create(Person.prototype); //ES5方法确丢,原型鏈繼承
Student.prototype = create(Person.prototype);
function create (parentObj){ // 兼容IE
function F(){}
F.prototype = parentObj;
return new F();
};
Student.prototype.sayScore = function(){
console.log(this.score);
}
var student = new Student("xsnowholy", 22, 95);
console.log(student);
-
模塊模式
使用立即執(zhí)行函數(shù)包裹代碼段绷耍,使內(nèi)部的私有變量和方法不會(huì)暴露出來,通過return函數(shù)給外部提供使用內(nèi)部方法的接口鲜侥。
這樣的好處是不會(huì)污染全局變量褂始,外部無法訪問或者改變模塊內(nèi)部的變量和方法。
var Pepole = (function(){
var name = "xsnowholy";
return {
sayName : function() {
console.log(name);
},
changeName : function(newName) {
name = newName;
}
}
})();
Pepole.sayName();
Pepole.changeName("蕭雪圣");
Pepole.sayName();
-
工廠模式
工廠模式可以算是構(gòu)造函數(shù)模式的基礎(chǔ)版描函,
需要一個(gè)對(duì)象的時(shí)候可以通過這個(gè)函數(shù)創(chuàng)建一個(gè)對(duì)象崎苗,
但是這個(gè)對(duì)象沒有構(gòu)造函數(shù),無法用 instanceof 的方法判斷是否為實(shí)例舀寓。
function createPerson(opts){
var person = {
name: opts.name||'xsnowholy'
};
person.sayName: function(){
console.log(this.name);
}
return person;
}
var p1 = createPerson({name:'xsnowholy'});
var p2 = createPerson({name: '蕭雪圣'});
-
單例模式
單例模式就是胆数,如果你要使用這個(gè)函數(shù)創(chuàng)建一個(gè)對(duì)象,如果這個(gè)對(duì)象存在則直接返回這個(gè)對(duì)象互墓,如果對(duì)象不存在則創(chuàng)建這個(gè)對(duì)象必尼。
無論你使用這個(gè)函數(shù)多少次,得到的都是同一個(gè)對(duì)象篡撵。
var People = (function(){
var instance;
function init() {
//define private methods and properties
//do something
return {
//define public methods and properties
};
}
return {
createPeople: function() {
if (!instance) {
instance = init();
}
return instance;
}
};
}());
var obj1 = People.createPeople();
var obj2 = People.createPeople();
-
發(fā)布訂閱模式
發(fā)布訂閱模式判莉,可以自定義發(fā)布事件,事件處理函數(shù)酸休,通過訂閱事件來觸發(fā)事件骂租,執(zhí)行函數(shù)。
var EventCenter = (function() {
var events = {};
function on(evt, handler) { // 發(fā)布事件
events[evt] = events[evt] || [];
events[evt].push({ // 同一個(gè)事件綁定多個(gè)方法
handler: handler
})
}
function fire(evt, args) { // 訂閱事件
if(!events[evt]) return;
for (var i=0; i<events.length; i++) {
events[evt][i].handler(args); // 執(zhí)行事件的多個(gè)方法
}
}
function off(evt) { // 刪除事件
if(!events[evt]) return;
delete events[evt];
}
return {
on: on,
fire: fire,
off: off;
}
})();
EventCenter.on("myEvent", function(data){
console.log("myEvent received...");
})
//發(fā)布事件
EventCenter.fire("myEvent");
//訂閱事件斑司,如果該事件被添加發(fā)布過渗饮,則執(zhí)行相應(yīng)的函數(shù)方法
EventCenter.off("myEvent");
//刪除事件 myEvent 事件
2. 使用發(fā)布訂閱模式寫一個(gè)事件管理器,可以實(shí)現(xiàn)如下方式調(diào)用
Event.on('change', function(val){
console.log('change... now val is ' + val);
});
Event.fire('change', '饑人谷');
Event.off('change');
var Event = (function() {
var events = {};
function on(evt, handler) { // 發(fā)布事件
events[evt] = events[evt] || [];
events[evt].push({ // 同一個(gè)事件綁定多個(gè)方法
handler: handler
})
}
function fire(evt, args) { // 訂閱事件
if(!events[evt]) return;
for (var i=0; i<events.length; i++) {
events[evt][i].handler(args); // 執(zhí)行事件的多個(gè)方法
}
}
function off(evt) { // 刪除事件
if(!events[evt]) return;
delete events[evt];
}
return {
on: on,
fire: fire,
off: off;
}
})();
Event.on('change', function(val){ // 發(fā)布事件
console.log('change... now val is ' + val);
});
Event.fire('change', '饑人谷'); // 訂閱事件 輸出結(jié)果: change... now val is 饑人谷
Event.off('change'); // 刪除事件