链式调用

以一个简单的例子为例,我们要实现一个链式的调用,例:

Man('pcd').eat('lunch').eat('dinner')

该方法简单,只需我们新建一个对象,将Man、eat作为对象的属性,每次调用时返回该对象变可以实现
例:

function _Man(name) {
	console.log('I am ' + name);
}

_Man.prototype.eat = function(something) {
	console.log('eat ' + something);
	return this;
}

function Man(name) {
	return new _Man(name);
}

Man('pcd').eat('lunch').eat('dinner');
//I am pcd
//eat lunch
//eat dinner

此时我们想改变一下,pcd不想吃完中饭后直接去吃晚饭,他想过5s之后再去吃晚饭

Man('pcd').eat('lunch').wait(5000).eat('dinner');

改变上面的例子

function _Man(name) {
	console.log('I am ' + name);
}

_Man.prototype.eat = function(something) {
	console.log('eat ' + something);
	return this;
}

_Man.prototype.wait = function(time) {
	setTimeout(function() {
		console.log('wait ' + time);
	}, time);
	return this;
}

function Man(name) {
	return new _Man(name);
}

Man('pcd').eat('lunch').wait(5000).eat('dinner');
//I am pcd
//eat lunch
//eat dinner
//wait 5000

输出的结果跟我们的预期不符,我们需要先"wait 5000"后再"ear dinner";当然你会想我们可以再执行完定时器之后再回到this对象就好了。如下

function _Man(name) {
	console.log('I am ' + name);
}

_Man.prototype.eat = function(something) {
	console.log('eat ' + something);
	return this;
}

_Man.prototype.wait = function(time) {
	var _this = this;
	setTimeout(function() {
		console.log('wait ' + time);
		return _this;
	}, time);
}

function Man(name) {
	return new _Man(name);
}

Man('pcd').eat('lunch').wait(5000).eat('dinner');
//I am pcd
//eat lunch
//Cannot read property 'eat' of undefined

但是却报了eat为undefined,因为我们在执行定时器操作相当于异步操作,而Man('pcd').eat('lunch').wait(5000).eat('dinner');中wait函数后的eat还需要继续执行,但此时的this还没有返回,故找不到eat的方法。所以我们需要换一种方式解决。
首先,我们先执行链式调用的Man('pcd').eat('lunch').wait(5000).eat('dinner');但不实际操作该函数,只是将其存放在数组中,通过setTimeout执行异步操作,从数组中一个个去除执行变可以了,如下:

function _Man(name) {
	console.log('I am ' + name);
	var _this = this;
	this.funcArr = [];
	setTimeout(function() {
		_this.next();
	})
}

_Man.prototype.next = function() {
	var fn = this.funcArr.shift();
	fn&&fn();
}

_Man.prototype.eat = function(something) {
	var _this = this;
	var func = function(something) {
		console.log('eat ' + something);
		_this.next()
	}
	this.funcArr.push(func);
	return this;
}

_Man.prototype.wait = function(time) {
	var _this = this;
	var func = function(time) {
		setTimeout(function() {
			console.log('wait ' + time);
			_this.next();
		}, time);
	}
	this.funcArr.push(func);
	return this;
}

function Man(name) {
	return new _Man(name);
}

Man('pcd').eat('lunch').wait(5000).eat('dinner');
//I am pcd
//eat undefined
//wait undefined
//eat undefined

此时你会发现函数虽然放入数组并一个个执行了,但函数的参数并没有传入进去。此时我们便需要使用高大上的闭包存储变量了。

function _Man(name) {
	console.log('I am ' + name);
	var _this = this;
	this.funcArr = [];
	setTimeout(function() {
		_this.next();
	})
}

_Man.prototype.next = function() {
	var fn = this.funcArr.shift();
	fn&&fn();
}

_Man.prototype.eat = function(something) {
	var _this = this;
	var func = (function(something) {
		return function() {
			console.log('eat ' + something);
			_this.next();
		}
	})(something);
	this.funcArr.push(func);
	return this;
}

_Man.prototype.wait = function(time) {
	var _this = this;
	var func = (function(time) {
		return function() {
			setTimeout(function() {
				console.log('wait ' + time);
				_this.next();
			}, time);
		}
	})(time);
	this.funcArr.push(func);
	return this;
}

function Man(name) {
	return new _Man(name);
}

Man('pcd').eat('lunch').wait(5000).eat('dinner');
//I am pcd
//eat lunch
//wait 5000
//eat dinner

大功告成。。。

原文地址:https://www.cnblogs.com/pcd12321/p/6327436.html