0

给定 JavaScript 中的函数是引用类型(通过引用复制,与简单类型不同),这里到底发生了什么?

var func = function() { alert(1); };
var func_alias = func;
var func = function() { alert(2); };
func_alias(); //1

如果func_alias是对 的引用func为什么它不更新?您不希望它的调用(第 4 行)返回2吗?

这是与其他引用示例不同的行为:

var obj = {prop: 'val'};
var obj_alias = obj;
obj.prop = 'updated val';
alert(obj_alias.prop); //updated val - not original one

func_alias似乎保留了原始的预覆盖副本func- 简而言之,它似乎表现得好像它是按价值复制的。这当然被以下事实证明是不成立的:

var func = function(){}
var func_alias = func;
func === func_alias; //true
4

3 回答 3

2

var func = function() { alert(1); };

这里创建了一个新函数,并将对它的引用复制到func

var func_alias = func;

存储的函数引用func被分配给另一个变量func_alias

var func = function() { alert(2); };

另一个新函数被创建并且对它的引用被分配给func. 对存储在其中的第一个函数的引用func丢失。但是由于您func_alias在覆盖之前保存了它func,因此仍然可以调用它。

func_alias();

func_alias在步骤 2 中被分配了对第一个函数的引用(并且在那之后没有被覆盖)。所以第一个函数被调用。


编辑#1

根据您使用对象的第二个示例:

var obj = {prop: 'val'};

在这里,创建了一个新对象并将对它的引用分配给obj

var obj_alias = obj;

引用被复制到另一个变量 obj_alias

obj.prop = 'updated val';

在这里,您不会覆盖 的值obj,而只是覆盖存储在 obj 中的引用所指向的对象的属性。的值obj(即对第一步创建的对象的引用)保持不变。

在您的函数示例中,您实际上是func用新的函数引用覆盖了变量。

alert(obj_alias.prop);

的 和 的值仍然相同,因为您也没有覆盖obj_aliasobj它们都持有对第 1 步中创建的对象的引用。


编辑#2

这可以用C语言很好地解释。

  • 当您通过创建对象时var obj = {prop: 'val'};- 假设该对象存储在内存中的地址 0x0001 处。即obj的实际值为0x0001

  • 当您将其分配给 时obj_aliasobj_alias也会获得值 0x0001 - 现在两个变量都指向存储在地址 0x0001 的内容

  • 当您这样做时obj.x = y,您不会覆盖 的值obj,而只是obj用于访问存储在 0x0001 的对象并修改其属性之一。

于 2012-08-15T08:45:17.583 回答
1

不同的是

在第一段代码中,您让一个变量引用另一个对象。

在第二段代码中,你改变了对象的属性,这两个变量是指同一个对象。

var func = function() { alert(1); };
var func_alias = func; // func_alias refer to the first function.
var func = function() { alert(2); }; // let func refer to another function, but won't affect func_alias
func_alias(); //1
于 2012-08-15T08:33:58.750 回答
0

如果您认为您的程序代码是一个允许您存储和使用对象的大型仓库。
然后您的代码执行以下操作:
第 1 行 - 让我们存储函数 SOMEWHERE 并且我(第一个变量)会记住它的位置 [您没有(也不能)在此处指定特定位置]。
第 2 行 - 让其他人也记住函数的存储位置。
第 3 行 - 让我们在 SOMEWHERE 存储另一个函数,我(第一个变量)会记住它在哪里[你没有(也不能)在此处指定特定位置]。
第 4 行 - 询问第 2 行的人我的职能在哪里。

你预期的结果是什么?

于 2012-08-15T08:44:13.890 回答