以一个简单的例子为例,我们要实现一个链式的调用,例:
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
大功告成。。。