in PHP we have the neat use
keyword for allowing the usage of 'external' variables when using closures, like the following:
$tax = 10;
$totalPrice = function ($quantity, $price) use ($tax){ //mandatory 'use'
return ($price * $quantity) * ($tax + 1.0);
};
If we omit the use ($tax)
part, it will throw an error, which I like a lot.
Similarly in C++ 11, we do the same, specifying the external variables, called capture list, with brackets:
float tax = 10;
auto totalPrice = [tax](int quantity, float price){ //mandatory []
return (price*quantity) * (tax + 1.0);
};
As in php, it will throw an error if the capture list is omitted.
In Javascript, we don't have an equivalent to this use
keyword (or c++ []), we just do:
var tax = 10;
var totalPrice = function (quantity, price){ //no need for 'use' or similar
return (price * quantity) * (tax + 1.0); //tax is usable here :(
};
I don't like much that freedom, I strongly prefer to specify the variables that will be accessible by the closure function or get an error otherwise, for reasons outside the scope of this question.
So, I was wondering, is there a special keyword or operator for this in ES6, or in any language that transpiles to javascript? (CoffeeScript, TypeScript, etc) If so, in which language and what's the syntax?
Ideally I'd like to detect in transpilation time (or before), when a variable hasn't been explicitly 'authorized' to be used in a closure, pretty much like PHP/C++.
Thanks in advance
PS: Please don't ask me why I want this in js-like language, that debate is another topic.
EDIT: A linter that performs this check would also help
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function.
JavaScript allows us to nest scopes, and variables declared in outer scopes are accessible from all inner ones. Variables can be globally-, module-, or block-scoped. A closure is a function enclosed with references to the variables in its outer scope.
Explanation: In JavaScript, closures are created every time a function is created, at function creation time. Technically, all JavaScript functions are closures: they are objects, and they have a scope chain associated with them.
A closure is an example of encapsulation: it encapsulates the body of code together with the lexical scope. The only means of access into the capsule is through the function: the function is like a "method", and the elements of the captured lexical environment are like "slots" in an object.
Unfortunately as you can immagine the keyword use
doesn't exists in javascript but to achieve the result you are looking for there are several ways.
So this was your example in which totalPrice
is a function and tax
is global.
// Your example
var tax = 10;
var totalPrice = function (quantity, price) {
return (price * quantity) * (tax + 1.0);
};
var price = totalPrice(1, 1);
console.log ("Price YE is : " + price);
So I think that probably the solution who simulate more the keyword use
is to generate a function which initialise tax
in a sub scope and return a function:
// Example 1 return function
function generatePriceCalculator(tax) {
return function(quantity, price) {
if ("undefined" === typeof tax) {
throw "tax is undefined";
}
return (price * quantity) * (tax + 1.0);
};
};
var priceCalculator = generatePriceCalculator(20);
var price1 = priceCalculator(1, 1);
console.log ("Price Example 1 is : " + price1);
As you can see generatePriceCalculator
is setting the value for tax
in the function that return.
Another option is to generate an external function to call inside the closure.
// 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);
You can see all of them here:
https://jsfiddle.net/jo9yzoke/1/
There is no such keyword in JavaScript.
In JavaScript variables are available to all child scopes, for example:
(function() {
var outerVariable = true;
(function() {
console.log(typeof outerVariable); // boolean
(function() {
console.log(typeof outerVariable); // boolean
}())
}());
}());
However, you can't access variables which has been defined in a separate, not-parent scope, for example:
(function() {
var someVariable = true;
}());
(function() {
console.log(typeof someVariable); // undefined
}());
This is the reason why you should write JavaScript code in such a way that you always have access only to variables that you need. Consider following example:
(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"
}());
Inside the IIFE which creates the math
object, you can use PI
variable and multiply
function. The IIFE returns two function, which can access PI
and multiply
too, because they are still inside this IIFE. You can call math.circleArea()
and math.circumference()
from outside this IIFE, but you can access PI
or multiply
— they are undefined
in this scope.
See also:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With