Подтвердить что ты не робот

Закрытие: эквивалент ключевого слова PHP "use" или списка захвата С++ в Javascript или языке транспилятора

в PHP у нас есть аккуратное ключевое слово use, позволяющее использовать "внешние" переменные при использовании закрытий, например:

$tax = 10;
$totalPrice = function ($quantity, $price) use ($tax){  //mandatory 'use'
    return ($price * $quantity) * ($tax + 1.0);
};

Если мы опустим часть use ($tax), она выдаст ошибку, которую мне очень нравится.

Аналогично в С++ 11 мы делаем то же самое, указывая внешние переменные, называемые список захвата, с скобками:

float tax = 10;
auto totalPrice = [tax](int quantity, float price){   //mandatory []
   return (price*quantity) * (tax + 1.0);
};

Как и в php, он выдаст ошибку, если список захвата опущен.

В Javascript у нас нет эквивалента этого ключевого слова use (или С++ []), мы просто делаем:

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/С++.

Заранее спасибо

PS: Пожалуйста, не спрашивайте меня, почему я хочу это на js-подобном языке, эта дискуссия - это еще одна тема.

EDIT: ЛИНТЕР, который выполняет эту проверку, также поможет

4b9b3361

Ответ 1

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

Ответ 2

В 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 в этой области.

См. также:

Ответ 3

Прежде всего: JS - это не PHP, а С++ и никогда не будет.

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)

Ответ 4

Вот еще один альтернативный подход. Если ваша цель в поиске эквивалента use в javascript заключается в написании более чистого кода, вы можете взглянуть на window.variablename. Переменные в глобальной области видимости в javascript являются неявно свойствами объекта window. Например, вы можете написать:

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).

Ответ 5

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

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

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

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

Ответ 6

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

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

См https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind