Javascript函数 - 通过引用复制,但是这里发生了什么?

时间:2012-08-15 08:31:40

标签: javascript function reference variable-assignment

鉴于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

3 个答案:

答案 0 :(得分: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_alias的值以及obj的值仍然相同,因为您还没有覆盖它们。它们都包含对步骤1中创建的对象的引用。


编辑#2

这可以用 C 术语来解释。

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

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

  • 当您执行obj.x = y时,您不会覆盖obj的值,而只会使用obj来访问存储在0x0001中的对象并修改其中一个属性

答案 1 :(得分: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

答案 2 :(得分:0)

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

您的预期结果是什么?