我怎样才能创建一个函数expr;t继承词法范围

How can I create a function expr that doesn't inherit lexical scope?

本文关键字:expr 函数 一个 范围 词法 继承 创建      更新时间:2023-09-26

以下JavaScript违反CSP(如果CSP有默认设置):

(function() {
  return new Function('return function Thing() {}');
}());

但这个替代方案继承了它的父范围:

(function() {
  var foo = '42';
  return function Thing() {};
}());

我相信这可以防止foo被垃圾收集。

如果您被限制在IIFE中编写代码,有没有一种方法可以将函数定义放在全局范围内(请注意,我不是指在全局范围中访问它,我的意思是它的定义存在于全局范围中)?

我不太确定您在这里想要实现什么,因为您提供的代码没有任何实际用途。变量foo将被创建和分配,函数Thing将被返回,但一旦IIFE被执行,所有引用都将丢失,并将进行垃圾收集。

如果我把这个函数作为一个例子做得更有用一点,下面将生成thing函数,并且变量foo仍然存在,因为它是封闭的——参见闭包。

function generateThing() {
    var foo = '42';
    return function thing() {
        console.log("thing:", foo)
    };
}
var myThing = generateThing();
myThing();

如果您不在内部函数中引用foo,那么该引用将不会得到维护,并且将被垃圾回收。

如果为模块使用对象文字,则可以使用this来限制作用域。在以下示例中,generateThing函数引用模块的foo字段。在执行过程中,该值将在词法范围内可用。但是,如果您创建一个内部函数,上下文this将有所不同。因此,当您调用返回的函数时,它将输出undefined

您可以使用apply函数(以及其他函数)控制this的上下文。通过调用以myModule为上下文的函数,我们可以引用foo变量。

(function() {
    var myModule = {
        foo: 42,
        generateThing: function() {
            console.log("generateThing", this.foo);
            return function() {
                console.log("thing:", this.foo);
            }
        }
    }
    window.myModule = myModule;
}());
var thing = myModule.generateThing(); // log: generateThing 42
thing(); // log: thing undefined
thing.apply(myModule); // output: thing 42