javascript变量参考/别名


89

是否有可能在JavaScript中以某种方式将别名/引用分配给本地var?

我的意思是类似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中的某个人会来做这件事:)
Amarghosh,2009年

Answers:


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)。这个方法有可能吗?如果可以理解,我可以为“参数”加上别名,但是无论如何我还是要写“被调用者”,不是吗?
gpilotino,

9
@Darin:这有点简化了。它是可变类型而不是可变类型,而不是原始类型和对象。在JavaScript中,一切都是某种形式的对象。

7
在JS中,引用是按值传递的。“通过引用传递”和“通过值传递引用”之间存在区别。在Javascript中,不支持通过引用传递参数。
Corneliu 2012年

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 

1
我相信“ alert(y); //打印2”应该是:“ alert(y()); //打印2”您必须实际调用函数以获取结果。太糟糕了,因为建议的语法在某些情况下会有所帮助。
内森·拉彭兹

3
之所以存在toString重新定义是有原因的,alert(y)实际上是正确的。尽管重新定义Function原型方法是非常糟糕的样式。但是,嘿!
metalim 2016年

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

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

扩展user187291的文章,您还可以使用getter / setter来解决必须使用函数的问题。

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'

0

在2019年,我需要编写缩小的jquery插件,所以我也需要这个别名,因此从其他来源测试了这些示例和其他示例,我发现了一种在整个对象的内存中不复制但仅创建引用的方法。我已经使用Firefox进行了测试,并在Firefox上观看了任务管理器的选项卡内存。代码是:

var {p: d} ={p: document};
console.log(d.body);

这不会通过引用传递任何内容,您可以直接传递文档(它已经是对对象的引用,并通过值传递)。销毁不会创建别名。
记得莫妮卡
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.