JavaScript: возможно ли, чтобы замыкания обращались к переменным в охватывающей области по значению, а не по ссылке, как в PHP?

Следующий код JavaScript демонстрирует, как функции JavaScript (замыкание) получают доступ к переменным в окружающей их среде по ссылке, а не по значению.

var sum; // global variable

function outer() {
  var hundred_more = 100;
  sum = function (a, b) {
    return a + b + (++hundred_more);
  };
  sum2 = function (a, b) {
    return a + b + (++hundred_more);
  };
  alert(hundred_more);
}
outer(); // define sum at the global scope and print 100
alert(sum(5, 10)); // 116
alert(sum(5, 10)); // 117
alert(sum2(5, 10)); // 118
alert(sum2(5, 10)); // 119
outer(); // redefine sum at the global scope and print 100
alert(sum(5, 10)); // 116
alert(sum(5, 10)); // 117
alert(sum2(5, 10)); // 118
alert(sum2(5, 10)); // 119

Тот же код на PHP выглядит следующим образом:

<?php

$sum = null; // global variable
$sum2 = null; // global variable

function outer() {
  global $sum;
  global $sum2;
  $hundred_more = 100;
  $sum = function ($a, $b) use (&$hundred_more) {
    return $a + $b + (++$hundred_more);
  };
  $sum2 = function ($a, $b) use (&$hundred_more) {
    return $a + $b + (++$hundred_more);
  };
  var_dump($hundred_more);
}
outer(); // define sum at the global scope and print 100
var_dump($sum(5, 10)); // 116
var_dump($sum(5, 10)); // 117
var_dump($sum2(5, 10)); // 118
var_dump($sum2(5, 10)); // 119
outer(); // redefine sum at the global scope and print 100
var_dump($sum(5, 10)); // 116
var_dump($sum(5, 10)); // 117
var_dump($sum2(5, 10)); // 118
var_dump($sum2(5, 10)); // 119

Чтобы передать переменную из окружающей среды по значению, а не по ссылке в PHP, вы просто опускаете амперсанд (&) перед переменными после ключевого слова use. Это приводит к тому, что значение копируется в область закрытия функции во время определения функции, так что все 'var_dumps' печатают значение 116. Можно ли как-то добиться этой же конструкции в JavaScript (с переменными, переданными во внутреннее замыкание? по значению, а не по ссылке)?

Спасибо.


person John Sonderson    schedule 28.10.2014    source источник
comment
Единственные параметры, которые я вижу, это числовые константы 5 и 10. О какой конкретной части кода вы спрашиваете?   -  person Pointy    schedule 28.10.2014
comment
Я не имею в виду аргументы функции. Я имею в виду переменные из объемлющей области видимости (например, после ключевого слова use в PHP).   -  person John Sonderson    schedule 29.10.2014


Ответы (1)


Ну, вы могли бы создать для него другое закрытие...

function outer() {
    var hundred_more = 100;
    sum = (function(hundred_more){
        return function (a, b) {
          return a + b + (++hundred_more);
        };
    })(hundred_more);
    sum2 = (function(hundred_more){
        return function (a, b) {
          return a + b + (++hundred_more);
        };
    })(hundred_more);
    alert(hundred_more);
}
outer(); // define sum at the global scope and print 100
alert(sum(5, 10)); // 116
alert(sum(5, 10)); // 117
alert(sum2(5, 10)); // 116
alert(sum2(5, 10)); // 117
outer(); // redefine sum at the global scope and print 100
alert(sum(5, 10)); // 116
alert(sum(5, 10)); // 117
alert(sum2(5, 10)); // 116
alert(sum2(5, 10)); // 117

На самом деле это не передача по ссылке; они просто ссылаются на одну и ту же переменную. Создавая новое замыкание, мы передаем старое по ссылке и получаем несвязанные переменные.

person Scimonster    schedule 28.10.2014
comment
Спасибо за ваш ответ. Насколько я понимаю ваш ответ, он использует тот факт, что когда параметр передается функции в JavaScript, он передается по значению (как в следующем фрагменте). - person John Sonderson; 29.10.2014
comment
функция привет(а) { а='привет'; предупреждение (а); } вар а = 'мир'; привет (а); / * отображает приветствие * / alert(a); /* отображает мир */ - person John Sonderson; 29.10.2014
comment
Это отличается от оператора присваивания в JavaScript, который просто создает ссылку на присваиваемую переменную, а не копирует ее. Спасибо. - person John Sonderson; 29.10.2014