Javascript函数 – 指针分配

考虑这个JavaScript代码:

var bar = function () { alert("A"); } var foo = bar; bar = function () { alert("B"); }; foo(); 

运行这个代码时,我得到“A”。 这是行为的JavaScript规范的一部分,我可以依靠它吗?

是的,这是预计和devise。

你的问题基本上是: foo引用bar作为指针或引用会在另一种语言?

答案是否定的: 赋值bar被赋值给foo

在其他的例子中,没有任何东西是被传递的。 一切都通过参考传递。

酒吧和富都是两个指针

所有在JavaScript中的非原始对象的variables/句柄都是指针; 指针是原生的JavaScript,他们是默认的。

 var bar = function () { alert("A"); } //bar is a pointer to function1 var foo = bar; //pointer copied; foo is now also a pointer to function1 bar = function () { alert("B"); }; //bar points to function2 foo(); //foo is still a pointer to function1 

如果您认为它们是副本,则会遇到隐藏的错误和错误。 特别是如果你使用复杂的对象。 例如

 function person(name){this.name = name} var john = new person("john") var backup = john backup.name //john john.name = "jack" backup.name //jack, NOT john 

要在javascript中真正地复制一个非原语,需要比a = b更多的工作。 例如:

 function person(name){ this.name = name} var john = new person("john") var backup = new Object() backup = JSON.parse(JSON.stringify(john)) backup.__proto__ = john.__proto__ //useful in some cases john.name = "jack" backup.name //john 

我在这里有点晚,但是我想我会给出一个答案,并且有所作为。

讨论JavaScript(或ECMAScript)的内部结构时,最好不要考虑指针和内存引用。 variables是内部的环境logging,按名称存储和引用,而不是内存地址。 在内部和devise上,你的赋值语句正在执行的是查找环境logging名称(“foo”或“bar”)并将该值赋值给该logging。

所以,

 var bar = function () { alert("A"); } 

分配环境logging“bar”的值(匿名函数)。

 var foo = bar; 

内部调用GetValue(“bar”),它检索与logging“bar”相关联的值,然后将该值与logging“foo”相关联。 因此,之后bar的原始值仍然可以被使用,因为它现在与foo相关联。

因为JavaScript通过string引用而不是内存地址正是为什么你可以这样做:

 someObject["someProperty"] 

它正在查找基于属性名称的值。

是的,没有什么特别的事实,variables是指的function,没有别名涉及。

 var bar = 1; var foo = bar; bar = "something entirely different"; // foo is still 1 

您正将一个匿名函数的值分配给一个不是指针的variables。
如果你想玩指针,你可以使用通过引用传递的对象,而不是复制。

这里有些例子:

“obj2”是“obj1”的引用,更改“obj2”,更改“obj1”。 它会提醒false

 var obj1 = {prop:true}, obj2 = obj1; obj2.prop = false; alert(obj1.prop); 

“prop”指向一个属性,而不是一个对象,“prop”不是指向这个对象的指针而是一个副本。 如果你改变“道具”,“obj1”不会改变。 它会提醒true

 var obj1 = {prop:true}, prop = obj1.prop; prop = false; alert(obj1.prop); 

“obj2”是对“obj1”的“subObj”属性的引用。 如果“obj2”被改变,“obj1”被改变。 它会提醒false

 var obj1 = {subObj:{prop:true}}, obj2 = obj1.subObj; obj2.prop = false; alert(obj1.subObj.prop); 

是的,这是正确的行为。

 //create variable bar and assign a function to it var bar = function () { alert("A"); } //assign value of bar to the newly created variable foo var foo = bar; //assign a new function to the variable bar //since foo and bar are not pointers, value of foo doesn't change bar = function () { alert("B"); }; //call the function stored in foo foo(); 

这些不是函数指针(本身没有JS的指针)。 JS中的函数可以是匿名的,并且是第一类对象。 于是

 function () { alert("A"); } 

创build一个匿名函数,在执行时提醒“A”;

 var bar = function () { alert("A"); }; 

分配该function吧;

 var foo = bar; 

将foo分配给bar,这是函数“A”。

 bar = function () { alert("B"); }; 

重新绑定到一个匿名函数“B”。 这不会影响foo或其他function“A”。

 foo(); 

调用存储在foo中的函数,这是函数“A”。


实际上,在有function点的语言中,例如C也不会影响foo 。 我不知道你在哪里得到重新分配“B”的想法。

 void A(void) { printf("A\n"); } void B(void) { printf("B\n"); } typedef void(*fptr_t)(void); fptr_t foo = A; fptr_t bar = foo; bar = B; foo(); // should print "A" 

这是给一个未命名的函数分配一个variables,而不是一个指向函数的指针

是的,你已经创build了一个指向原始“A”函数的指针。 当你重新分配吧,你正在重新分配它,但你仍然只留下旧函数的任何引用。

所以要回答你的问题,是的,你可以依靠它。

我只想添加这也适用于预定义的命名函数:

 function myfunc() { alert("A"); } var bar = myfunc; var foo = bar; bar = function () { alert("B"); }; foo(); 

这将做同样的事情,表明函数名称像数组名称(指针)。

对于代码中的每个FunctionDeclaration f,按源文本顺序执行:

让fn是函数声明中的标识符f。

设第13章描述的实例化FunctionDeclaration f的结果。

让funcAlreadyDeclared是调用env的HasBinding具体方法传递fn作为参数的结果。

如果funcAlreadyDeclared为false,则调用env的CreateMutableBinding具体方法,传递fn和configurableBindings作为参数。

参考

  • ECMAScript-5:10.5节