借用underscore的bind方法的源码实现
示例:
var func = function (greeting) {
return greeting ":" this.name;
}
func = _.bind(func, {name:joe}, Hi);
func(); // Hi : joe
源码:
通用准备:
var optimizeCb= function(func, context, argCount){
if (context === void 0) return func;
switch (argCount === null ? 3: argCount){
case 1: return function (value){
return func.call(context,value);
};
case 2: return function(value, other){
return func.call(context, value, other);
};
case 3: return function(value, index, collection){
return func.call(context, value, index, collection);
};
case 4: return function(accumulator, value, index, collection){
return func.call(context, accumulator, value, index, collection);
};
}
return function(){
return func.call(context, arguments)
}
}
var cb = function(value, context, argCount) {
if (value == null) return _.identity;
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
if (_.isObject(value)) return _.matcher(value);
return _.property(value);
};
var slice = array.prototype.slice;
nativebind = Function.prototype.bind;
_.isFunction = fucntion(obj) {
return typeof obj === 'function' || false;
}
_.isObject = function(obj){
return typeof obj === object || function;
}
_.baseCreate = function(prototype){
var func = function(){};
func.prototype = prototype;
return new func;
}
var executeBound = function(sourceFunc,boundFunc,context,callingContext,args){
if (! callingContext instanceOf boundFunc) return sourceFunc.apply(context,args);
var Func1 = _.baseCreate(sourceFunc.prototype);
var result = sourceFunc.apply(Func1,args);
if (_.isObject(result)) return result;
return Func1;
}
_bind = function(func, context){
if (nativebind && func.bind === nativebind ){
return nativebind.apply(func, slice.call(arguments,1))
}
if (!_.isFunction(func)){
throw new TypeError("func must be a function");
}
var args = slice.call(arguments, 2);
var bound = function(){
return executeBound(func,bound,context,this,args.concat(slice.call(arguments));
}
return bound;
}
object.keys源码
object.keys = _.keys= function(obj){
_.has = function(obj, key){
return obj !==null && object.prototype.hasOwnProperty.call (obj, key);
}
if (!typeof obj === object) return [];
if (object.keys) return object.keys(obj);
var keys = [];
for (var key in obj){
if (_.has(obj, key)){
keys.push(key);
}
}
return keys;
}
Array.isArray源码
var nativeIsArray = Array.isArray,
toString = Object.prototype.toString;
_.isArray = nativeIsArray || function (arr){
return toString.call(arr) === '[object Array]';
}
indexOf源码
_.sortedIndex = function(array, obj, iteratee, context){
iteratee = cb(iteratee, context);
var value = iteratee(obj);
var low = 0, high=array.length;
while(low < high){
mid = Math.floor((low + high)/2);
iteratee(array[mid]) < value ? low = mid+1 : high = mid;
}
return low;
};
_.findIndex = function(array, iteratee, context){
predicate = cb(predicate, context);
for (var i=0, length= array && array.length; i<length; i++ ){
if (predicate(array[i], i, array)){
return i;
}
return -1;
}
}
_.indexOf = function(arr, item, isSorted){
var i = 0; length = arr && arr.length;
if (typeof isSorted == 'number'){
i= isSorted>0?isSorted: Math.max(0,arr.length+isSorted);
}else if (isSorted && length>0){
i= _.sortedIndex(arr, item);
return arr[i] === item ? i : -1;
}
if (item !== item){
return _.findIndex(slice.call(arr, i), _.isNaN)
}
for (;i<length;i++){
if (arr[i]===item) return i;
}
return -1;
};
Array.prototype.every(t,c);
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
var isArrayLike = function(collection){
var length = collection && collection.length;
typeof length === 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
}
_.every = function(obj, iteratee, context){
var predicate= cb(iteratee, 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 (!iteratee(obj[currentKey], currentKey, obj)) return false;
}
return true;
}
Array.prototype.some(t,c);
_.some = function(obj, iteratee, context){
predicate = cb(iteratee, context);
keys = !isArrayLike(obj) && _.keys(obj);
length= (keys || obj).length;
for (var index= 0; index< length; index++){
currentKey= keys ? keys[index] : index;
if (iteratee(obj[currentKey])) return true;
}
return false;
}
Array.prototype.forEach(t,c);
_.each= _.forEach= function(obj, iteratee, context){
iteratee = optimizeCb(iteratee, context);
//iteratee是函数。
var keys= !isArrayLike(obj) && _.keys(obj);
var length= (keys || obj).length;
for (var i= 0; i< length; i++){
var currentKey= keys ? keys[i] : i;
iteratee(obj[currentKey], currentKey, obj);
}
return obj;
};
Array.prototype.map(f,c)
_.map= function(obj, iteratee, context){
iteratee = cb(iteratee, context);
//iteratee可以是null,函数,对象。
var keys= !isArrayLike(obj) && _.keys(obj);
var length= (keys || obj).length;
var array= Array(length);
for (var i= 0; i< length; i++){
var currentKey= keys ? keys[i] : i;
array[i]= iteratee(obj[currentKey], currentKey, obj);
}
return array;
};
Array.prototype.filter(f,c)
_.filter= _.select= function(obj, iteratee, context){
var predicate= cb(iteratee, context);
var results= [];
_.each(obj,function(value, index, list){
if (predicate(value, index, list)) results.push(value);
});
return results;
};
Array.prototype.reduce(f,c)
function createReduce(dir){
function iterator(obj, iteratee, memo, keys, index, length){
for (; index >= 0 && index < length; index += dir){
var currentKey= keys ? keys[index]: index;
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);
if(arguments.length< 3){
index0= keys ? keys[index] : index;
memo= obj[index0];
index += dir;
}
return iterator (obj, iteratee, memo, keys, index, length);
}
}
_.reduce = _.foldl = _.inject = createReduce(1);
_.reduceRight = _.foldr = createReduce(-1);
_.shuffle(把list随机排序)
_.random= function(min, max){
if(max === null){
max= min;
min= 0;
}
return min + Math.floor(Math.random*(max- min + 1));
}
_.values= function(obj){
var keys= _.keys(obj);
length= keys.length;
values= Array(length);
for(var i= 0; i< length; i++){
values[i]= obj[keys[i]]
}
return values;
}
_.shuffle = function(obj){
var set= isArrayLike(obj) ? obj : _.values(obj);
length= set.length;
shuffles= Array(length);
for(var i= 0, rand; i< length; i++){
rand= _.random(0, i);
if (rand !== i){
shuffles[index]=shuffles[rand];
}
shuffles[rand]=set[index];
}
return shuffles;
}
_.sample(从list中随机去除样本)
_.sample= function(obj, n, guard){
if(n=== null || guard){
if (!isArrayLike(obj)) obj= _.values(obj);
return obj[_.random(obj.length-1)];
}
return _.shuffle (obj).slice(0, Math.max(0, n));
}
_.sortBy(according the callBack function to sort the list)
example:
var stooges = [{name: ‘moe’, age: 40}, {name: ‘larry’, age: 50}, {name: ‘curly’, age: 60}]; _.sortBy(stooges, ‘name’); => [{name: ‘curly’, age: 60}, {name: ‘larry’, age: 50}, {name: ‘moe’, age: 40}];
origin code:
_.property= function(key){
return function(obj){
return obj === null ? void 0: obj[key];
};
};
_.pluck= function(obj, key){
return _.map(obj, _.property(key));
}
_.sortBy= function(obj, iteratee, context){
var iteratee= cb(iteratee, context);
return _.pluck(_.map(obj,function(value, index, list){
return {
value: value;
index: index;
result: iteratee(value, index, obj);
}
})
.sort(function(left, right){
var a= left.result;
b= right.result;
if (a!== b){
if (a> b || a === void 0) return 1;
if (a< b || b === void 0) return -1;
}
return left.index - right.index;
}), 'value')
}
_.groupBy, _.indexBy, _.countBy
example:
_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
=> {1: [1.3], 2: [2.1, 2.4]}
sourceCode
function group(behavior){
return function(obj, iteratee, context){
iteratee= cb(iteratee, context);
var result= {};
_.each(obj, function(value, index){
var key= iteratee(value, index, obj);
behavior(result, value, key);
})
return result;
}
}
_.groupBy= group(function(result, key, value){
return _.has(result, key)? result[key].push(value): result[key]= [value];
});
_.indexBy= group(function(result, key, value){
return result[key]= value;
})
_.countBy= group(function(){
return _.has(result, key)? result[key]++: result[key]= 1;
});