笔记
//使用原型实现观察者模式 function Observer() { this.fns = []; } Observer.prototype = { //订阅 subscribe: function(fn) { this.fns.push(fn); }, //退订 unsubscribe: function(fn) { this.fns = this.fns.filter(function(el) { if(el !== fn) { return el; } }); }, //更新 update: function(o,thisObj) { var scope = thisObj || window; this.fns.forEach(function(el) { el.call(scope,o); }); } }; var ob = new Observer(); var f1 = function(data) { console.log('haode' + data); } var f2 = function(data) { console.log('ok' + data); } ob.subscribe(f1); ob.subscribe(f2); ob.update('我回来了~'); ob.unsubscribe(f1); ob.update('我回来了~'); /** haode我回来了~ ok我回来了~ ok我回来了~ **/ //实现forEach,返回的是一个数组 Array.prototype.filter = function(fn,thisObj) { var scope = thisObj || window; var a = []; for(var i = 0;i < this.length; i++) { if(!fn.call(scope,this[i],i,this)) { continue; } a.push(this[i]); } return a; } //实现forEach Array.prototype.forEach = function(fn,thisObj) { var scope = thisObj ||window; for(var i = 0;i < this.length;i++) { fn.call(scope,this[i],i,this); } } //使用on/off功能,定义jQuery版的观察者 (function($) { var o = $({}); $.subscribe = function() { o.on.apply(o,arguments); }; $.unsubscribe = function() { o.off.apply(o,arguments); }; $.publish = function() { o.trigger.apply(o,arguments); }; }(jQuery)); //回调函数 function handle(e, a, b, c) { // `e`是事件对象,不需要关注 console.log(a + b + c); }; //订阅 $.subscribe("/some/topic", handle); //发布 $.publish("/some/topic", ["a", "b", "c"]); // 输出abc $.unsubscribe("/some/topic", handle); // 退订 //订阅 $.subscribe("/some/topic", function (e, a, b, c) { console.log(a + b + c); }); $.publish("/some/topic", ["a", "b", "c"]); // 输出abc //退订(退订使用的是/some/topic名称,而不是回调函数哦,和版本一的例子不一样 $.unsubscribe("/some/topic"); //$.on 订阅者实现 EventEmiter.prototype.on = function(event,cb) { //event可以是事件名数组 if(event instanceof Array) { event.forEach( fn => { this.on(fn,cb); }); } if(this.events[event]) { this.events[event].push(cb); } else { this.events[event] = cb; } } //$.emit 发布者实现 EventEmiter.prototype.emit = function(event) { let args = Array.from(arguments).slice(1); let cbs = this.events[event]; if(cbs) { cbs.forEach( cb => { cb.apply(this,args); }) } } //$$.off 移除事件 EventEmiter.prototype.off = function(event,cb) { //没有参数的情况 if(!arguments) { this.events = Object.create(null); } //只指定事件 if(event instanceof Array) { event.forEach(evt => { this.off(evt,cb); }); } //提供了事件和回调 if(cb) { let cbs = this.events[event]; if(cbs) { for(var i = 0;i < cbs.length;i++) { if(cbs[i] == cb || cbs[i].cbName == cb) { cbs.splice(i,1); break; } } } } } //实现call Function.prototype.call = function(thisObj) { let scope = thisObj || window; scope.fn = this; let args = [...arguments].slice(1); //[...arr] 类数组变为数组 let result = scope.fn(...args); delete scope.fn; return result; } //实现apply Function.prototype.apply = function(thisObj) { let scope = thisObj || window; let args = arguments[1],result; scope.fn = this; if(args) { result = scope.fn(...args); } else { result = scope.fn(); } delete scope.fn; return result; } // 使用 call 或者 apply 实现 bind // bind 的输入:接受一个或者多个参数,第一个是要绑定的上下文,额外参数当作绑定函数的前置函数(最后concat的原因) // bind 的输出:返回原函数的拷贝 Function.prototype.bind = function(thisObj) { if(typeof this !== 'function') { return; } let _self = this; let args = Array.prototype.slice.call(arguments, 1); let fnNop = function() {} let fnBound = function() { let _this = this instanceof _self ? this:thisObj; return _self.apply(_this,args.concat(Array.prototype.slice.call(arguments))); } if(this.prototype) { fnNop.prototype = this.prototype; } fnBound.prototype = new fnNop; return fnBound; } //手写实现promise,遵循promiseA+规范,pending(等待状态),fulfilled(成功状态)、rejected(失败状态) function Promise(executor) { var self = this; self.status = 'pending'; self.value = undefined; //接受成功的值 self.reason = undefined; //接受失败回调传递的值 self.onResolved = []; //专门存放成功的回调,使用数组是因为回调可能会有多个 self.onRejected = []; //专门存放失败的回调 function resolve(value) { if(self.status == 'pending') { self.value = value; //将成功的原因保存 self.status = 'fulfilled'; self.onResolved.forEach(fn => fn()); //依次调用保存的函数 } } function reject(reason) { if(self.status == 'pending') { self.reason = reason; //将失败的结果保存 self.status = 'rejected'; self.onRejected.forEach(fn => fn()); } } executor(resolve,reject); } function resolvePromise(promise2,x,resolve,reject) { if(promise2 == x) { //防止回调地狱的形成,需要判断他俩之间的关系 return reject(new TypeError('循环引用')); } if(x!=null && (typeof x === 'Object' || typeof x === 'function')) { try { var then = x.then; if(typeof then === 'function') { then.call(x,(y) => { if(called) return; called = true; resolvePromise(promise2,y,resolve,reject); //递归解析,重复执行,直到返回的不是一个promise为止 },(e) => { if(called) return; called = true; reject(e); }); } else { resolve(x); } } catch(error) { reject(error); } } else { resolve(x); } } Promise.prototype.then = function(onfulfilled,onrejected) { onfulfilled = typeof onfulfilled == 'function' ? onfulfilled : val=>val; onrejected = typeof onrejected == 'function' ? onrejected : err => { throw err; } var self = this; var promise2; promise2 = new Promise((resolve,reject) => { if(self.status == 'fulfilled') { var x = onfulfilled(self.value); resolvePromise(promise2,x,resolve,reject); } if(self.status == 'rejected') { var x = onrejected(self.reason); resolvePromise(promise2,x,resolve,reject); } if(self.status == 'pending') { self.onResolved.push(function() { var x = onfulfilled(self.value); resolvePromise(promise2,x,resolve,reject); }); self.onRejected.push(function() { var x = onrejected(self.reason); resolvePromise(promise2,x,resolve,reject); }); } }); }