//使用原型实现观察者模式
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);
});
}
});
}