理解功能自引用机制

时间:2014-04-19 11:09:21

标签: javascript function

我有(大约)这种情况:我试图声明func1()函数,并通过_init()函数运行它,一次性添加几个静态方法,提供带附加属性的哈希它没有意识到在_init()函数完成工作后它仍未在当前范围内声明。它只是暂时定义,并在_init()运行后gc-ed(据我所知)。这是代码示例:

//
// #_init
// merge src{} into target{}, overwriting
// 
var _init = (function (target, src) {

  var _ = this;

  if (_.isobj(target))
    _.keys(src).forEach(_.pass, {
      src    : src, 
      target : target
    });

  return target;

}).bind({

  isobj : (function (node) {
    return node === this(node);
  }).bind(Object), 

  keys  : (function (node) {
    return this.keys(this(node));
  }).bind(Object), 

  pass  : function (field) {
    this.target[field] = this.src[field];
  }

});

,我本来希望批量生成'它在这里同时添加静态方法:

_init(function func1 (e) {
  var _api = func1.pop(arguments);
  var node = this;
  // and stuff...
}, {
  pop: Function.prototype.call.bind(Array.prototype.pop), 
  // ...etc
});

稍后尝试引用它时出现错误:

x = func1();
// ReferenceError: func1 is not defined
// x = func1()

_init()的输出分配给var func2可以完成这项工作,我可以参考并使用该功能。让我感到困惑的是console.log() - func2日志' func1()',但尝试引用func1直接抛出ReferenceError:

//
// #func2
//
var func2 = _init(function func1 () {
  return func1.pop(arguments);
}, {
  pop: Function.prototype.call.bind(Array.prototype.pop)
});

console.log(typeof func2, func2, func2(1,2,3));
// function func1() 3

console.log(func1(1,2,3));
// ReferenceError: func1 is not defined
// console.log(func1(1,2,3));
//

有人可以向我解释为什么func1引用没有被创建,但是(奇怪地)可以使用func2(它显然可以使用它...)?< / p>

1 个答案:

答案 0 :(得分:0)

  

有人可以向我解释为什么func1引用没有被创建,但(奇怪的是)可以使用func2(它显然可以使用它...)?

这就是named function expressions的工作方式。它们的名称(func1)在函数体内可用作标识符,但不在外部。表达式的结果(将创建的函数传递给_init,然后将其分配给func2)会发生什么变化,这是一个不同且完全不相关的事情。


  

我试图声明func1()函数并向其添加几个静态方法

除非那些静态方法确实是公开的,而不仅仅是简单的辅助方法,否则你不应该这样做。使用揭示XY模式(IEFE),只需在闭包范围内获取实用程序功能:

var _init = (function() {
  function isobj(node) {
    return node === Object(node);
  }
  function pass(field) {
    this.target[field] = this.src[field];
  }
  var keys = Object.keys;

  return function (target, src) {
    if (isobj(target))
      keys(src).forEach(_.pass, {
        src    : src, 
        target : target
      });
    return target;
  };
});
var func2 = (function() {
  var pop = Function.prototype.call.bind(Array.prototype.pop);

  return function func1 () {
    return pop(arguments);
  };
});