使用Function构造函数创建的函数始终在全局范围内创建

时间:2016-06-06 16:26:22

标签: javascript

来自MDN description of Function:

  

注意:使用Function构造函数创建的函数不会创建   封闭他们的创作背景;他们总是在   全球范围。运行它们时,它们只能访问   他们自己的局部变量和全局变量,而不是范围内的变量   其中调用了Function构造函数。这不同于   使用eval和函数表达式的代码。

我理解,

            var y = 10;
            var tester;
            function test(){
                var x = 5;

                tester = new Function("a", "b", "alert(y);");
                tester(5, 10);
            }
            test();           // alerts 10

tester = new Function("a", "b", "alert(y);");替换tester = new Function("a", "b", "alert(x);");,我会得到

// ReferenceError: x is not defined

但无法理解作者的界限 -

  

......它们总是在全球范围内创建。

我的意思是new Function("a", "b", "alert(y);"); fn中的test嵌套在global scope中是什么意思?

事实上,从test fn外部访问它只会导致

  

Uncought TypeError:tester不是函数

请澄清。

4 个答案:

答案 0 :(得分:2)

在您的示例中,"在全局范围内创建"表示x不会test function test(){ var x = 5; tester = new Function("a", "b", "alert(x);"); // this will not show x tester(5, 10); } 上的Function关闭。

function test(){
  var x = 5;
  tester = function (a, b) {
    alert(x); // this will show x
  };
  tester(5, 10);
}

当您新建function addOne(x) { return compile("return " + x + " + 1"); } function addTwo(x) { return compile("return " + x + " + 2"); } function compile(str) { return new Function(str); } 时,它不会自动捕获当前范围,就像声明一个那样。如果您只是简单地声明并返回一个函数,具有闭包:

compile

这是您为动态编译函数所做的权衡。如果你提前编写函数,你可以有闭包,或者你可以拥有一个动态的体,但是会失去对周围范围的封闭。

这个警告通常不重要,但考虑(稍微做作)将函数体构建为字符串,然后将其传递给函数构造函数以进行实际评估的情况:

str

因为该函数是由x实例化的,所以任何闭包都会抓取compile而不是compile。由于str没有关闭任何其他函数,事情变得有点奇怪,new Function返回的函数将始终保持对<router-outlet></router-outlet>的闭包引用(对于垃圾收集可能很糟糕) )。

相反,为了简化所有这些,规范只是制定了<router-outlet>没有任何关闭的一揽子规则。

答案 1 :(得分:0)

您必须创建一个对象,以便在test()函数内通过return公开,以使其成为全局对象。换句话说,添加var pub = {}并将内部函数命名为pub的属性和/或方法(例如pub.tester = new func),然后在关闭test()之前说{{1} }}。因此,它将以公开方式提供(如return pub)。它被称为揭示模块模式。

答案 2 :(得分:0)

这意味着在函数内部,您只能引用全局变量,正如您所发现的那样。但是,对函数本身的引用仍然在创建它的本地范围内。

答案 3 :(得分:0)

我对混淆的地方感到困惑。

它表示该函数将在全局范围内......因此只能访问自己的作用域和全局作用域,而不能访问创建作用域的本地变量。

您测试了它,它可以访问自己的范围和全局范围,而不是创建范围的本地变量。

那么混淆在哪儿?

是否将函数赋值给变量testingtesting只是一个局部变量,带有对函数的引用......与函数的创建范围无关。

范围是词汇,并且与创建函数的位置有关,而不是在运行时将函数引用分配给的随机变量。文档告诉你,当你以这种方式创建一个函数时,它就好像它是在全局范围内创建的......所以它的表现完全符合预期。

以下是一个例子:

这:

var y = 10;
var tester;

function test()
{
    var x = 5;

    // 10 and errors as not defined
    tester = new Function("console.log(y); console.log(x);");
}

与此类似:

var y = 10;
var tester;

function test()
{
    var x = 5;

    // also 10 and errors as not defined
    tester = something;
}

function something()
{
    console.log(y);
    console.log(x);
}

不会

var y = 10;
var tester;

function test()
{
    var x = 5;

    // 10 and 5...since x is local to the function creation
    tester = function()
    {
        console.log(y);
        console.log(x);
    }
}