- 把做什么和谁去做分离开来,消除类型直接的耦合性
- 将过程化的条件分支语句转化为对象的多态性,从而消除分支语句
Function.prototype.bind =function(context,argument){
var seelf = this;
return function(){
return self.apply(context,arguments)
}
}
JavaScript 特别灵活;随着Node.js以及html5和web2.0的兴起,JavaScript变得越来越受重视
PS:注意
var a= "";
var a=new String();//这个是有成本的
var printer = (function(){
var printerInstance;
function create(){ //私有方法
function print(){}
function turnOn(){}
return {
print:print,
turnOn:turnOn
};
}
return {
getInstance:function(){ //公开方法
if(!printerInstance){
printerInstance = create();
}
return printerInstance;
}
};
function Singleton () {
if(!printerInstance) {
printerInstance = intialize();
}
};
})()
//生成打印机的实例
var officePrinter = printer.getInstance();
//测试
var uni = new Universe()
var uni2 = new Universe()
uni=== uni2 //结果为true
var getSingle = function(fn){
var result;
return function(){
return result || (result = fn.apply(this.arguments));
}
}
优点:简洁;类似Universe.instance的属性用来缓存该属性
缺点:instance属性是公开可访问的属性
function Universe(){
//判断是否已经存在Universe.instance
if(typeof Universe.instance ==="object"){
return Universe.instance;
}
this.start_time = 0;
this.bang ="Big"
//缓存
Universe.instance =this; //Universe.instance是公开属性,存在被外界修改的可能
//隐式返回
return this
}
优点:【保证实例的私有性,并保证该实例不会被构造函数之外的代码替代】
缺点:带来了额外的闭包开销
//实现1——————————私有成员模式实现————————重写构造函数————————闭包
function Universe(){
//缓存实例
var instance = this;
//正常添加属性
this.start_time = 0;
this.bang ="Big"
//重写构造函数
Universe = function(){
return instance;
}
}
//缺点:需要重写构造函数,且测试如下
Universe.prototype.nothing = true; //向原型添加属性
var uni = new Universe();
Universe.prototype.everything =true; //在创建初始化对象之后,再次向该原型添加属性
var uni2 = new Universe();
//uni.nothing 与 unin2.nothing 都存在为true
//uni.everything 与uni2.everything 都不存在 为undefined
uni.constructor.name //结果为Universe
uni.constructor === Universe//结果为false uni,constructor指向原始的构造函数
//实现2 将构造函数的指针在函数内部进行处理
function Universe(){
//缓存实例
var instance;
//重写构造函数
Universe = function(){
return instance;
}
Universe.prototype = this; //保留原型属性
instance = new Universe(); //构造实例
//重置构造函数指针
instance.constructor =Universe;
//加功能
instance.start_time = 0;
instance.bang = "Big"
return instance;
}
//如上测试均成功
//uni.nothing && uni.everything && uni2.nothing && uni2.everything //结果为true
//将构造函数和实例包装在即时函数中
var Universe;
(function(){
var instance;
Universe = function Universe(){
if(instance){ return instance; }
instance = this;
this.start_time =0;
this.bang = "Big"
}
})()
//只是单例
var mySingleton = {
property1:"",
property2:"",
method:function(){
}
}
//单例+公私分明
var mySingleton = function () {
/* 这里声明私有变量和方法 */
var privateVariable = 'something private';
function showPrivate() {
console.log(privateVariable);
}
/* 公有变量和方法(可以访问私有变量和方法) */
return {
publicMethod: function () {
showPrivate();
},
publicVar: 'the public can see this!'
};
};
var single = mySingleton();
single.publicMethod(); // 输出 'something private'
console.log(single.publicVar); // 输出 'the public can see this!'
//单例+ 公私分明+按需初始化
var Singleton = (function(){
var instantiated;
function init(){
//定义单例代码
return{
publicMethod:function(){
console.log('hello world');
},
publicProperty:'test'
};
}
return {
getInstance:function(){
if(!instantiated){
instantiated = init();
}
return instantiated;
}
};
})();
Singleton.getInstance().publicMethod();
//最佳实践的代码
var SingletonTester = (function(){
//参数:传递给单例一个参数集合
function Singleton(args){
//设置args变量为接收的参数或者为空(如果没有提供的话)
var args = args || {};
//设置name参数
this.name = 'SingletonTester';
//设置pointX的值
this.pointX = args.pointX || 6; //从接收的参数里获取,或者设置为默认值
//设置pointY的值
this.pointY = args.pointY || 10;
}
//实例容器
var instance;
var _static = {
name: 'SingletonTester',
//获取实例的方法
//返回Singleton的实例
getInstance: function (args) {
if (instance === undefined) {
instance = new Singleton(args);
}
return instance;
}
};
return _static;
})();
var singletonTest = SingletonTester.getInstance({ pointX: 5 });
console.log(singletonTest.pointX); // 输出 5
var CreateDiv = function(html){
this.html=html
this.init()
}
CreateDiv.prototype.init = function(){
var div =document.createElement('div');
div.innerHTML = this.htmll
document.body,appendChild(div);
}
var ProxySingleCreateDiv = (function(){ //代理
var instance;
return function(){
if(!instance){
instance = new CreateDiv(html);
}
return instance;
}
})()
var a =new ProxySingleCreateDiv('seven1');
var b = new ProxySingleCreateDiv('sevent2');
alert(a==b)
var pubsub = {};
(function (q) {
var topics = {}, // 回调函数存放的数组
subUid = -1;
// 发布方法
q.publish = function (topic, args) { //args='hello world!' topics['example1']存在
if (!topics[topic]) {
return false;
}
setTimeout(function () {
var subscribers = topics[topic], //subscribe = topics['example1']
len = subscribers ? subscribers.length : 0; //len=2
while (len--) {
subscribers[len].func(topic, args); //subscribers[2]
}
}, 0);
return true;
};
//订阅方法
q.subscribe = function (topic, func) { //topic = 'example1'; func=function(topics,data){ console.log(topics+':'+data);}
if (!topics[topic]) { //topics['example1'] =[]
topics[topic] = [];
}
var token = (++subUid).toString(); //subUid=0 token="0"
topics[topic].push({ // topics['example1'] = {token:token,func:function(topics,data){ console.log(topics+':'+data);}
token: token,
func: func
});
return token; // return "0"
};
//退订方法
q.unsubscribe = function (token) {
for (var m in topics) {
if (topics[m]) {
for (var i = 0, j = topics[m].length; i < j; i++) {
if (topics[m][i].token === token) {
topics[m].splice(i, 1);
return token;
}
}
}
}
return false;
};
} (pubsub));
//使用方法:来,订阅一个
pubsub.subscribe('example1', function (topics, data) {
console.log(topics + ": " + data);
}); //return "0"
//发布通知
pubsub.publish('example1', 'hello world!');
pubsub.publish('example1', ['test', 'a', 'b', 'c']);
pubsub.publish('example1', [{ 'color': 'blue' }, { 'text': 'hello'}]);
function Observer(){
this.fns=[];
}
Obeserver.prototype = {
subscribe :function(fn){
this.fns.push(fn);
},
unsubscribe:function(fn){
this.fns = this.fns.filter( //将不fn的元素取出来,再赋给this.fn,用来得到新的订阅单
function(el){
if(el !== fn){
return el;
}
}
)
},
update:function(arg, thisObj){
var scope=thisObj || window;
this.fns.forEach( //执行每一个观察者都执行的函数
function(el){
el.call(scope,arg); //call的两个参数,以为this指向,二为传入的参数
//让每个观察者都执行 ???如何理解
}
);
}
};
//测试
var o=new Observer;
var f1 = function(data){
console.log('函数1'+data);
};
var f2 = function(data){
console.log('函数2'+data);
}
o.subscribe(f1);
o.subscribe(f2);
o.update('更新');
o.unsubscribe(f1);
o.update('更新测试');
/** delete obj.name 对象属性删除
* delete obj;变量删除
* delete 删除不了原型链中的变量
* */
//通用代码
var observer ={
//订阅
addSubscriber:function(callback){
this.subscribers[this.subscribers.length] =callback;
},
//退订
removeSubscriber:function(callback){
for(var i=0;i<this.subscribers.length;i++){
if(this.subscribers[i] === callback){
delete(this.subscribers[i]); //删除
}
}
},
//发布
publish:function(what){
for(var i=0;i<this.subscribers.length;i++){
if(typeof this.subscribers[i]==='function'){
this.subscribers[i](what);
}
}
},
//将对象o具有观察者功能
make:function(o){
for(var i in this){
o[i] =this[i];
o.subscribers = [];
}
}
}
//订阅对象
var blogger = {
recommend:function(id){
var msg='杜杜推荐了帖子'+id;
this.publish(msg);
}
};
var user ={
vote:function(id){
var msg="有人投票了帖子Id为"+id;
this.publish(msg);
}
};
observer.make(blogger);
observer.make(user);
//订阅不同的回调函数,以便可以注册到不同的观察者对象里,也可以同时注册到多个观察者对里
var tom={
read:function(what){
console.log('Tom看到了如下信息'+what);
}
}
var mm = {
show:function(what){
console.log('mm看到了如下消息'+what);
}
};
//订阅
blogger.addSubscriber(tom.read); //将tom.read添加到blogger.subscribers数组里面
blogger.addSubscriber(mm.show);
blogger.recommend(123);//调用发布
//退订
blogger.removeSubscriber(mm.show);
blogger.recommend(456);
//另外一个对象的订阅
user.addSubscriber(mm.show);
user.vote(789); //调用发布
(function($){
var o =$({});
$.subscribe = function(){
o.on.apply(o,arguments); //o.on是绑定函数 function(){} apply是将this指向了o,然后传参数进去
};
$.unsubscribe=function(){
o.off.apply(o,arguments); //移除一个事件处理函数
};
$.publish = function(){
o.trigger.apply(o,arguments); //根据绑定到匹配元素的给定的事件类型执行所有的处理程序和行为
//trigger 第一个参数是event事件??
}
})(jQuery);
//回调函数
function handle(e,a,b,c){
//e是事件对象,不需要关注
}
//订阅
$.subscribe("/some/topic",handle);
//发布
$.publish("/some/topic",["a","b","c"]);//输出abc
$.unsubscribe("/some/topic",handle);
//订阅
$.subscribe("some",function(e,a,b,c){
console.log(a+b+c);
});
$.publish("/some/topic",["a","b","c"]);
//退订
$.unsubscribe("/some/topic");