в PHP мы имеем аккуратный use
ключевое слово для разрешения использования «внешних» переменных при использовании замыканий, например:
$tax = 10;
$totalPrice = function ($quantity, $price) use ($tax){ //mandatory 'use'
return ($price * $quantity) * ($tax + 1.0);
};
Если мы опустим use ($tax)
часть, это выдаст ошибку, которая мне очень нравится.
Точно так же в C ++ 11 мы делаем то же самое, определяя внешние переменные, называемые список захвата, с кронштейнами:
float tax = 10;
auto totalPrice = [tax](int quantity, float price){ //mandatory []
return (price*quantity) * (tax + 1.0);
};
Как и в php, он выдаст ошибку, если список захвата опущен.
В Javascript у нас нет эквивалента этому use
ключевое слово (или 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? (CoffeeScript, TypeScript и т. Д.) Если так, на каком языке и каков синтаксис?
В идеале я хотел бы обнаружить во время транспиляции (или раньше), когда переменная не была явно «разрешена» для использования в замыкании, во многом как PHP / C ++.
заранее спасибо
PS: Пожалуйста, не спрашивайте меня, почему я хочу это на js-подобном языке, эти дебаты — другая тема.
РЕДАКТИРОВАТЬ: Линтер, который выполняет эту проверку, также поможет
К сожалению, как вы можете представить себе ключевое слово use
не существует в javascript, но для достижения результата, который вы ищете, есть несколько способов.
Так что это был ваш пример, в котором totalPrice
это функция и tax
является глобальным.
// 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);
Так что я думаю, что, вероятно, решение, которое больше имитирует ключевое слово use
это генерировать функцию, которая инициализирует tax
в подобласти и вернуть функцию:
// 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);
Как вы видете 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
}());
По этой причине вы должны писать код 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"}());
Внутри IIFE, которая создает math
объект, вы можете использовать PI
переменная и multiply
функция. IIFE возвращает две функции, которые могут получить доступ PI
а также multiply
тоже, потому что они все еще внутри этого IIFE. Ты можешь позвонить math.circleArea()
а также math.circumference()
снаружи этого IIFE, но вы можете получить доступ PI
или же multiply
— они есть undefined
в этом объеме.
Смотрите также:
Прежде всего: 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)
Вот еще один альтернативный подход. Если ваша цель в поиске эквивалента use
в JavaScript, чтобы написать более чистый код, вы можете взглянуть на 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
).
Я не думаю, что JS когда-либо предложит то, что вы хотите. PHP имеет строгую сферу применения. Если я определяю переменную внутри функции, она ограничивается этой функцией. Аналогично, что-то определенное вне этой функции неявно доступно внутри функции. use
, лайк global
просто меняет, где и когда вы можете использовать переменную внутри определенной области видимости.
JS по умолчанию помещает все в глобальную область видимости. Фактически, это форма странного мира, в которой вы ограничиваете область действия переменной внутри функции, которую вы либо должны иметь в качестве аргумента, либо явно предел область действия этой переменной
function bob(x) {
// x is implicitly local
y = 1; //global
var z = 2; //local
}
Другими словами, все переменные в JS use
объявлено неявно.
Вы можете связать свои внешние переменные с this
ключевое слово вашего закрытия, используя .bind()
функция:
Метод bind () создает новую функцию, которая при вызове имеет
этому ключевому слову присваивается заданное значение с заданной последовательностью
аргументы, предшествующие любому, предоставляются при вызове новой функции.
Увидеть
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind