成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

underscore 系列之鏈?zhǔn)秸{(diào)用

zhangrxiang / 2197人閱讀

摘要:我們都知道可以鏈?zhǔn)秸{(diào)用,比如我們寫(xiě)個(gè)簡(jiǎn)單的模擬鏈?zhǔn)秸{(diào)用之所以能實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,關(guān)鍵就在于通過(guò),返回調(diào)用對(duì)象。系列預(yù)計(jì)寫(xiě)八篇左右,重點(diǎn)介紹中的代碼架構(gòu)鏈?zhǔn)秸{(diào)用內(nèi)部函數(shù)模板引擎等內(nèi)容,旨在幫助大家閱讀源碼,以及寫(xiě)出自己的。

前言

本文接著上篇《underscore 系列之如何寫(xiě)自己的 underscore》,閱讀本篇前,希望你已經(jīng)閱讀了上一篇。

jQuery

我們都知道 jQuery 可以鏈?zhǔn)秸{(diào)用,比如:

$("div").eq(0).css("width", "200px").show();

我們寫(xiě)個(gè)簡(jiǎn)單的 demo 模擬鏈?zhǔn)秸{(diào)用:

function JQuery(selector) {
    this.elements = [];
    var nodeLists = document.getElementsByTagName(selector);
    for (var i = 0; i < nodeLists.length; i++) {
        this.elements.push(nodeLists[i]);
    }
    return this;
}

JQuery.prototype = {
    eq: function(num){
        this.elements = [this.elements[0]];
        return this;
    },
    css: function(prop, val) {
        this.elements.forEach(function(el){
            el.style[prop] = val;
        })
        return this;
    },
    show: function() {
        this.css("display", "block");
        return this;
    }

}

window.$ = function(selector){
    return new JQuery(selector)
}

$("div").eq(0).css("width", "200px").show();

jQuery 之所以能實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,關(guān)鍵就在于通過(guò) return this,返回調(diào)用對(duì)象。再精簡(jiǎn)下 demo 就是:

var jQuery = {
    eq: function(){
        console.log("調(diào)用 eq 方法");
        return this;
    },
    show: function(){
        console.log("調(diào)用 show 方法");
        return this;
    }
}

jQuery.eq().show();
_.chain

在 underscore 中,默認(rèn)不使用鏈?zhǔn)秸{(diào)用,但是如果你想使用鏈?zhǔn)秸{(diào)用,你可以通過(guò) _.chain 函數(shù)實(shí)現(xiàn):

_.chain([1, 2, 3, 4])
.filter(function(num) { return num % 2 == 0; })
.map(function(num) { return num * num })
.value(); // [4, 16]

我們看看 _.chain 這個(gè)方法都做了什么:

_.chain = function (obj) {
    var instance = _(obj);
    instance._chain = true;
    return instance;
};

我們以 [1, 2, 3] 為例,_.chain([1, 2, 3]) 會(huì)返回一個(gè)對(duì)象:

{
    _chain: true,
    _wrapped: [1, 2, 3]
}

該對(duì)象的原型上有著 underscore 的各種方法,我們可以直接調(diào)用這些方法。

但是問(wèn)題在于原型上的這些方法并沒(méi)有像 jQuery 一樣,返回 this ,所以如果你調(diào)用了一次方法,就無(wú)法接著調(diào)用其他方法了……

但是試想下,我們將函數(shù)的返回值作為參數(shù)再傳入 _.chain 函數(shù)中,不就可以接著調(diào)用其他方法了?

寫(xiě)一個(gè)精簡(jiǎn)的 Demo:

var _ = function(obj) {
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
};

_.chain = function (obj) {
    var instance = _(obj);
    instance._chain = true;
    return instance;
};

_.prototype.push = function(num) {
    this._wrapped.push(num);
    return this._wrapped
}

_.prototype.shift = function(num) {
    this._wrapped.shift()
    return this._wrapped
}

var res = _.chain([1, 2, 3]).push(4);
// 將上一個(gè)函數(shù)的返回值,傳入 _.chain,然后再繼續(xù)調(diào)用其他函數(shù)
var res2 = _.chain(res).shift();

console.log(res2); // [2, 3, 4]

然而這也太復(fù)雜了吧,難道 chain 這個(gè)過(guò)程不能是自動(dòng)化的嗎?如果我是開(kāi)發(fā)者,我肯定希望直接寫(xiě)成:

_.chain([1, 2, 3]).push(4).shift()

所以我們?cè)賰?yōu)化一下實(shí)現(xiàn)方式:

var _ = function(obj) {
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
};

var chainResult = function (instance, obj) {
    return instance._chain ? _.chain(obj) : obj;
};

_.chain = function (obj) {
    var instance = _(obj);
    instance._chain = true;
    return instance;
};

_.prototype.push = function(num) {
    this._wrapped.push(num);
    return chainResult(this, this._wrapped)
}

_.prototype.shift = function() {
    this._wrapped.shift();
    return chainResult(this, this._wrapped)
}

var res = _.chain([1, 2, 3]).push(4).shift();

console.log(res._wrapped);

