【问题标题】:Prevent JavaScript closure from inheriting scope防止 JavaScript 闭包继承作用域
【发布时间】:2017-12-28 20:12:59
【问题描述】:

我正在寻找一种奇特的方法来防止闭包继承周围的 scrope。例如:

let foo = function(t){

  let x = 'y';

  t.bar = function(){

    console.log(x); // => 'y'

  });

};

只有两种方法我知道防止共享范围:

(1) 使用阴影变量:

let foo = function(t){

  let x = 'y';

  t.bar = function(x){

    console.log(x); // => '?'

  });

};

(2) 把函数体放到别的地方:

  let foo = function(t){

      let x = 'y';

      t.bar = createBar();

    };

我的问题是——有谁知道防止闭包在 JS 中继承作用域的第三种方法?花哨的东西很好。

我认为唯一可行的是 Node.js 中的 vm.runInThisContext()

让我们想象一下,假设 JS 有一个 private 关键字,这意味着该变量仅对该函数的范围是私有的,如下所示:

  let foo = function(t){

      private let x = 'y';  // "private" means inaccessible to enclosed functions

      t.bar = function(){

        console.log(x); // => undefined

      });

    };

并且 IIFE 不起作用:

let foo = function(t){

    (function() {
    let x = 'y';
    }());

   console.log(x); // undefined (or error will be thrown)
   // I want x defined here

  t.bar = function(){
    // but I do not want x defined here
    console.log(x); 
  }

  return t;
};

【问题讨论】:

  • “私有”变量或在较低范围内无法访问的变量等通常没有太多用处,这就是为什么实际上没有任何方法可以创建此类变量的原因。如果您希望某些内容无法访问,请将其包含在它自己的范围内,例如 IIFE 等。
  • 也许你想要一个 IIFE?
  • 您可以将我的 1000 美元转入我在开曼群岛的账户 -> jsfiddle.net/01fyqp0v
  • 知道了,块范围似乎是这样!
  • @AlexanderMills 我不知道...我认为 OP 有点像 IIFE。

标签: javascript node.js closures lexical-closures


【解决方案1】:

你可以使用块作用域

let foo = function(t) {
  {
    // `x` is only defined as `"y"` here
    let x = "y";
  } 
  {
    t.bar = function(x) {
      console.log(x); // `undefined` or `x` passed as parameter
    };
  }
};


const o = {};
foo(o);

o.bar();

【讨论】:

  • 我会被诅咒的
  • 如果您正在编写一个库,那么如果您需要它来使其工作,那么您可能做错了。然而,这是一个很好的答案,块作用域适用于 letconst,它们当然是块作用域。
  • Block statements 本身在几乎所有浏览器中都受支持,并且从一开始就是 JS 的一部分,无论有无标签等。但是块范围的变量,又名 letconst仅在 newer browsers 中可用,这不适用于常规的 var,它是函数范围的。
  • 应该注意的是,如果您希望它在旧浏览器中工作,使用var,我们将返回创建新范围的额外功能,很可能再次是 IIFE,看起来与块语句非常相似,但字符更多 -> jsfiddle.net/adeneo/ydpfaq5w/1
  • 不,他们不会在内部使用 IIFE,然后他们会创建“函数范围”,但他们不会。同样,块从一开始就是 JS 的一部分,并且不是函数,但在块作用域变量可用之前,它们并不是很有用。
【解决方案2】:

这种技术有效:

Create helper function to run a function in an isolated scope

 const foo = 3;

 it.cb(isolated(h => {
    console.log(foo);  // this will throw "ReferenceError: foo is not defined"
    h.ctn();
 }));

JavaScript with 操作符也可能让您很幸运

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-13
    • 1970-01-01
    • 1970-01-01
    • 2019-09-16
    • 2018-09-09
    • 2010-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多