链式调用

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值