我們?cè)诿總€(gè)函數(shù)中,都用 chainResult 將函數(shù)的返回值包裹一遍,再生成一個(gè)類似以下這種形式的對(duì)象:

{
    _wrapped: some value, 
    _chain: true
}

該對(duì)象的原型上有各種函數(shù),而這些函數(shù)的返回值作為參數(shù)傳入了 chainResult,該函數(shù)又會(huì)返回這樣一個(gè)對(duì)象,函數(shù)的返回值就保存在 _wrapped 中,這樣就實(shí)現(xiàn)了鏈?zhǔn)秸{(diào)用。

_.chain鏈?zhǔn)秸{(diào)用原理就是這樣,可是這樣的話,我們需要對(duì)每個(gè)函數(shù)都進(jìn)行修改呀……

幸運(yùn)的是,在 underscore 中,所有的函數(shù)是掛載到 _ 函數(shù)對(duì)象中的,_.prototype 上的函數(shù)是通過(guò) _.mixin 函數(shù)將 _ 函數(shù)對(duì)象中的所有函數(shù)復(fù)制到 _.prototype 中的。

所以為了實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,我們還需要對(duì)上一篇《underscore 系列之如何寫(xiě)自己的 underscore》 中的 _.mixin 方法進(jìn)行一定修改:

// 修改前
var ArrayProto = Array.prototype;
var push = ArrayProto.push;

_.mixin = function(obj) {
    _.each(_.functions(obj), function(name) {
        var func = _[name] = obj[name];
        _.prototype[name] = function() {
            var args = [this._wrapped];
            push.apply(args, arguments);
            return func.apply(_, args);
        };
    });
    return _;
};

_.mixin(_);
// 修改后
var ArrayProto = Array.prototype;
var push = ArrayProto.push;

var chainResult = function (instance, obj) {
    return instance._chain ? _(obj).chain() : obj;
};

_.mixin = function(obj) {
    _.each(_.functions(obj), function(name) {
        var func = _[name] = obj[name];
        _.prototype[name] = function() {
            var args = [this._wrapped];
            push.apply(args, arguments);
            return chainResult(this, func.apply(_, args));
        };
    });
    return _;
};

_.mixin(_);
_.value

根據(jù)上面的分析過(guò)程,我們知道如果我們打?。?/p>

console.log(_.chain([1, 2, 3]).push(4).shift());

其實(shí)會(huì)打印一個(gè)對(duì)象 {_chain: true, _wrapped: [2, 3, 4] }

可是我希望獲得值是 [2, 3, 4] 呀!

所以,我們還需要提供一個(gè) value 方法,當(dāng)執(zhí)行 value 方法的時(shí)候,就返回當(dāng)前 _wrapped 的值。

_.prototype.value = function() {
    return this._wrapped;
};

此時(shí)調(diào)用方式為:

var arr = _.chain([1, 2, 3]).push(4).shift().value();
console.log(arr) // [2, 3, 4]
最終代碼

結(jié)合上一篇文章,最終的 underscore 代碼組織結(jié)構(gòu)如下:

(function() {

    var root = (typeof self == "object" && self.self == self && self) ||
        (typeof global == "object" && global.global == global && global) ||
        this || {};

    var ArrayProto = Array.prototype;

    var push = ArrayProto.push;

    var _ = function(obj) {
        if (obj instanceof _) return obj;
        if (!(this instanceof _)) return new _(obj);
        this._wrapped = obj;
    };

    if (typeof exports != "undefined" && !exports.nodeType) {
        if (typeof module != "undefined" && !module.nodeType && module.exports) {
            exports = module.exports = _;
        }
        exports._ = _;
    } else {
        root._ = _;
    }

    _.VERSION = "0.2";

    var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;

    var isArrayLike = function(collection) {
        var length = collection.length;
        return typeof length == "number" && length >= 0 && length <= MAX_ARRAY_INDEX;
    };

    _.each = function(obj, callback) {
        var length, i = 0;

        if (isArrayLike(obj)) {
            length = obj.length;
            for (; i < length; i++) {
                if (callback.call(obj[i], obj[i], i) === false) {
                    break;
                }
            }
        } else {
            for (i in obj) {
                if (callback.call(obj[i], obj[i], i) === false) {
                    break;
                }
            }
        }

        return obj;
    }

    _.isFunction = function(obj) {
        return typeof obj == "function" || false;
    };

    _.functions = function(obj) {
        var names = [];
        for (var key in obj) {
            if (_.isFunction(obj[key])) names.push(key);
        }
        return names.sort();
    };

    /**
     * 在 _.mixin(_) 前添加自己定義的方法
     */
    _.reverse = function(string){
        return string.split("").reverse().join("");
    }

    _.chain = function(obj) {
        var instance = _(obj);
        instance._chain = true;
        return instance;
    };

    var chainResult = function(instance, obj) {
        return instance._chain ? _(obj).chain() : obj;
    };

    _.mixin = function(obj) {
        _.each(_.functions(obj), function(name) {
            var func = _[name] = obj[name];
            _.prototype[name] = function() {
                var args = [this._wrapped];
                push.apply(args, arguments);
                return chainResult(this, func.apply(_, args));
            };
        });
        return _;
    };

    _.mixin(_);

    _.prototype.value = function () {
        return this._wrapped;
    };

})()
underscore 系列

underscore 系列目錄地址:https://github.com/mqyqingfeng/Blog。

underscore 系列預(yù)計(jì)寫(xiě)八篇左右,重點(diǎn)介紹 underscore 中的代碼架構(gòu)、鏈?zhǔn)秸{(diào)用、內(nèi)部函數(shù)、模板引擎等內(nèi)容,旨在幫助大家閱讀源碼,以及寫(xiě)出自己的 undercore。

如果有錯(cuò)誤或者不嚴(yán)謹(jǐn)?shù)牡胤?,?qǐng)務(wù)必給予指正,十分感謝。如果喜歡或者有所啟發(fā),歡迎star,對(duì)作者也是一種鼓勵(lì)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/89915.html

