将范围变量传递给在该范围之外声明的闭包

时间:2014-06-16 09:31:57

标签: javascript

我真的希望这不是重复的。

function a(){ b(); } // function a calls function b; but there's no function b in the global scope...

(function(){

    // the purpose was to declare it later because it may collide with user-defined functions
    var b = function(){ console.log('I am function b()'); };

    a(); // doesn't work, obviously
    a.call(this); // also doesn't work
    a.apply(this, []); // doesn't work either

    // neither works
    var scope = { 'b': function(){ return b.apply(this,arguments); } }; 
    with(scope){
        a.call(scope);
    }

    // ... what works then? 

}()); 

简单地说,函数a()声明全局调用函数b()。函数b()未在a()之前声明,并且不属于同一范围。

所以:

  1. 我们无法修改函数a(),也无法修改其定义的位置
  2. 我们无法在b()
  3. 的同一范围内声明a()
  4. 我们也不能var a = eval(a().toString())或任何同样的作弊
  5. 使用纯范围处理,这可能吗?如果它不是,我们还能做些什么? 只是想在这里学习一些JavaScript。

2 个答案:

答案 0 :(得分:2)

你不能这样做。范围内的变量不能在该范围之外访问,这是范围界定的全部要点。如果要在匿名函数外部显示b()函数,则需要将其分配给外部变量。

答案 1 :(得分:0)

创建函数对象时,它会包装所有封闭函数并形成闭包。之后,只要在本地范围内找不到正在使用的对象,就会搜索封闭的函数对象。

在您的情况下,a在全局范围内声明,并且没有封闭函数。当您从IIFE调用a时,b将在a本身及其封闭函数内搜索,最后在全局范围内搜索,而该范围在该范围列表中的任何位置都找不到。这就是它失败的原因

ReferenceError: b is not defined

注意:这里需要注意的重要一点是,当你调用一个函数时,将搜索定义函数的作用域,而不是它被调用的位置。

所以,答案是否定的。它不可能做你想做的事。