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

資訊專欄INFORMATION COLUMN

Underscore 整體架構(gòu)淺析

ningwang / 2177人閱讀

摘要:支持形式的調(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é)掉,也好了卻一件心事。

本文預(yù)計(jì)是解讀系列的倒數(shù)第二篇,最后一篇那么顯然就是大總結(jié)了。樓主的 Underscore 系列解讀完整版地址 https://github.com/hanzichi/u...

常規(guī)調(diào)用

之前寫(xiě)的文章,關(guān)注點(diǎn)大多在具體的方法,具體的知識(shí)細(xì)節(jié),也有讀者留言建議樓主講講整體架構(gòu),這是必須會(huì)講的,只是樓主把它安排在了最后,也就是本文,因?yàn)闃侵饔X(jué)得不掌握整體架構(gòu)對(duì)于具體方法的理解也是沒(méi)有大的問(wèn)題的。

Underscore 大多數(shù)時(shí)候的調(diào)用形式為 _.funcName(xx, xx),這也是 文檔中 的調(diào)用方式。

_.each([1, 2, 3], alert);

最簡(jiǎn)單的實(shí)現(xiàn)方式,我們可以把 _ 看做一個(gè)簡(jiǎn)單的對(duì)象:

var _ = {};
_.each = function() {
  // ...
};

在 JavaScript 中,一切皆對(duì)象,實(shí)際上,源碼中的 _ 變量是一個(gè)方法:

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

為什么會(huì)是方法?我們接下去看。

OOP

Underscore 支持 OOP 形式的調(diào)用:

_([1, 2, 3]).each(alert);

這其實(shí)是非常經(jīng)典的「無(wú) new 構(gòu)造」,_ 其實(shí)就是一個(gè) 構(gòu)造函數(shù),_([1, 2, 3]) 的結(jié)果就是一個(gè)對(duì)象實(shí)例,該實(shí)例有個(gè) _wrapped 屬性,屬性值是 [1, 2, 3]。實(shí)例要調(diào)用 each 方法,其本身沒(méi)有這個(gè)方法,那么應(yīng)該來(lái)自原型鏈,也就是說(shuō) _.prototype 上應(yīng)該有這個(gè)方法,那么,方法是如何掛載上去的呢?

方法掛載

現(xiàn)在我們已經(jīng)明確以下兩點(diǎn):

_ 是一個(gè)函數(shù)(支持無(wú) new 調(diào)用的構(gòu)造函數(shù))

_ 的屬性有很多方法,比如 _.each,_.template 等等

我們的目標(biāo)是讓 _ 的構(gòu)造實(shí)例也能調(diào)用這些方法。仔細(xì)想想,其實(shí)也不難,我們可以遍歷 _ 上的屬性,如果屬性值類型是函數(shù),那么就將函數(shù)掛到 _ 的原型鏈上去。

源碼中用來(lái)完成這件事的是 _.mixin 方法:

// Add your own custom functions to the Underscore object.
// 可向 underscore 函數(shù)庫(kù)擴(kuò)展自己的方法
// obj 參數(shù)必須是一個(gè)對(duì)象(JavaScript 中一切皆對(duì)象)
// 且自己的方法定義在 obj 的屬性上
// 如 obj.myFunc = function() {...}
// 形如 {myFunc: function(){}}
// 之后便可使用如下: _.myFunc(..) 或者 OOP _(..).myFunc(..)
_.mixin = function(obj) {
  // 遍歷 obj 的 key,將方法掛載到 Underscore 上
  // 其實(shí)是將方法淺拷貝到 _.prototype 上
  _.each(_.functions(obj), function(name) {
    // 直接把方法掛載到 _[name] 上
    // 調(diào)用類似 _.myFunc([1, 2, 3], ..)
    var func = _[name] = obj[name];

    // 淺拷貝
    // 將 name 方法掛載到 _ 對(duì)象的原型鏈上,使之能 OOP 調(diào)用
    _.prototype[name] = function() {
      // 第一個(gè)參數(shù)
      var args = [this._wrapped];

      // arguments 為 name 方法需要的其他參數(shù)
      push.apply(args, arguments);
      // 執(zhí)行 func 方法
      // 支持鏈?zhǔn)讲僮?      return result(this, func.apply(_, args));
    };
  });
};

