Замыкания: Эквивалент PHP & quot; использовать & quot; список захвата ключевых слов или C ++ в Javascript или на языке транспилера

в 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-подобном языке, эти дебаты — другая тема.

РЕДАКТИРОВАТЬ: Линтер, который выполняет эту проверку, также поможет

11

Решение

К сожалению, как вы можете представить себе ключевое слово 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);

Вы можете увидеть их все здесь:

https://jsfiddle.net/jo9yzoke/1/

3

Другие решения

В 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 в этом объеме.

Смотрите также:

2

Прежде всего: 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)
1

Вот еще один альтернативный подход. Если ваша цель в поиске эквивалента 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).

1

Я не думаю, что JS когда-либо предложит то, что вы хотите. PHP имеет строгую сферу применения. Если я определяю переменную внутри функции, она ограничивается этой функцией. Аналогично, что-то определенное вне этой функции неявно доступно внутри функции. use, лайк global просто меняет, где и когда вы можете использовать переменную внутри определенной области видимости.

JS по умолчанию помещает все в глобальную область видимости. Фактически, это форма странного мира, в которой вы ограничиваете область действия переменной внутри функции, которую вы либо должны иметь в качестве аргумента, либо явно предел область действия этой переменной

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

Другими словами, все переменные в JS use объявлено неявно.

0

Вы можете связать свои внешние переменные с this ключевое слово вашего закрытия, используя .bind() функция:

Метод bind () создает новую функцию, которая при вызове имеет
этому ключевому слову присваивается заданное значение с заданной последовательностью
аргументы, предшествующие любому, предоставляются при вызове новой функции.

Увидеть
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

0
По вопросам рекламы [email protected]