在javascript中复制但不克隆函数的最佳方法是什么?

时间:2015-07-05 15:52:50

标签: javascript function

鉴于我已在foo = function F() {}的for中声明了一个函数,我如何复制但不能克隆该函数。 例如,每次使用下面的代码调用函数log()时,参数被添加到数组log.list中,可以通过调用函数log.alert()来显示该列表。

如何声明一个新变量log2,它将复制log函数的功能但仍保持独立?

即将为listlog维护一个独立的log2,并通过致电log2.alert()显示log2.list,并致电log.alert() } log.list将会显示?

var log = log || function F (x) {
    F.list = F.list || [];
    if (x != undefined) F.list.push(x);
    if (!F.fired) {
        F.alert = function () {
            alert (F.list.join("\n"));
        }
        F.reset = function () {
            F.list = [];
        }
    F.fired = true;
    }
}

// Demonstrate the function
log("log #1");
log("log #2");
log("log #3");
log("log #4");
log.alert();

1 个答案:

答案 0 :(得分:2)

这有点棘手。您已经有一半描述了工厂,它们是返回新对象(包括函数)的函数,还有一半描述了创建实例的常规构造函数。

这个问题的关键在于直接调用您的loglog2变量是否真正重要。 JavaScript并没有提供一种元调用非函数对象的方法,它甚至看起来像ES6 Proxies在实现这个功能时跳过了(你只能拦截函数的调用)。调用log的唯一真正方法是,如果 是一个函数。

您可以定义一个工厂函数,该函数返回一个函数,该函数使用直接附加到其上的相应方法,并封装您需要的任何变量。这种模式所涉及的开销是你必须重新定义一个函数和两个方法每隔时间创建一个新的' log'。



function logFactory () {
  var stack = [];
  
  function f () {
    stack.push.apply(stack, arguments);
  }
  
  f.list = stack;
  
  f.alert = function () {
    alert(stack);
  };
  
  f.reset = function () {
    while (stack.length > 0) {
      stack.pop();
    }
  };
  
  return f;
}

var log = logFactory(),
    log2 = logFactory();

log('one', 'three');
log2('two', 'four');

log.alert();
log.reset();
log2.alert();

alert('Lists are different? ' + log.list !== log2.list);




但是,如果您不需要直接调用log对象,则可以使用原型方法创建普通构造函数,并减少开销。



function Log () {
  this.list = [];
}

Log.prototype.add = function () {
  this.list.push.apply(this.list, arguments);
};

Log.prototype.alert = function () {
  alert(this.list);
};

Log.prototype.reset = function () {
  while (this.list.length > 0) {
    this.list.pop();
  }
};

var log = new Log(),
    log2 = new Log();

log.add('one', 'three');
log2.add('two', 'four');

log.alert();
log.reset();
log2.alert();

alert('Lists are different? ' + log.list !== log2.list);




还应该注意的是,在您的示例中,函数F每次调用它时都会重新定义自己的方法以将某些内容推送到list。这是非常不受欢迎的。