V-1.8.2 underscore源码解析(三)

来源:互联网 发布:js use strict 编辑:程序博客网 时间:2024/06/06 03:14

V-1.8.2 underscore源码解析(三)

// each的实现类似于forEach
// 遍历数组或对象的每个元素。第一个参数为数组(类数组)或对象
// 第二个参数为迭代方法,对数组或对象每个元素执行该方法,
// 第三个参数(可省略)来决定iteratee的this指向

    _.each = _.forEach = function(obj, iteratee, context) {        // 如果包含context参数,this指向context,将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);            }            // 如果是对象,获取对象所有的value(obj[keys[i]])的值        } else {            var keys = _.keys(obj);            // 遍历处理values的值            for(i = 0, length = keys.length; i < length; i++) {                //          迭代当前索引的值(value),索引(key),当前数组或对象                iteratee(obj[keys[i]], keys[i], obj);            }        }        // 返回传入的obj参数,以方便链式调用        return obj;    };
var arr1 = {one:'zha',two:'chg',three:'bai'};var arr2 = [1,2,3];var obj =   _.each(arr1,function(value,key,arr1){        console.log('key值为 '+key+'  value值为  '+value +'   list参数为  '+ arr1);    })console.log('obj的值  ' + obj);var obj2 =  _.each(arr2,function(value,key,list){        console.log('key值为 '+key+'  value值为  '+value +'    list参数为  '+ list);    })console.log( 'obj2的值为   '+obj2);

这里写图片描述

//map方法通过转换函数(迭代器函数)映射列表中的每个值产生价值的新数组
//iteratee包含三个参数:value,key(index),最后一个是引用指向整个list

_.map = _.collect = function(obj, iteratee, context) {// 如果有context参数,就将迭代方法绑定到context上下文,确定this指向        iteratee = cb(iteratee, context);// 如果传参是个对象,获取他的keys值数组// 获取类数组或者对象的长度// 创建一个新的确定长度的数组        var keys = !isArrayLike(obj) && _.keys(obj),            length = (keys || obj).length,            results = Array(length);// 判断keys是否可枚举,即是否为对象,是就返回keys[index](value值),currentKey为对象的key值// 若不为对象,为数组,则currentKey为数组的下标        for(var index = 0; index < length; index++) {            var currentKey = keys ? keys[index] : index;// 重组新的数组            results[index] = iteratee(obj[curentKey], currentKey, obj);        }// 返回新的结果数组        return result;    };

// Create a reducing function iterating left or right.
//创建一个向左或向右迭代方向的归纳函数
// memo为reduce 函数的初始值
// 根据dir来确定从左侧或右侧来确定组合方向

function createReduce(dir) {// Optimized iterator function as using arguments.length// in the main function will deoptimize the, see #1991.        function iterator(obj, iteratee, memo, keys, index, length) {            for(; index >= 0 && index < length; index += dir) {                var currentKey = keys ? keys[index] : index;//迭代函数的第一个值是memo(初始值),会被每一次成功调用iteratee函数的返回值所取代 。//第二个值是value,第三个是key或者index,第四个是obj(数组或类数组对象)                memo = iteratee(memo, obj[currentKey], currentKey, obj);            }            return memo;        }        return function(obj, iteratee, memo, context) {            iteratee = optimizeCb(iteratee, context, 4);            var keys = !isArrayLike(obj) && _.keys(obj),                length = (keys || obj).length,                index = dir > 0 ? 0 : length - 1;// Determine the initial value if none is provided.//如果没有提供memo的初始值,即参数长度少于3//memo就设置为obj的第一个值(value或者indexif(arguments.length < 3) {                memo = obj[keys ? keys[index] : index];                index += dir;            }            return iterator(obj, iteratee, memo, keys, index, length);        };    }

// 归纳函数 目的:将一个值列表归纳为一个单一的结果 ,也叫做注入/折叠
// _.reduce(list, iteratee, [memo], [context]) Aliases: inject, foldl
// 别名为 inject 和 foldl, reduce方法把list中元素归结为一个单独的数值
// Reduce builds up a single result from a list of values, aka inject,or foldl.
.reduce = .foldl = _.inject = createReduce(1);

// var sum = _.reduce([1,2,3,4],function(memo,num){
// return memo+num;
// },0)
// console.log(sum)
//10

/ The right-associative version of reduce, also known as foldr.
.reduceRight = .foldr = createReduce(-1);

/* 12月25号 */
// Return the first value which passes a truth test. Aliased as detect.
//predicate 为迭代函数真值检测,返回一个布尔值,
// _.find()返回第一个匹配的元素,然后结束,如果没有找到则返回 undefined
// 如果找到匹配的元素,函数将立即返回,不会遍历整个list。
.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];
};
// var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); => 2

// Return all the elements that pass a truth test.// Aliased as `select`.//predicate 为迭代函数真值检测,返回一个布尔值,//_.filter()返回所有满足predicate函数的元素组成的数组_.filter = _.select = function(obj, predicate, context) {    var results = [];    predicate = cb(predicate, context);    //通过each来遍历所有元素    _.each(obj, function(value, index, list) {        if(predicate(value, index, list)) results.push(value);    });    return results;};

// var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); => [2, 4, 6]

// Return all the elements for which a truth test fails.//  返回所有不满足真值检测条件的元素组成的数组,与filter相反_.reject = function(obj, predicate, context) {    return _.filter(obj, _.negate(cb(predicate)), context);};

// var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); => [1, 3, 5]

// Determine whether all of the elements match a truth test.// Aliased as `all`.//如果list中的所有元素都通过predicate的真值检测就返回true_.every = _.all = function(obj, predicate, context) {    predicate = cb(predicate, context);    var keys = !isArrayLike(obj) && _.keys(obj),        length = (keys || obj).length;    for(var index = 0; index < length; index++) {        var currentKey = keys ? keys[index] : index;        if(!predicate(obj[currentKey], currentKey, obj)) return false;    }    return true;};

// .every([true, 1, null, ‘yes’], .identity); => false

// Determine if at least one element in the object matches a truth test.// Aliased as `any`.//some与find有点类似,不过find返回的是第一个匹配的元素,some返回的是布尔值//一旦找到了符合条件的元素, 就直接中断对list的遍历
_.some = _.any = function(obj, predicate, context) {        predicate = cb(predicate, context);        var keys = !isArrayLike(obj) && _.keys(obj),            length = (keys || obj).length;        for(var index = 0; index < length; index++) {            var currentKey = keys ? keys[index] : index;            if(predicate(obj[currentKey], currentKey, obj)) return true;        }        return false;    };
// _.some([null, 0, 'yes', false]);//  true// Determine if the array or object contains a given value (using `===`).// Aliased as `includes` and `include`.
_.contains = _.includes = _.include = function(obj, target, fromIndex) {    // 如果不是数组,则将获取对象的value属性构成的数组        if(!isArrayLike(obj)) obj = _.values(obj);    //      运用短路运算符优化性能        return _.indexOf(obj, target, typeof fromIndex == 'number' && fromIndex) >= 0;    };
// _.contains([1, 2, 3], 3);  => true

// Invoke a method (with arguments) on every item in a collection.
// 调用函数

_.invoke = function(obj, method) {  //        利用Array.prototype.slice.call()将arguments转化为数组        var args = slice.call(arguments, 2);    //判断method是否为函数        var isFunc = _.isFunction(method);    // 使用map函数去遍历obj,将符合条件的重新绑定对象并返回一个新的数组,该数组存储了所有方法的处理结果        return _.map(obj, function(value) {    // 此处method可能是一个回调函数,也可能是一个函数名,如果是函数名,通过value[method]来调用    //_.invoke([5, 1, 7]], 'sort');  [1, 5, 7]            var func = isFunc ? method : value[method];            return func == null ? func : func.apply(value, args);        });    };

// _.invoke([[5, 1, 7], [3, 2, 1]], ‘sort’); => [[1, 5, 7], [1, 2, 3]]

// Convenience version of a common use case of `map`: fetching a property.//   pluck 为map函数的简化模型,可以只map里面的某一个key的value值
_.pluck = function(obj, key) {        return _.map(obj, _.property(key));    };
// var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];

// _.pluck(stooges, ‘name’);
// => [“moe”, “larry”, “curly”]

//遍历list中的每一个值,返回一个数组,这个数组包含properties所列出的属性的所有的 键 - 值对。//如果没有找到则返回 undefined// Convenience version of a common use case of `filter`: selecting only objects// containing specific `key:value` pairs.
_.where = function(obj, attrs) {        return _.filter(obj, _.matcher(attrs));    };
//遍历整个list,返回匹配 properties参数所列出的所有 键 - 值 对的第一个值。//如果没有找到则返回 undefined// Convenience version of a common use case of `find`: getting the first object// containing specific `key:value` pairs.
_.findWhere = function(obj, attrs) {        return _.find(obj, _.matcher(attrs));    };
// Return the maximum element (or element-based computation).
    _.max = function(obj, iteratee, context) {        var result = -Infinity,            lastComputed = -Infinity,            value, computed;// 判断是否为数组,若是,则直接比较,若为对象或类数组对象,则比较value值        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;    };
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 苏泊尔球釜说明书 球釜电饭煲缺点 陶晶内胆和球釜内胆哪个好 铜晶球釜内胆好不好 电压力锅球釜内胆好吗 球釜电饭煲已经被淘汰 球釜电压力锅怎么样 球釜电压力锅价格 苏泊尔球釜 苏泊尔球釜ih电饭煲 球釜智能电饭煲 苏泊尔ih球釜电饭煲 球釜电饭煲怎么用 蒸汽球釜ih电饭煲 球釜内胆好吗 球釜内胆是什么意思 球釜电饭煲哪个牌子好 球釜内胆 苏泊尔球釜电饭煲说明书 球釜是什么意思 电饭煲球釜是什么意思 球釜 ih电饭煲 苏泊尔电饭煲哪款好 苏泊尔电饭煲怎么样 苏泊尔ih电饭煲 苏泊尔电饭煲球釜柴火饭 三峡钢球厂 磨煤机钢球 碳钢球阀 钢球价格 钢球生产厂家 钢球厂 锻钢球阀 钢球供应 碳钢深沟球轴承 钢球有限公司 耐磨钢球采购 铸钢球阀 球磨机用钢球 进口锻钢球阀