Указатели в JavaScript?

Можно ли передать ссылку переменной, которая является неизменной как аргумент в функции?

Пример:

var x = 0;
function a(x)
{
    x++;
}
a(x);
alert(x); //Here I want to have 1 instead of 0

Ответ 1

Так как 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

Ответ 2

Этот вопрос может помочь: Как передать переменную по ссылке в javascript? Чтение данных из функции ActiveX, которая возвращает более одного значения

Подводя итог, примитивные типы Javascript всегда передаются по значению, тогда как значения внутри объектов передаются по ссылке (спасибо комментаторам за указание моего контроля). Итак, чтобы обойти это, вы должны поместить свое целое внутри объекта:

var myobj = {x:0};

function a(obj)
{
    obj.x++;
}

a(myobj);
alert(myobj.x); // returns 1

  

Ответ 3

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

В JavaScript, как и в C, переменные массива на самом деле просто указывают на массив, поэтому вы можете использовать массив точно так же, как объявление указателя. Таким образом, все указатели в вашем коде могут использоваться одинаково, несмотря на то, что вы назвали переменную в исходном объекте.

Он также позволяет использовать две разные обозначения, ссылающиеся на адрес указателя и то, что находится по адресу указателя.

Вот пример (я использую знак подчеркивания для обозначения указателя):

var _x = [ 10 ];

function foo(_a){
    _a[0] += 10;
}

foo(_x);

console.log(_x[0]);

Урожайность

output: 20

Ответ 4

Вы ссылаетесь на "x" из окна объекта

var x = 0;

function a(key, ref) {
    ref = ref || window;  // object reference - default window
    ref[key]++;
}

a('x');                   // string
alert(x);

Ответ 5

Поздний ответ, но я столкнулся с методом передачи примитивных значений посредством ссылки посредством закрытия. Сложно создать указатель, но он работает.

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

Ответ 6

В JavaScript, который был бы глобальным. Однако ваша функция будет выглядеть примерно так:

function a(){
   x++;
};

Так как x находится в глобальном контексте, вам не нужно передавать его в функцию.

Ответ 7

Javascript должен просто поместить указатели в микс, потому что он решает много проблем. Это означает, что код может ссылаться на неизвестное имя переменной или переменные, которые были созданы динамически. Он также упрощает модульное кодирование и инъекцию.

Это то, что я вижу как самое близкое к тому, что вы можете сделать с помощью указателей на практике

в 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

Ответ 8

Это может быть невозможно, поскольку 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);

Ответ 9

В JavaScript вы не можете передавать переменные по ссылке на функцию. Однако вы можете передать объект по ссылке.

Ответ 10

Я думаю, что в отличие от C или любого языка с указателями:

/** Javascript **/
var o = {x:10,y:20};
var o2 = {z:50,w:200};
  • очевидно, в javascript вы не можете получить доступ к объектам o и o2 в памяти
  • но вы не можете сравнить их адрес: (нет тривиальной возможности сортировать их, а затем получить доступ к дихотомии) li >

.

o == o2 // obviously false : not the same address in memory
o <= o2 // true !
o >= o2 // also true !!

что огромная проблема:

  • это означает, что вы можете перечислить/управлять всеми объектами, созданными (выделенными) вашим приложением,

  • из этого огромного списка объектов, вычислите некоторую информацию о них (например, как они связаны друг с другом)

  • но если вы хотите получить информацию, которую вы создали об определенном объекте, вы не можете найти ее в своем огромном списке по дихотомии: нет уникального идентификатора для каждого объекта, которые могут использоваться в качестве замены реального адреса памяти.

это, наконец, означает, что это огромная проблема, если вы хотите написать в javascript:

  • a отладчик javascript/IDE
  • или специально оптимизированный сборщик мусора
  • a ящик/анализатор структуры данных

Ответ 11

JavaScript не поддерживает передачу примитивных типов по ссылке. Однако есть обходной путь.

Поместите все переменные, которые вам нужно передать в объекте. В этом случае существует только одна переменная, x. Вместо передачи переменной передайте имя переменной как строку, которая "x".

var variables = {x:0};
function a(x)
{
    variables[x]++;
}
a("x");
alert(variables.x);

Ответ 12

В зависимости от того, что вы хотели бы сделать, вы могли бы просто сохранить имя переменной, а затем получить доступ к ней позже:

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

Ответ 13

Это просто не поддерживает указатели, конец истории :-(.

Я хотел бы добавить, что, хотя я новичок и пришел из C-фона, из того, что я читаю о цикле событий и стеке, вы должны держать любой объект как можно ближе к его вызывающему объекту. Поскольку я новичок, я могу ошибаться.

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

Кроме того, любой пример с указателями, имитирующими указатели, всего лишь во многих отношениях делает одно и то же, что не будет указателем.

Ответ 14

Нет, ты не можешь. Браузер не дает вам доступ к системной памяти и ее переменным. Это должно быть возможно с подобным окружению узлом, но внутри браузера это не совсем возможно, если вы не хакер.

Ответ 15

В вашем примере у вас на самом деле есть две переменные с тем же именем. (Глобальная) переменная x и переменная x с переменной. Интересно видеть, что javascript, когда ему задан выбор того, что делать с 2 переменными с тем же именем, относится к имени области действия и игнорирует переменную вне области видимости.

Вероятно, небезопасно предположить, что javascript всегда будет вести себя так...

Ура!