笔记

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

  

posted @ 2019-05-28 23:46  SunLemon  阅读(195)  评论(0编辑  收藏  举报