闭包:相当于PHP;使用「;关键字或C++;Javascript或transpiler语言中的捕获列表

闭包:相当于PHP;使用「;关键字或C++;Javascript或transpiler语言中的捕获列表,javascript,php,c++11,typescript,closures,Javascript,Php,C++11,Typescript,Closures,在PHP中,我们有一个整洁的use关键字,用于在使用闭包时允许使用“外部”变量,如下所示: $tax = 10; $totalPrice = function ($quantity, $price) use ($tax){ //mandatory 'use' return ($price * $quantity) * ($tax + 1.0); }; 如果我们省略use($tax)部分,它将抛出一个错误,这是我非常喜欢的 同样,在C++ 11中,我们也这样做,用调用括号:< /P>指

在PHP中,我们有一个整洁的
use
关键字,用于在使用闭包时允许使用“外部”变量,如下所示:

$tax = 10;
$totalPrice = function ($quantity, $price) use ($tax){  //mandatory 'use'
    return ($price * $quantity) * ($tax + 1.0);
};
如果我们省略
use($tax)
部分,它将抛出一个错误,这是我非常喜欢的

同样,在C++ 11中,我们也这样做,用调用括号:< /P>指定外部变量,

float tax = 10;
auto totalPrice = [tax](int quantity, float price){   //mandatory []
   return (price*quantity) * (tax + 1.0);
};
与php一样,如果省略捕获列表,它将抛出一个错误

在Javascript,我们没有一个等价于这个代码>使用< /Cord>To关键字(或C++ []),我们只做:

var tax = 10;
var totalPrice = function (quantity, price){  //no need for 'use' or similar
    return (price * quantity) * (tax + 1.0);  //tax is usable here :(
};
我不太喜欢这种自由,我强烈地喜欢指定闭包函数可以访问的变量,或者以其他方式获得错误,原因超出了这个问题的范围

所以,我想知道,在ES6,或任何可以转换为javascript的语言中,是否有专门的关键字或运算符?(咖啡脚本、打字脚本等)如果是,用哪种语言,语法是什么

理想情况下,我希望在编译时(或之前)检测变量未被显式“授权”用于闭包的情况,非常类似于PHP/C++

提前谢谢

PS:请不要问我为什么要用类似js的语言来表达,这是另一个话题


编辑:执行此检查的过梁也会有所帮助

我认为JS永远不会提供您想要的东西。PHP有一个严格的作用域。如果我在一个函数中定义了一个变量,它只限于那个函数。同样,在该函数外部定义的内容在函数内部也不是隐式可用的<代码>使用,就像
全局
一样,只需更改可以在特定范围内使用变量的位置和时间

默认情况下,JS将所有内容都放在全局范围内。事实上,这是bizarro世界的一种形式,因为您将变量的范围限制在函数中,您要么将其作为参数,要么显式地限制该变量的范围

function bob(x) {
    // x is implicitly local
    y = 1; //global
    var z = 2; //local
}

换句话说,JS中的所有变量都是隐式声明的
use

不幸的是,正如您可以在引擎中看到的那样,
use
关键字在javascript中不存在,但要实现您正在寻找的结果,有几种方法

这就是您的示例,
totalPrice
是一个函数,
tax
是全局函数。

因此,我认为模拟关键字
use
的解决方案可能是生成一个函数,在子范围内初始化
tax
,并返回一个函数:

如您所见,
generatePriceCalculator
正在为返回的函数中的
tax
设置值

另一个选项是生成外部函数以在闭包内调用

// Example 2 function return tax
function getTax() {
    return 30;
}
var totalPrice2 = function (quantity, price) {
    var tax = getTax();
    return (price * quantity) * (tax + 1.0);
};
var price2 = totalPrice2(1, 1);
console.log ("Price Example 2 is : " + price2);
您可以在这里看到所有这些:


JavaScript中没有这样的关键字

在JavaScript中,所有子作用域都可以使用变量,例如:

(function() {
  var outerVariable = true;
  (function() {
    console.log(typeof outerVariable); // boolean
    (function() {
      console.log(typeof outerVariable); // boolean
    }())
  }());
}());
(function() {
  var someVariable = true;
}());
(function() {
  console.log(typeof someVariable); // undefined
}());
但是,您不能访问在单独的非父范围中定义的变量,例如:

(function() {
  var outerVariable = true;
  (function() {
    console.log(typeof outerVariable); // boolean
    (function() {
      console.log(typeof outerVariable); // boolean
    }())
  }());
}());
(function() {
  var someVariable = true;
}());
(function() {
  console.log(typeof someVariable); // undefined
}());
这就是为什么您应该以这样一种方式编写JavaScript代码,即您始终只能访问所需的变量。考虑下面的例子:

(function() {
  var math = (function() {
    // inner variable
    var PI = 3.141592653589793;

    // inner function
    function multiply(...args) {
      return args.reduce((a, b)=> a * b);
    }

    // outer functions
    return {
      circleArea: function circleArea(r) {
        return multiply(r, r, PI);
      },
      circumference: function circumference(r) {
        return multiply(2, PI, r);
      }
    };
  }());

  console.log(math.circleArea(5)); // 78.53981633974483
  console.log(math.circumference(10)); // 62.83185307179586

  console.log(typeof PI); // "undefined"
  console.log(typeof multiply); // "undefined"
}());
在创建
math
对象的IIFE中,可以使用
PI
变量和
multiply
函数。IIFE返回两个函数,它们也可以访问
PI
multiply
,因为它们仍然在这个IIFE中。您可以在此生活之外调用
math.circleArea()
math.percentral()
,但您可以访问
PI
multiply
-它们在此范围内未定义

另见:


您可以使用
.bind()
函数将外部变量绑定到闭包的
this
关键字:

bind()方法创建一个新函数,该函数在调用时具有 此关键字设置为提供的值,并具有给定的 调用新函数时,将在任何函数前面提供参数


首先,JS不是PHP,也不是C++,也不是以前的。
use()
不适用于JS。你有很多可能的例子来做你需要的事情,这是一种非常灵活的语言。除了前面的答案之外,我想再分享一个例子:

var tax = 'improper';

var priceFactory = function(tax) { 
    // private `tax` variable for this scope
    var tax = tax;

    // or a nightmare to check it
    // var tax = 'number' ==  typeof tax && tax || function() { throw "No tax given"; }();

    return function(quantity, price) {
        return (price * quantity) * (1 + tax / 100);
    }
};

var price = new priceFactory(10); // 10%

var totalPrice = price(1, 100)

这里还有另一种方法。如果您在javascript中寻找与
use
等效的代码是为了编写更干净的代码,那么您可能需要查看
window.variablename
。javascript中全局范围内的变量是窗口对象的隐式属性。例如,你可以写:

var window.tax = 10;
var totalPrice = function (quantity, price){  //no need for 'use' or similar
    return (price * quantity) * (window.tax + 1.0);  //tax is usable here :(
};

这让阅读代码的人清楚地知道,函数中引用的
tax
是属于全局范围的
tax
(即
window.tax
)。

我认为没有一个transpiler可以做到这一点。它必须管理这些函数的范围,这很可能会破坏您的代码。这将是一个非常挑剔的行业。我想你最好的办法是用一根针来警告你当前的关闭情况。@4一根针或类似的东西就好了,你知道有一个能检查这个特殊情况的吗?很遗憾,我不知道。但这绝对是可行的。。。这并不是很多人会喜欢的功能,因为我们一直都在使用它们,而且每次我们使用它们的时候都会有人对着我们尖叫。作为一个超级严格的标志(在我看来,还有比这个更荒谬的规则)是件好事。JSLint已经涵盖了这一点(
X在定义之前就已经被使用了
),除非闭包已经可以从函数定义周围访问(比如包装私有),那样的话,你就不会为此烦恼了。谢谢你,丹达维斯@丹达维斯,不幸的是,我的问题是定义变量,