编码JS Underscore _.extend从头开始

时间:2015-10-06 15:49:46

标签: javascript arguments underscore.js

扩展已被证明具有挑战性,因为我试图操纵参数对象。

我的当前扩展函数在初始给定对象

之后不考虑多个参数
1. schedule job
2. start method invoke

首先,我尝试复制arguments对象,将其转换为数组,然后将第一个参数移出()。这非常不优雅,但仍被证明是无效的

我意识到应该以某种方式在此上下文中使用apply()或call()。当我尝试它时,它也没有用。

  _.extend = function(object, sources) {
    return _.reduce(sources, function(memo, current) {
      memo[Object.keys(sources)] = current || 0;
      return memo;
    }, object)
  }

关于我可以采取哪些措施来解决这个问题?

1 个答案:

答案 0 :(得分:1)

您的功能无需使用apply,只需正常调用即可。通过这样做,您将移动的数组作为参数列表传递到函数中。由于您只在参数列表中使用copy,因此只有一个参数可以使用它。也不需要call,因为您可以轻松调用该函数,因为不需要this上下文。最后,由于您的函数不是函数声明,因此在评估持有函数的表达式之后(在var doIt之后可用),它将不可用。

现在,您的doIt函数出错了:

memo[Object.keys(copy)] = current || 0;

Object.keys(copy)返回一个包含副本keys的数组。所以你在做:

memo[array] = current || 0;

array将被转换为字符串,但它绝对不是您想要的。您需要的是迭代copy数组的每个元素属性(每个元素都在current上)并将这些属性复制到您的第一个对象(memo累加器)中。像这样:

var extend = function (object) {
    var copy = [].slice.call(arguments);
    copy.shift();
    var doIt = function (copy) {
        return copy.reduce(function (memo, current) {
            Object.keys(current).forEach(function (key) {
                memo[key] = current[key];
            });
            return memo;
        }, object)
    }
    return doIt(copy);
}

然而,扩展仍然需要处理适当的getter和setter。所以你需要做类似的事情:

var extend = function (object) {
    var copy = [].slice.call(arguments);
    copy.shift();
    var doIt = function (copy) {
        return copy.reduce(function (memo, current) {
            Object.keys(current).forEach(function (key) {
                var pDesc = Object.getOwnPropertyDescriptor(current, key);
                Object.defineProperty(memo, key, pDesc);
            });
            return memo;
        }, object)
    }
    return doIt(copy);
}