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

資訊專欄INFORMATION COLUMN

underscore 誕生記(二)—— 鏈?zhǔn)秸{(diào)用與混入(mixin)

yck / 1165人閱讀

摘要:上篇文章講述了的基本結(jié)構(gòu)搭建,本文繼續(xù)講鏈?zhǔn)秸{(diào)用與混入。獲得一個經(jīng)包裹后的實例標(biāo)識當(dāng)前實例支持鏈?zhǔn)秸{(diào)用小試牛刀返回的為一個實例對象,后面的方法判斷屬性是否為為的話再調(diào)用一次方法再返回原來實例即可。

上篇文章講述了 underscore 的基本結(jié)構(gòu)搭建,本文繼續(xù)講鏈?zhǔn)秸{(diào)用與混入。

如果你還沒看過第一篇文章,請點擊 “underscore 誕生記(一)—— 基本結(jié)構(gòu)搭建”

鏈?zhǔn)秸{(diào)用

在 JQuery 中,我們經(jīng)常使用到鏈?zhǔn)秸{(diào)用,如:

$(".div")
  .css("color", "red")
  .show();

那么在 underscore 中,是否支持鏈?zhǔn)秸{(diào)用呢?答案是支持的,只不過默認(rèn)不開啟鏈?zhǔn)秸{(diào)用罷了。

想要實現(xiàn)鏈?zhǔn)秸{(diào)用,通常我們會在支持鏈?zhǔn)秸{(diào)用的函數(shù)中返回對象本身:

let car = {
  run(name) {
    console.log(`${name}老司機(jī)開車?yán)参?!`);
    return this;
  },
  stop() {
    console.log("車停了");
  },
};

car.run("奔馳").stop();

// 奔馳老司機(jī)開車?yán)参梗?// 車停了

那么在每個 _ 方法下都 return this , 顯然不大優(yōu)雅缺乏可控性!嘗試著寫個通用方法 chain() 開啟鏈?zhǔn)秸{(diào)用。

_.chain = function(obj) {
  // 獲得一個經(jīng)underscore包裹后的實例
  var instance = _(obj);
  // 標(biāo)識當(dāng)前實例支持鏈?zhǔn)秸{(diào)用
  instance._chain = true;
  return instance;
};

// 小試牛刀
_.chain([1, 2, 3]);
/* 
{
    _chain: true,
    _wrapped: [1, 2, 3]
}
 */

返回的為一個實例對象,后面的方法判斷 _chain 屬性是否為 true,為 true 的話再調(diào)用一次 chain() 方法再返回原來實例即可。我們在之前用于給 prototype 復(fù)制方法的 each() 函數(shù)加入判斷吧

var ArrayProto = Array.prototype;
var push = ArrayProto.push;
_.each(_.functions(_), function(name) {
  var func = _[name];
  _.prototype[name] = function() {
    var args = [this._wrapped];
    // args = [this._wrapped, arguments[0], arguments[1]...], 相當(dāng)于用 this._wrapped 代替 obj 實現(xiàn)
    push.apply(args, arguments);
    return this._chain ? _(func.apply(_, args)).chain() : func.apply(_, args);
  };
});

有點冗長,將 return this._chain ? _(func.apply(_, args)).chain() : func.apply(_, args); 改造下,

// 判斷是否需要鏈?zhǔn)秸{(diào)用
var chainResult = function(instance, obj) {
  return instance._chain ? _(obj).chain() : obj;
};
var ArrayProto = Array.prototype;
var push = ArrayProto.push;
_.each(_.functions(_), function(name) {
  var func = _[name];
  _.prototype[name] = function() {
    var args = [this._wrapped];
    // args = [this._wrapped, arguments[0], arguments[1]...], 相當(dāng)于用 this._wrapped 代替 obj 實現(xiàn)
    push.apply(args, arguments);
    return chainResult(this, func.apply(_, args));
  };
});

好了,試試看效果:

_.chain([1, 2, 3])
  .each(function(item) {
    console.log(item);
  })
  .each(function(item) {
    console.log(item);
  });
// 1 2 3 1 2 3
// {_wrapped: [1,2,3], _chain: true}
混入(mixin)

underscore 很強(qiáng)大,功能也很齊全,但有時候也不能滿足所有人的需求。我們想創(chuàng)建一些方法,讓它掛載在 _ 上,這樣我們?nèi)忠部梢哉{(diào)用到這些方法,作為一款強(qiáng)大的方法庫,也應(yīng)該提供這種接口,讓用戶自定添加方法,ok, let us do it !

我們先定義一個 mixin 方法

_.mixin = function(obj) {};

// `obj` 為一個類似 `_` 的對象。傳入的這個對象,也需要遍歷一次,并且復(fù)制方法于 prototype 屬性上。詳細(xì)代碼如下:
_.mixin = function(obj) {
  _.each(_.functions(obj), function(name) {
    var func = (_[name] = obj[name]);
    _.prototype[name] = function() {
      var args = [this._wrapped];
      push.apply(args, arguments);
      // args = [this._wrapped, arguments[0], arguments[1]...], 相當(dāng)于用 this._wrapped 代替 obj 實現(xiàn)
      return chainResult(this, func.apply(_, args));
    };
  });
  return _;
};

看到這里,你會發(fā)現(xiàn),我們在方法的最后遍歷賦值給_.prototype方法,其實就是一次mixin() 的調(diào)用.

_.each(_.functions(_), function(name) {
  var func = _[name];
  _.prototype[name] = function() {
    var args = [this._wrapped];
    // args = [this._wrapped, arguments[0], arguments[1]...], 相當(dāng)于用 this._wrapped 代替 obj 實現(xiàn)
    push.apply(args, arguments);
    return func.apply(_, args);
  };
});

// 簡化為
_.mixin(_);
最終代碼
(function() {
  // root 為掛載對象,為 self 或 global 或 this 或 {}
  var root =
    (typeof self == "object" && self.self === self && self) ||
    (typeof global == "object" && global.global === global && global) ||
    this ||
    {};

  var _ = function(obj) {
    // 如果傳入的是實例后對象,返回它
    if (obj instanceof _) return obj;
    // 如果還沒有實例化,new _(obj)
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
  };

  // 最大數(shù)值
  var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
  var ArrayProto = Array.prototype;
  var push = ArrayProto.push;
  // 判斷是否為數(shù)組
  var isArrayLike = function(collection) {
    var length = collection.length;
    return (
      typeof length == "number" && length >= 0 && length <= MAX_ARRAY_INDEX
    );
  };

  // 判斷是否需要鏈?zhǔn)秸{(diào)用
  var chainResult = function(instance, obj) {
    return instance._chain ? _(obj).chain() : obj;
  };

  root._ = _;

  _.VERSION = "1.9.1"; // 給我們的 underscore 一個版本號吧

  /**
   * 字符串倒裝
   */
  _.reverse = function(string) {
    return string
      .split("")
      .reverse()
      .join("");
  };

  /**
   * 判斷是否為 function
   */
  _.isFunction = function(obj) {
    return typeof obj == "function" || false;
  };
  // 鏈?zhǔn)秸{(diào)用方法
  _.chain = function(obj) {
    // 獲得一個經(jīng)underscore包裹后的實例
    var instance = _(obj);
    // 標(biāo)識當(dāng)前實例支持鏈?zhǔn)秸{(diào)用
    instance._chain = true;
    return instance;
  };
  /**
   * 獲取_的所有屬性函數(shù)名
   */
  _.functions = function(obj) {
    var names = [];
    for (var key in obj) {
      if (_.isFunction(obj[key])) names.push(key);
    }
    return names.sort();
  };
  /**
   * 數(shù)組或?qū)ο蟊闅v方法,并返回修改后的對象或數(shù)組
   * @param iteratee 回調(diào)函數(shù)
   * @param context 回調(diào)函數(shù)中this的指向
   */
  _.map = function(obj, iteratee, context) {
    var length = obj.length,
      results = Array(length);
    for (var index = 0; index < length; index++) {
      results[index] = iteratee.call(context, obj[index], index, obj);
    }

    return results;
  };

  /**
   * 數(shù)組或?qū)ο蟊闅v方法
   */
  _.each = function(obj, callback) {
    var length,
      i = 0;

    if (isArrayLike(obj)) {
      // 數(shù)組
      length = obj.length;
      for (; i < length; i++) {
        //   這里隱式的調(diào)用了一次 callback.call(obj[i], obj[i], 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;
  };
  /*
   * 混入方法 mixin
   */
  _.mixin = function(obj) {
    _.each(_.functions(obj), function(name) {
      var func = (_[name] = obj[name]);
      _.prototype[name] = function() {
        var args = [this._wrapped];
        push.apply(args, arguments);
        // args = [this._wrapped, arguments[0], arguments[1]...], 相當(dāng)于用 this._wrapped 代替 obj 實現(xiàn)
        return chainResult(this, func.apply(_, args));
      };
    });
    return _;
  };
  _.mixin(_);
})();
未完待續(xù),靜待下篇

前端進(jìn)階小書(advanced_front_end)

前端每日一題(daily-question)

webpack4 搭建 Vue 應(yīng)用(createVue)

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

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

相關(guān)文章

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

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

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

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

    nifhlheimr 評論0 收藏0
  • underscore源碼分析之基礎(chǔ)方法

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

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

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

    ningwang 評論0 收藏0
  • underscore 系列之鏈?zhǔn)?/em>調(diào)用

    摘要:我們都知道可以鏈?zhǔn)秸{(diào)用,比如我們寫個簡單的模擬鏈?zhǔn)秸{(diào)用之所以能實現(xiàn)鏈?zhǔn)秸{(diào)用,關(guān)鍵就在于通過,返回調(diào)用對象。系列預(yù)計寫八篇左右,重點介紹中的代碼架構(gòu)鏈?zhǔn)秸{(diào)用內(nèi)部函數(shù)模板引擎等內(nèi)容,旨在幫助大家閱讀源碼,以及寫出自己的。 前言 本文接著上篇《underscore 系列之如何寫自己的 underscore》,閱讀本篇前,希望你已經(jīng)閱讀了上一篇。 jQuery 我們都知道 jQuery 可以鏈...

    zhangrxiang 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<