Можем ли мы передать ссылку на неизменяемую переменную в качестве аргумента функции?
Пример:
var x = 0;
function a(x)
{
x++;
}
a(x);
alert(x); //Here I want to have 1 instead of 0
javascript
пользователь1342369
источник
источник
Ответы:
Поскольку JavaScript не поддерживает передачу параметров по ссылке, вам нужно вместо этого сделать переменную объектом:
var x = {Value: 0}; function a(obj) { obj.Value++; } a(x); document.write(x.Value); //Here i want to have 1 instead of 0
В данном случае
x
это ссылка на объект. Когдаx
передается в функциюa
, эта ссылка копируется вobj
. Таким образом,obj
иx
обращайтесь к тому же в памяти. ИзменениеValue
свойстваobj
влияет наValue
свойствоx
.Javascript всегда передает параметры функции по значению. Это просто спецификация языка. Вы можете создать
x
в области видимости, локальную для обеих функций, и вообще не передавать переменную.источник
Этот вопрос может помочь: как передать переменную по ссылке в javascript? Чтение данных из функции ActiveX, которая возвращает более одного значения
Подводя итог, примитивные типы Javascript всегда передаются по значению, тогда как значения внутри объектов передаются по ссылке (спасибо комментаторам за указание на мой надзор). Итак, чтобы обойти это, вы должны поместить свое целое число внутри объекта:
var myobj = {x:0}; function a(obj) { obj.x++; } a(myobj); alert(myobj.x); // returns 1
источник
x
значение, независимо от того,x
является ли он объектом или нет, вы не можете заменить его другим значением любым способом, который увидит вызывающий.Я нашел несколько иной способ реализации указателей, который, возможно, является более общим и легким для понимания с точки зрения C (и, таким образом, больше соответствует формату примера пользователей).
В JavaScript, как и в C, переменные массива на самом деле являются просто указателями на массив, поэтому вы можете использовать массив точно так же, как объявление указателя. Таким образом, все указатели в вашем коде могут использоваться одинаково, независимо от того, как вы назвали переменную в исходном объекте.
Это также позволяет использовать две разные записи, относящиеся к адресу указателя и тому, что находится по адресу указателя.
Вот пример (я использую подчеркивание для обозначения указателя):
var _x = [ 10 ]; function foo(_a){ _a[0] += 10; } foo(_x); console.log(_x[0]);
Урожайность
output: 20
источник
Вы ссылаетесь на 'x' из оконного объекта
var x = 0; function a(key, ref) { ref = ref || window; // object reference - default window ref[key]++; } a('x'); // string alert(x);
источник
Поздний ответ, но я нашел способ передачи примитивных значений по ссылке с помощью закрытий. Указатель создать довольно сложно, но он работает.
function ptr(get, set) { return { get: get, set: set }; } function helloWorld(namePtr) { console.log(namePtr.get()); namePtr.set('jack'); console.log(namePtr.get()) } var myName = 'joe'; var myNamePtr = ptr( function () { return myName; }, function (value) { myName = value; } ); helloWorld(myNamePtr); // joe, jack console.log(myName); // jack
В ES6 код можно сократить, чтобы использовать лямбда-выражения:
var myName = 'joe'; var myNamePtr = ptr(=> myName, v => myName = v); helloWorld(myNamePtr); // joe, jack console.log(myName); // jack
источник
В JavaScript это будет глобальный. Однако ваша функция будет выглядеть примерно так:
function a(){ x++; };
Поскольку он
x
находится в глобальном контексте, вам не нужно передавать его в функцию.источник
Javascript должен просто добавлять указатели в смесь, потому что это решает множество проблем. Это означает, что код может ссылаться на неизвестное имя переменной или переменные, которые были созданы динамически. Это также упрощает модульное кодирование и внедрение.
Это то, что я считаю наиболее близким к c-указателям на практике.
в js:
var a = 78; // creates a var with integer value of 78 var pointer = 'a' // note it is a string representation of the var name eval (pointer + ' = 12'); // equivalent to: eval ('a = 12'); but changes value of a to 12
в c:
int a = 78; // creates a var with integer value of 78 int pointer = &a; // makes pointer to refer to the same address mem as a *pointer = 12; // changes the value of a to 12
источник
Это может быть невозможно, поскольку в JavaScript нет оператора Perl «\» для получения примитива по ссылке, но есть способ создать объект «фактически указатель» для примитива с использованием этого шаблона.
Это решение имеет наибольший смысл, когда у вас уже есть примитив (поэтому вы больше не можете поместить его в объект, не изменяя другой код), но все же необходимо передать указатель на него, чтобы другие части вашего кода могли повозиться со своим состоянием; так что вы все еще можете повозиться с его состоянием, используя бесшовный прокси, который ведет себя как указатель.
var proxyContainer = {}; // | attaches a pointer-lookalike getter/setter pair // | to the container object. var connect = function(container) { // | primitive, can't create a reference to it anymore var cant_touch_this = 1337; // | we know where to bind our accessor/mutator // | so we can bind the pair to effectively behave // | like a pointer in most common use cases. Object.defineProperty(container, 'cant_touch_this', { 'get': function() { return cant_touch_this; }, 'set': function(val) { cant_touch_this = val; } }); }; // | not quite direct, but still "touchable" var f = function(x) { x.cant_touch_this += 1; }; connect(proxyContainer); // | looks like we're just getting cant_touch_this // | but we're actually calling the accessor. console.log(proxyContainer.cant_touch_this); // | looks like we're touching cant_touch_this // | but we're actually calling the mutator. proxyContainer.cant_touch_this = 90; // | looks like we touched cant_touch_this // | but we actually called a mutator which touched it for us. console.log(proxyContainer.cant_touch_this); f(proxyContainer); // | we kinda did it! :) console.log(proxyContainer.cant_touch_this);
источник
В JavaScript вы не можете передавать переменные по ссылке в функцию. Однако вы можете передать объект по ссылке.
источник
Я думаю, что в отличие от C или любого языка с указателями:
/** Javascript **/ var o = {x:10,y:20}; var o2 = {z:50,w:200};
.
o == o2 // obviously false : not the same address in memory o <= o2 // true ! o >= o2 // also true !!
это огромная проблема:
это означает, что вы можете перечислять / управлять всеми объектами, созданными (выделенными) вашим приложением,
из этого огромного списка объектов вычислите некоторую информацию о них (например, как они связаны друг с другом)
но когда вы хотите получить информацию, которую вы создали о конкретном объекте, вы не можете найти ее в своем огромном списке по дихотомии: нет уникального идентификатора для каждого объекта, который можно было бы использовать в качестве замены реального адреса памяти
это, наконец, означает, что это огромная проблема, если вы хотите написать на javascript:
источник
JavaScript не поддерживает передачу примитивных типов по ссылке. Однако есть обходной путь.
Поместите все переменные, которые необходимо передать в объект. В этом случае есть только одна переменная,
x
. Вместо передачи переменной передайте имя переменной в виде строки"x"
.var variables = {x:0}; function a(x) { variables[x]++; } a("x"); alert(variables.x);
источник
В зависимости от того, что вы хотите сделать, вы можете просто сохранить имя переменной, а затем получить к нему доступ следующим образом:
function toAccessMyVariable(variableName){ alert(window[variableName]); } var myFavoriteNumber = 6; toAccessMyVariable("myFavoriteNumber");
Чтобы применить к вашему конкретному примеру, вы можете сделать что-то вроде этого:
var x = 0; var pointerToX = "x"; function a(variableName) { window[variableName]++; } a(pointerToX); alert(x); //Here I want to have 1 instead of 0
источник
window
объекта. Кроме того, менее рекомендуется использовать глобальные переменные, поскольку может уже существовать переменная с таким же именем.Он просто не поддерживает указатели, конец истории :-(.
Я хотел бы добавить, что, хотя я новичок и работаю с языком C, из того, что я читаю о цикле событий и стеке, вы должны держать любой объект как можно ближе к вызывающему объекту. Поскольку я новенький, я мог ошибаться.
Многие ответы здесь предлагают сделать его глобальным, но опять же, если я правильно читаю, это могло бы увеличить количество прыжков в стеке и, в некотором смысле, возможно, без необходимости фрагментировать ваш цикл событий (в зависимости от того, что вызываемый объект делает в настоящее время).
Кроме того, любой пример, имитирующий указатели, - это всего лишь 1 во многих отношениях, чтобы делать то же самое, но не указатель.
источник
В вашем примере у вас фактически есть 2 переменные с одинаковым именем. (Глобальная) переменная x и переменная x в области видимости функции . Интересно видеть, что javascript, когда ему предоставляется выбор, что делать с двумя переменными с одинаковым именем, идет с именем в области видимости функции и игнорирует переменную вне области видимости.
Вероятно, небезопасно предполагать, что javascript всегда будет вести себя таким образом ...
Ура!
источник
Нет, ты не можешь. Браузер не дает вам доступа к системной памяти и ее разнообразным возможностям. Это должно быть возможно с такой средой, как node, но внутри браузера это невозможно, если вы не хакер.
источник