// Add all of the Underscore functions to the wrapper object.
// 將前面定義的 underscore 方法添加給包裝過(guò)的對(duì)象
// 即添加到 _.prototype 中
// 使 underscore 支持面向?qū)ο笮问降恼{(diào)用
_.mixin(_);

_.mixin 方法可以向 Underscore 庫(kù)增加自己定義的方法:

_.mixin({
  capitalize: function(string) {
    return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
  }
});
_("fabio").capitalize();
=> "Fabio"

同時(shí),Underscore 也加入了一些 Array 原生的方法:

// Add all mutator Array functions to the wrapper.
// 將 Array 原型鏈上有的方法都添加到 underscore 中
_.each(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function(name) {
  var method = ArrayProto[name];
  _.prototype[name] = function() {
    var obj = this._wrapped;
    method.apply(obj, arguments);

    if ((name === "shift" || name === "splice") && obj.length === 0)
      delete obj[0];

    // 支持鏈?zhǔn)讲僮?    return result(this, obj);
  };
});

// Add all accessor Array functions to the wrapper.
// 添加 concat、join、slice 等數(shù)組原生方法給 Underscore
_.each(["concat", "join", "slice"], function(name) {
  var method = ArrayProto[name];
  _.prototype[name] = function() {
    return result(this, method.apply(this._wrapped, arguments));
  };
});
鏈?zhǔn)秸{(diào)用

Underscore 也支持鏈?zhǔn)秸{(diào)用:

// 非 OOP 鏈?zhǔn)秸{(diào)用
_.chain([1, 2, 3])
  .map(function(a) {return a * 2;})
  .reverse()
  .value(); // [6, 4, 2]

// OOP 鏈?zhǔn)秸{(diào)用
_([1, 2, 3])
  .chain()
  .map(function(a){return a * 2;})
  .first()
  .value(); // 2

乍一看似乎有 OOP 和非 OOP 兩種鏈?zhǔn)秸{(diào)用形式,其實(shí)只是一種,_.chain([1, 2, 3])_([1, 2, 3]).chain() 的結(jié)果是一樣的。如何實(shí)現(xiàn)的?我們深入 chain 方法看下。

_.chain = function(obj) {
  // 無(wú)論是否 OOP 調(diào)用,都會(huì)轉(zhuǎn)為 OOP 形式
  // 并且給新的構(gòu)造對(duì)象添加了一個(gè) _chain 屬性
  var instance = _(obj);

  // 標(biāo)記是否使用鏈?zhǔn)讲僮?  instance._chain = true;

  // 返回 OOP 對(duì)象
  // 可以看到該 instance 對(duì)象除了多了個(gè) _chain 屬性
  // 其他的和直接 _(obj) 的結(jié)果一樣
  return instance;
};

我們看下 _.chain([1, 2, 3]) 的結(jié)果,將參數(shù)代入函數(shù)中,其實(shí)就是對(duì)參數(shù)進(jìn)行無(wú) new 構(gòu)造,然后返回實(shí)例,只是實(shí)例多了個(gè) _chain 屬性,其他的和直接 _([1, 2, 3]) 一模一樣。再來(lái)看 _([1, 2, 3]).chain()_([1, 2, 3]) 返回構(gòu)造實(shí)例,該實(shí)例有 chain 方法,調(diào)用方法,為實(shí)例添加 _chain 屬性,返回該實(shí)例對(duì)象。所以,這兩者效果是一致的,結(jié)果都是轉(zhuǎn)為了 OOP 的形式。

說(shuō)了這么多,似乎還沒(méi)講到正題上,它是如何「鏈」下去的?我們以如下代碼為例:

_([1, 2, 3])
  .chain()
  .map(function(a){return a * 2;})
  .first()
  .value(); // 2

當(dāng)調(diào)用 map 方法的時(shí)候,實(shí)際上可能會(huì)有返回值。我們看下 _.mixin 源碼:

// 執(zhí)行 func 方法
// 支持鏈?zhǔn)讲僮?return result(this, func.apply(_, args));

result 是一個(gè)重要的內(nèi)部幫助函數(shù)(Helper function ):

// Helper function to continue chaining intermediate results.
// 一個(gè)幫助方法(Helper function)
var result = function(instance, obj) {
  // 如果需要鏈?zhǔn)讲僮鳎瑒t對(duì) obj 運(yùn)行 chain 方法,使得可以繼續(xù)后續(xù)的鏈?zhǔn)讲僮?  // 如果不需要,直接返回 obj
  return instance._chain ? _(obj).chain() : obj;
};

如果需要鏈?zhǔn)讲僮鳎▽?shí)例會(huì)有帶有 _chain 屬性),則對(duì)運(yùn)算結(jié)果調(diào)用 chain 函數(shù),使之可以繼續(xù)鏈?zhǔn)秸{(diào)用。

小結(jié)

Underscore 整體架構(gòu),或者說(shuō)是基礎(chǔ)實(shí)現(xiàn)大概就是這個(gè)樣子,代碼部分就講到這了,接下去系列解讀最后一篇,講講這段時(shí)間(幾乎也是歷時(shí)半年了)的一些心得體會(huì)吧,沒(méi)錢的就捧個(gè)人場(chǎng)吧!

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

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

相關(guān)文章

  • 學(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源碼剖析之整體架構(gòu)

    摘要:我這里有個(gè)不夠準(zhǔn)確但容易理解的說(shuō)法,就是檢查一個(gè)對(duì)象是否為另一個(gè)構(gòu)造函數(shù)的實(shí)例,為了更容易理解,下面將全部以是的實(shí)例的方式來(lái)說(shuō)。 underscore源碼分析之整體架構(gòu) 最近打算好好看看underscore源碼,一個(gè)是因?yàn)樽约捍_實(shí)水平不夠,另一個(gè)是underscore源碼比較簡(jiǎn)單,比較易讀。本系列打算對(duì)underscore1.8.3中關(guān)鍵函數(shù)源碼進(jìn)行分析,希望做到最詳細(xì)的源碼分析。今...

    2shou 評(píng)論0 收藏0
  • 淺析開(kāi)源數(shù)據(jù)庫(kù)MySQL架構(gòu)

    摘要:數(shù)據(jù)庫(kù)系統(tǒng)一旦出現(xiàn)問(wèn)題無(wú)法提供服務(wù),有可能導(dǎo)致整個(gè)系統(tǒng)都無(wú)法繼續(xù)工作。所以,一個(gè)成功的數(shù)據(jù)庫(kù)架構(gòu)在高可用設(shè)計(jì)方面也是需要充分考慮的。操作保持順序,可滿足數(shù)據(jù)庫(kù)對(duì)數(shù)據(jù)一致性的苛刻要求。 數(shù)據(jù)庫(kù)是所有應(yīng)用系統(tǒng)的核心,故保證數(shù)據(jù)庫(kù)穩(wěn)定、高效、安全地運(yùn)行是所有企業(yè)日常工作的重中之重。數(shù)據(jù)庫(kù)系統(tǒng)一旦出現(xiàn)問(wèn)題無(wú)法提供服務(wù),有可能導(dǎo)致整個(gè)系統(tǒng)都無(wú)法繼續(xù)工作。所以,一個(gè)成功的數(shù)據(jù)庫(kù)架構(gòu)在高可用設(shè)計(jì)方面...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<