Ссылка на переменную javascript / псевдоним

89

Возможно ли в javascript каким-то образом назначить псевдоним / ссылку на локальную переменную?

Я имею в виду что-то в стиле C:

function foo() {
  var x = 1;
  var y = &x;
  y++;
  alert(x); // prints 2 
}

= РЕДАКТИРОВАТЬ =

Можно ли использовать псевдоним arguments.callee в этом коде ?:

function foo() {
  arguments.callee.myStaticVar = arguments.callee.myStaticVar || 0;
  arguments.callee.myStaticVar++;
  return arguments.callee.myStaticVar;
}
гпилотино
источник
5
Простой ответ - нет. Но у меня такое чувство, что кто-то из SO придет с хаком, чтобы сделать это :)
Амаргош,

Ответы:

173

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

// declare an object with property x
var obj = { x: 1 };
var aliasToObj = obj;
aliasToObj.x ++;
alert( obj.x ); // displays 2
Дарин Димитров
источник
это было быстро =) я хочу создать псевдоним для arguments.callee внутри моей функции (просто чтобы каждый раз не вводить arguments.callee). это возможно с помощью этого метода? Если я понимаю, я могу использовать псевдоним «arguments», но мне все равно нужно писать «вызываемый», не так ли?
gpilotino 06
9
@Darin: это немного упрощает. Это неизменные и изменяемые типы, а не примитивные типы и объекты. В JavaScript все является объектом в той или иной форме.
Crescent Fresh
7
В JS ссылка передается по значению. Есть разница между «передачей по ссылке» и «передачей ссылки по значению». В Javascript не поддерживается передача параметров по ссылке.
Corneliu
15

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

Function.prototype.toString = function() {
    return this();
}

var x = 1;
var y = function() { return x }
x++;
alert(y); // prints 2, no need for () because of toString redefinition 
user187291
источник
1
Я считаю, что «alert (y); // выводит 2» должно быть: «alert (y ()); // выводит 2». Вы должны действительно вызвать функцию, чтобы получить результат. Жаль, поскольку предложенный синтаксис может быть полезен в определенных ситуациях.
Натан Лабенц
3
Это переопределение toString существует не просто так, так alert(y)что на самом деле оно верно. Хотя переопределение методов прототипа функций - это очень плохой стиль. Но эй, это работает!
metalim
8

Можно ли использовать псевдоним для чего-либо, зависит от типа данных. Объекты, массивы и функции будут обрабатываться по ссылке, возможно использование псевдонимов. Другие типы по сути атомарны, и переменная хранит значение, а не ссылку на значение.

arguments.callee - это функция, поэтому вы можете иметь ссылку на нее и изменять этот общий объект.

function foo() {
  var self = arguments.callee;
  self.myStaticVar = self.myStaticVar || 0;
  self.myStaticVar++;
  return self.myStaticVar;
}

Обратите внимание, что если бы в приведенном выше коде вы сказали, self = function() {return 42;};тогда selfбы он ссылался на другой объект, чем arguments.callee, который остается ссылкой на foo. Когда у вас есть составной объект, оператор присваивания заменяет ссылку, он не изменяет упомянутый объект. С атомарными значениями такой вариант y++эквивалентен y = y + 1, что переменной присваивается «новое» целое число.

Только в любви
источник
не говоря arguments.calleeуже о том, что у него уже есть псевдоним, который является именем функции. В этом примере вы могли бы просто использовать foo.myStaticVar(может быть, это было не так в 2009 году?)
aljgom
2

Расширяя сообщение user187291 , вы также можете использовать геттеры / сеттеры, чтобы обойти необходимость использования функций.

var x = 1;
var ref = {
    get x()  { return x; },
    set x(v) { x = v; }
};
(ref.x)++;
console.log(x); // prints '2'
x--;
console.log(ref.x); // prints '1'
Стивен Хименес
источник
1

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

var countMe = ( function() {
  var c = 0;

  return function() {
    c++;
    return c;
  }
})();

alert(countMe()); // Alerts "1"
alert(countMe()); // Alerts "2"

Здесь c служит счетчиком, и вам не нужно использовать arguments.callee.

Том Бартель
источник
или вы можете использовать статическую переменную countMe = function f(){ return ++f.c || (f.c = 1); }
aljgom
1

в 2019 году мне нужно написать миниатюрные плагины jquery, поэтому мне тоже нужен этот псевдоним, поэтому, тестируя эти и другие примеры из других источников, я нашел способ без копирования в памяти всего объекта, а создание только ссылки. Я уже тестировал это с помощью firefox и раньше смотрел память вкладок диспетчера задач в firefox. Код такой:

var {p: d} ={p: document};
console.log(d.body);
Константин
источник
Это ничего не передает по ссылке, вы можете просто передать документ напрямую (который уже является ссылкой на объект и передается по значению). Деструктуризация не создает псевдонимов.
Помните Монику