Javascript 重建和减少每个

Javascript 重建和减少每个,javascript,Javascript,最近有一次节目相关演出的面试。面试官让我先把每一个都重写一遍,我没有问题,完全理解。以下是我对每种方法的看法: var each = function(arrayItems,callback){ //if arrayItems is not an array if(!Array.isArray(arrayItems)){ //write a for in loop to iterate through the object for(var key in arrayItem

最近有一次节目相关演出的面试。面试官让我先把每一个都重写一遍,我没有问题,完全理解。以下是我对每种方法的看法:

var each = function(arrayItems,callback){
  //if arrayItems is not an array
  if(!Array.isArray(arrayItems)){
    //write a for in loop to iterate through the object
    for(var key in arrayItems){
      //store the value, the key and the whole object as the callback parameters 
      callback(arrayItems[key],key,arrayItems);
    }
  }
  //if arrayItems wasn't an object iterate through the array
  for(var i = 0; i < arrayItems.length; i++){
    //store the value,key and whole array as the callback's parameters
    callback(arrayItems[i],i,arrayItems);  
  }
};

我正在找人详细介绍reduce中的第二行代码。initialValue是一个以initialValue和number为参数的函数。初始值和数字是否需要按特定顺序排列?初始值等于以intialValue和number作为回调函数的函数是如何工作的?另外,如果代码类似于:
[number(s)]。reduce(函数(a,b){return a+b;},intialValue)
我知道这些问题可能看起来有点模糊,面试早已过去,但作为个人挑战,我想更好地了解情况

您可以检查下划线核心函数

if (typeof (/./) !== 'function') {
    _.isFunction = function(obj) {
      return typeof obj === 'function';
    };
  }
_.bind = function(func, context) {
    var args, bound;
    if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
    if (!_.isFunction(func)) throw new TypeError;
    args = slice.call(arguments, 2);
    return bound = function() {
      if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
      ctor.prototype = func.prototype;
      var self = new ctor;
      ctor.prototype = null;
      var result = func.apply(self, args.concat(slice.call(arguments)));
      if (Object(result) === result) return result;
      return self;
    };
  };

_.has = function(obj, key) {
    return hasOwnProperty.call(obj, key);
  };

_.keys = function(obj) {
    if (!_.isObject(obj)) return [];
    if (nativeKeys) return nativeKeys(obj);
    var keys = [];
    for (var key in obj) if (_.has(obj, key)) keys.push(key);
    return keys;
  };

_.each = function(obj, iterator, context) {
    if (obj == null) return obj;
    if (nativeForEach && obj.forEach === nativeForEach) {
      obj.forEach(iterator, context);
    } else if (obj.length === +obj.length) {
      for (var i = 0, length = obj.length; i < length; i++) {
        if (iterator.call(context, obj[i], i, obj) === breaker) return;
      }
    } else {
      var keys = _.keys(obj);
      for (var i = 0, length = keys.length; i < length; i++) {
        if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
      }
    }
    return obj;
  };


 _.reduce = function(obj, iterator, memo, context) {
    var initial = arguments.length > 2;
    if (obj == null) obj = [];
    if (nativeReduce && obj.reduce === nativeReduce) {
      if (context) iterator = _.bind(iterator, context);
      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
    }
    each(obj, function(value, index, list) {
      if (!initial) {
        memo = value;
        initial = true;
      } else {
        memo = iterator.call(context, memo, value, index, list);
      }
    });
    if (!initial) throw new TypeError(reduceError);
    return memo;
  };
if(typeof(/。/)!=='function'){
_.isFunction=功能(obj){
返回obj的类型==='函数';
};
}
_.bind=函数(函数,上下文){
var-args,绑定;
if(nativeBind&&func.bind==nativeBind)返回nativeBind.apply(func,slice.call(参数,1));
如果(!.isFunction(func))抛出新类型错误;
args=slice.call(参数,2);
返回边界=函数(){
if(!(this instanceof bound))返回函数apply(上下文,args.concat(切片调用(参数));
ctor.prototype=func.prototype;
var-self=新系数;
ctor.prototype=null;
var result=func.apply(self,args.concat(slice.call(arguments));
if(Object(result)==result)返回结果;
回归自我;
};
};
_.has=功能(obj,键){
返回hasOwnProperty.call(obj,key);
};
_.键=功能(obj){
如果(!_.isObject(obj))返回[];
如果(nativeKeys)返回nativeKeys(obj);
var键=[];
如果(u.has(obj,key))键按下(key),则为(obj中的var键);
返回键;
};
_.each=函数(对象、迭代器、上下文){
如果(obj==null)返回obj;
if(nativeForEach&&obj.forEach===nativeForEach){
forEach(迭代器,上下文);
}否则如果(对象长度===+对象长度){
对于(变量i=0,长度=obj.length;i2;
如果(obj==null)obj=[];
if(nativeReduce&&obj.reduce==nativeReduce){
if(context)iterator=u2;.bind(iterator,context);
返回初始值obj.reduce(迭代器,memo):obj.reduce(迭代器);
}
每个(对象、功能(值、索引、列表){
如果(!首字母){
备忘录=价值;
初始=真;
}否则{
memo=iterator.call(上下文、备忘录、值、索引、列表);
}
});
如果(!initial)抛出新类型错误(reduceError);
返回备忘录;
};
“这是如何工作的
initialValue
是一个以
initialValue
number
为参数的函数。”

我想你的意思是
callback
是一个函数。如果是这样,是的,它将被传递参数,但不仅仅是两个

第一个是您拥有的
初始值
,尽管这增加了混淆,因为在您第一次更新它之后,它不再是初始值。最好使用不同的变量名

第二个是迭代中的当前项。您有一个名称
编号
,但它可能不是编号。又是一个令人困惑的名字

第三个应该是当前迭代的索引

第四个应该是原始收藏


“是否需要将
初始值
编号
按特定顺序排列?”

当然。这是最终值和当前迭代值的“累加器”。用户需要知道哪个是哪个


“初始值等于以
intialValue
number
作为回调的函数,这是如何工作的?”

每次迭代,回调都应该返回累加器的更新值。该值作为下一次迭代的第一个参数传递


“如果代码类似于:
[number(s)]。reduce(函数(a,b){return a+b;},intialValue)
,它如何知道如何执行代码?”

这是一个奇怪的例子,但是如果您有一个正确的数组,并且您传递了类似
0
的内容,那么
a
就是累加器,它将等于您传递的
初始值
,或者上一次迭代的返回值


使用
.reduce()
的一个更合理的例子是:

var result = [2,4,3,8,6].reduce(function(acc, curr, i, arr) {
    console.log(acc, curr);
    return acc + curr;
}, 0);
因此,在第一次迭代中,
acc
(累加器的缩写)将是
0
(给定的初始值),
curr
(当前值的缩写)将是数字
2
,它是数组中的第一项

然后返回值为
0+2

在第二次迭代中,
acc
是最后一次返回的值,它是
0+2
2
,而
curr
是数组中的第二项,即
4

然后返回值为
2+4

在第三次迭代中,
acc
是最后一次返回的值,它是
2+4
6
,而
curr
是数组中的第三项,即
3

然后返回值为
6+3

……等等

如您所见,它只是获取初始值或上一次迭代的返回值,将其作为第一个参数传递,让您执行任何您想要的操作,然后获取
var result = [2,4,3,8,6].reduce(function(acc, curr, i, arr) {
    console.log(acc, curr);
    return acc + curr;
}, 0);
function firstToCapital(inputString) {
    return inputString.charAt(0).toUpperCase() + inputString.slice(1).toLowerCase();
}

function isClass(inputArg, className) {
    return Object.prototype.toString.call(inputArg) === '[object ' + firstToCapital(className) + ']';
}

function throwIfNotAFunction(inputArg) {
    if (!isClass(inputArg, 'function')) {
        throw TypeError('Argument is not a function');
    }

    return inputArg;
}
function checkObjectCoercible(inputArg) {
    if (typeof inputArg === 'undefined' || inputArg === null) {
        throw new TypeError('Cannot convert argument to object');
    }

    return inputArg;
};

function ToObject(inputArg) {
    checkObjectCoercible(inputArg);
    if (isClass(inputArg, 'boolean')) {
        inputArg = new Boolean(inputArg);
    } else if (isClass(inputArg, 'number')) {
        inputArg = new Number(inputArg);
    } else if (isClass(inputArg, 'string')) {
        inputArg = new String(inputArg);
    }

    return inputArg;
}

function ToUint32(inputArg) {
    return inputArg >>> 0;
}
function forEach(array, fn, thisArg) {
    var object = ToObject(array),
        length,
        index;

    throwIfNotAFunction(fn);
    length = ToUint32(object.length);
    for (index = 0; index < length; index += 1) {
        if (index in object) {
            fn.call(thisArg, object[index], index, object);
        }
    }
}
function reduce(array, fn, initialValue) {
    var object = ToObject(array),
        accumulator,
        length,
        kPresent,
        index;

    throwIfNotAFunction(fn);
    length = ToUint32(object.length);
    if (!length && arguments.length === 2) {
        throw new TypeError('reduce of empty array with no initial value');
    }

    index = 0;
    if (arguments.length > 2) {
        accumulator = initialValue;
    } else {
        kPresent = false;
        while (!kPresent && index < length) {
            kPresent = index in object;
            if (kPresent) {
                accumulator = object[index];
                index += 1;
            }
        }

        if (!kPresent) {
            throw new TypeError('reduce of empty array with no initial value');
        }
    }

    while (index < length) {
        if (index in object) {
            accumulator = fn.call(undefined, accumulator, object[index], index, object);
        }

        index += 1;
    }

    return accumulator;
}