代码之家  ›  专栏  ›  技术社区  ›  Austin Hyde

Javascript:用另一个函数重新分配一个函数

  •  6
  • Austin Hyde  · 技术社区  · 15 年前

    假设我有两个功能:

    function fnChanger(fn) {
        fn = function() { sys.print('Changed!'); }
    }
    function foo() {
        sys.print('Unchanged');
    }
    

    foo() ,我明白了 Unchanged ,如预期。不过,如果我打电话 fnChanger 不变的 :

    fnChanger(foo);
    foo(); //Unchanged
    

    我想这是因为 foo FN转换器 但我可能错了。

    FN转换器 不变 打印 Changed! ?
    而且,我怎么能 FN转换器 改变

    PS:我使用node.js来测试所有这些东西,所以 sys.print 来自。

    2 回复  |  直到 15 年前
        1
  •  5
  •   Christian C. Salvadó    15 年前

    分配给 fn foo 在外部范围内不受影响。

    当您将对象作为参数传递时,可以说“引用是按值传递的”。任务只是替换了 标识符引用。

    这就是为什么 evaluation strategy 在JavaScript中工作。

    fnChanger 函数,两个标识符,全局 fn公司 参数,指向同一个函数对象:

                    ---------------------------------------------
        foo ----->  |function foo { sys.print('Un changed!'); } |
                    ---------------------------------------------
                       ^
                       |
        fn -------------
    

    fn公司 只需指向新函数:

                    ---------------------------------------------
        foo ----->  | function foo { sys.print('Unchanged!'); } |
                    ---------------------------------------------
    
                    ---------------------------------------
        fn ------>  | function { sys.print('Changed!'); } |
                    ---------------------------------------
    

    好吧,假设

    function fnChanger(obj, name) {
        obj[name] = function() { sys.print('Changed!'); };
    }
    
    function foo() {
        sys.print('Unchanged');
    }
    
    fnChanger(this, 'foo');
    foo(); // Changed!
    

    上面的方法是有效的,因为 FN转换器 基本对象 以及 ,在全局执行上下文中声明的函数被绑定为 ,因此我们可以用这种方式重新分配它的值。

    线路 fnChanger(this, 'foo'); 如果也在全局范围内执行,它将通过 this GlobalObject.foo 标识符。

    如果代码在一个函数中,我们不可能得到 ,因为在此“函数代码执行上下文”中,函数声明(变量声明和函数形式参数也)绑定为 不可访问的对象 ,称为变量对象(这些变量对象的链,形成范围链),如果是这样,唯一的解决方法是使用 eval .

        2
  •  4
  •   subhaze    15 年前

    正如@CMS所指出的,由于作用域的原因,您不能在函数中分配它。但是,您可以这样重新分配:

    var fnChanger = function() {
      return function() {
          alert('changed!');
      }
    }
    
    var foo = function() {
      alert('Unchanged');
    }
    
    foo = fnChanger();
    foo();
    

    example