欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Underscore源碼分析

 更新時(shí)間:2015年12月30日 10:07:41   作者:black_star  
Underscore 是一個(gè) JavaScript 工具庫(kù),它提供了一整套函數(shù)式編程的實(shí)用功能,但是沒(méi)有擴(kuò)展任何 JavaScript 內(nèi)置對(duì)象。這篇文章主要介紹了underscore源碼分析相關(guān)知識(shí),感興趣的朋友一起學(xué)習(xí)吧

幾年前就有人說(shuō)javascript是最被低估一種編程語(yǔ)言,自從nodejs出來(lái)后,全端(All Stack/Full Stack)概念日漸興起,現(xiàn)在恐怕沒(méi)人再敢低估它了。javascrip是一種類C的語(yǔ)言,有C語(yǔ)言基礎(chǔ)就能大體理解javascript的代碼,但是作為一種腳本語(yǔ)言,javascript的靈活性是C所遠(yuǎn)遠(yuǎn)不及的,這也會(huì)造成學(xué)習(xí)上的一些困難。

一、集合

 1.首先是幾個(gè)迭代的方法。

_.each = _.forEach = function(obj, iteratee, context) {
iteratee = optimizeCb(iteratee, context);
var i, length;
if (isArrayLike(obj)) {
 for (i = 0, length = obj.length; i < length; i++) {
  iteratee(obj[i], i, obj);
 }
} else {
 var keys = _.keys(obj);
 for (i = 0, length = keys.length; i < length; i++) {
  iteratee(obj[keys[i]], keys[i], obj);
 }
}
// 鏈?zhǔn)秸{(diào)用
return obj;
 }; 

ES為數(shù)組同樣添加了原生的forEach()方法。不同的是這里的each(forEach)方法可以對(duì)所有集合使用,函數(shù)接受三個(gè)參數(shù)(集合、迭代函數(shù)、執(zhí)行環(huán)境)。

optimizeCb函數(shù)根據(jù)迭代函數(shù)參數(shù)個(gè)數(shù)的不同為不同的迭代方法綁定了相應(yīng)的執(zhí)行環(huán)境,forEach迭代函數(shù)同樣接受三個(gè)參數(shù)(值,索引,集合)。

接下來(lái)就是for循環(huán)調(diào)用迭代函數(shù)了。 

_.map中一種更優(yōu)雅的判斷isArrayLike的實(shí)現(xiàn)方式:(只用一個(gè)for循環(huán))

var keys = !isArrayLike(obj) && _.keys(obj),
    length = (keys || obj).length,
    results = Array(length);
  for (var index = 0; index < length; index++) {
   var currentKey = keys ? keys[index] : index;
   results[index] = iteratee(obj[currentKey], currentKey, obj);
  }
  return results;
  // 合理使用&&、||、?:可以大大減少代碼量 

還有兩個(gè)特別的地方:

•將集合分成了類數(shù)組集合和對(duì)象集合。使用了isArrayLike函數(shù):

// js的最大精確整數(shù)
 var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
 var isArrayLike = function(collection) {
var length = collection != null && collection.length;
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
 }; // 如果集合有Length屬性且為數(shù)字并且大于0小于最大的精確整數(shù),則判定是類數(shù)組

 •使用了_.keys函數(shù),Object同樣有原生的keys函數(shù),用于返回一個(gè)集合obj可被枚舉的屬性數(shù)組。實(shí)現(xiàn)比較簡(jiǎn)單,for in加上hasOwnProperty()方法。

--------------------------------------------------------------------------------

_.map,_.reduce方法原理類似.

 _.find函數(shù)和Array.some()類似,不同的是返回的是第一個(gè)使迭代結(jié)果為真的那個(gè)元素,而不是Array.some()那樣返回布爾值。

 _.find = _.detect = function(obj, predicate, context) {
  var key;
  if (isArrayLike(obj)) {
   key = _.findIndex(obj, predicate, context);
  } else {
   key = _.findKey(obj, predicate, context);
  }
  if (key !== void 0 && key !== -1) return obj[key];
 };
function createIndexFinder(dir) {
  return function(array, predicate, context) {
   predicate = cb(predicate, context);
   var length = array != null && array.length;
   // 如果dir為1,index為0,index+=1,index正序循環(huán)
   // 如果dir 為-1,index為length-1,index += -1反序循環(huán)
   // 判斷循環(huán)條件則用了index >= 0 && index < length方法兼顧兩種循環(huán)方式
   var index = dir > 0 ? 0 : length - 1;
   for (; index >= 0 && index < length; index += dir) {
    if (predicate(array[index], index, array)) return index;
   }
   return -1;
  };
 }
 _.findIndex = createIndexFinder(1);
 _.findLastIndex = createIndexFinder(-1); 

值得借鑒的地方是這里的一個(gè)for循環(huán)能夠根據(jù)傳入的參數(shù)不同配置不同的循環(huán)順序。

 1.集合中的其他方法基本都是基于迭代方法來(lái)實(shí)現(xiàn)的。

_.max = function(obj, iteratee, context) {
var result = -Infinity, lastComputed = -Infinity,
  value, computed;
if (iteratee == null && obj != null) {
 obj = isArrayLike(obj) ? obj : _.values(obj);
 for (var i = 0, length = obj.length; i < length; i++) {
  value = obj[i];
  if (value > result) {
   result = value;
  }
 }
} else {
 iteratee = cb(iteratee, context);
 _.each(obj, function(value, index, list) {
  computed = iteratee(value, index, list);
  if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
   result = value;
   lastComputed = computed;
  }
 });
}
return result;
 }; 

  max方法用于尋找集合中的最大值,通過(guò)循環(huán)list中的所有項(xiàng),然后比較當(dāng)前項(xiàng)和結(jié)果項(xiàng),如果當(dāng)前項(xiàng)大于結(jié)果,則將其賦給結(jié)果項(xiàng),最后返回結(jié)果項(xiàng)。

 2.集合轉(zhuǎn)換為數(shù)組

 _.toArray = function(obj) {
    if (!obj) return [];
    // 如果是數(shù)組,采用了Array.prototype.slice.call(this,obj)這種方法
    if (_.isArray(obj)) return slice.call(obj);
    // 類數(shù)組對(duì)象,這里沒(méi)有采用Slice方法,而是利用.map對(duì)集合進(jìn)行迭代,從而返回一個(gè)數(shù)組。 _.identity該方法傳入的值和返回的值相等。(主要用于迭代)
    if (isArrayLike(obj)) return _.map(obj, _.identity);
    // 普通對(duì)象,則返回由屬性值組成的數(shù)組。
    return _.values(obj);
   };

數(shù)據(jù)類型

STL需要對(duì)vector、list等進(jìn)行區(qū)分是因?yàn)椴煌臄?shù)據(jù)結(jié)構(gòu)需要或者可以進(jìn)行不同的實(shí)現(xiàn),但underscore里面Collections和Arrays分開(kāi)是什么道理呢?這也要從javascript的數(shù)據(jù)類型說(shuō)起,看下圖。

相關(guān)文章

最新評(píng)論