相關(guān)文章

  • underscore 的源碼該如何閱讀?

    摘要:所以它與其他系列的文章并不沖突,完全可以在閱讀完這個(gè)系列后,再跟著其他系列的文章接著學(xué)習(xí)。如何閱讀我在寫(xiě)系列的時(shí)候,被問(wèn)的最多的問(wèn)題就是該怎么閱讀源碼我想簡(jiǎn)單聊一下自己的思路。感謝大家的閱讀和支持,我是冴羽,下個(gè)系列再見(jiàn)啦 前言 別名:《underscore 系列 8 篇正式完結(jié)!》 介紹 underscore 系列是我寫(xiě)的第三個(gè)系列,前兩個(gè)系列分別是 JavaScript 深入系列、...

    weknow619 評(píng)論0 收藏0
  • underscore源碼分析基礎(chǔ)方法

    摘要:在上篇文章整體架構(gòu)分析中,我們講過(guò)上面的方法有兩種掛載方式,一個(gè)是掛載到構(gòu)造函數(shù)上以的形式直接調(diào)用在后文上統(tǒng)稱構(gòu)造函數(shù)調(diào)用,另一種則是掛到上以的形式被實(shí)例調(diào)用在后文上統(tǒng)稱原型調(diào)用。 underscore源碼分析之基礎(chǔ)方法 本文是underscore源碼剖析系列的第二篇,主要介紹underscore中一些基礎(chǔ)方法的實(shí)現(xiàn)。 mixin 在上篇文章underscore整體架構(gòu)分析中,我們講...

    BigNerdCoding 評(píng)論0 收藏0
  • Underscore 整體架構(gòu)淺析

    摘要:支持形式的調(diào)用這其實(shí)是非常經(jīng)典的無(wú)構(gòu)造,其實(shí)就是一個(gè)構(gòu)造函數(shù),的結(jié)果就是一個(gè)對(duì)象實(shí)例,該實(shí)例有個(gè)屬性,屬性值是。 前言 終于,樓主的「Underscore 源碼解讀系列」underscore-analysis 即將進(jìn)入尾聲,關(guān)注下 timeline 會(huì)發(fā)現(xiàn)樓主最近加快了解讀速度。十一月,多事之秋,最近好多事情搞的樓主心力憔悴,身心俱疲,也想盡快把這個(gè)系列完結(jié)掉,也好了卻一件心事。 本文...

    ningwang 評(píng)論0 收藏0
  • 學(xué)習(xí) underscore 源碼整體架構(gòu),打造屬于自己的函數(shù)式編程類庫(kù)

    摘要:譯立即執(zhí)行函數(shù)表達(dá)式處理支持瀏覽器環(huán)境微信小程序。學(xué)習(xí)整體架構(gòu),利于打造屬于自己的函數(shù)式編程類庫(kù)。下一篇文章可能是學(xué)習(xí)的源碼整體架構(gòu)。也可以加微信,注明來(lái)源,拉您進(jìn)前端視野交流群。 前言 上一篇文章寫(xiě)了jQuery整體架構(gòu),學(xué)習(xí) jQuery 源碼整體架構(gòu),打造屬于自己的 js 類庫(kù) 雖然看過(guò)挺多underscore.js分析類的文章,但總感覺(jué)少點(diǎn)什么。這也許就是紙上得來(lái)終覺(jué)淺,絕知此...

    junnplus 評(píng)論0 收藏0
  • 打造屬于自己的underscore系列 ( 一 )

    摘要:目前通行的模塊規(guī)范主要集中在和,因此為了讓定義的庫(kù)能夠適用于各種規(guī)范。在框架的定義時(shí)需檢測(cè)使用環(huán)境并兼容各種規(guī)范。服務(wù)端規(guī)范,檢測(cè)是否存在,滿足時(shí)通過(guò)將暴露出來(lái),不滿足則通過(guò)對(duì)象暴露出來(lái)。前者回調(diào)函數(shù)處理的是值和下標(biāo),后者處理的是值和屬性。 本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處 https://www.cnblogs.com/kidfl... underscore作為開(kāi)發(fā)中比較常用的一個(gè)...

    nifhlheimr 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<