基元类型(数字、字符串等)是通过值传递的,但对象是未知的,因为它们既可以通过值传递(如果我们认为持有对象的变量实际上是对对象的引用),也可以通过引用传递(当我们认为对象的变量持有对象本身)。
虽然最后这并不重要,但我想知道通过约定来表达论点的正确方式是什么。是否有JavaScript规范的摘录,该规范定义了与此相关的语义?
基元类型(数字、字符串等)是通过值传递的,但对象是未知的,因为它们既可以通过值传递(如果我们认为持有对象的变量实际上是对对象的引用),也可以通过引用传递(当我们认为对象的变量持有对象本身)。
虽然最后这并不重要,但我想知道通过约定来表达论点的正确方式是什么。是否有JavaScript规范的摘录,该规范定义了与此相关的语义?
当前回答
在JavaScript中向函数传递参数类似于传递参数(按C中的指针值):
/*
The following C program demonstrates how arguments
to JavaScript functions are passed in a way analogous
to pass-by-pointer-value in C. The original JavaScript
test case by @Shog9 follows with the translation of
the code into C. This should make things clear to
those transitioning from C to JavaScript.
function changeStuff(num, obj1, obj2)
{
num = num * 10;
obj1.item = "changed";
obj2 = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);
console.log(obj2.item);
This produces the output:
10
changed
unchanged
*/
#include <stdio.h>
#include <stdlib.h>
struct obj {
char *item;
};
void changeStuff(int *num, struct obj *obj1, struct obj *obj2)
{
// make pointer point to a new memory location
// holding the new integer value
int *old_num = num;
num = malloc(sizeof(int));
*num = *old_num * 10;
// make property of structure pointed to by pointer
// point to the new value
obj1->item = "changed";
// make pointer point to a new memory location
// holding the new structure value
obj2 = malloc(sizeof(struct obj));
obj2->item = "changed";
free(num); // end of scope
free(obj2); // end of scope
}
int num = 10;
struct obj obj1 = { "unchanged" };
struct obj obj2 = { "unchanged" };
int main()
{
// pass pointers by value: the pointers
// will be copied into the argument list
// of the called function and the copied
// pointers will point to the same values
// as the original pointers
changeStuff(&num, &obj1, &obj2);
printf("%d\n", num);
puts(obj1.item);
puts(obj2.item);
return 0;
}
其他回答
确定某个对象是否“通过引用传递”的一个简单方法是您是否可以编写“交换”函数。例如,在C中,您可以执行以下操作:
void swap(int *i, int *j)
{
int t;
t = *i;
*i = *j;
*j = t;
}
如果你不能在JavaScript中做到这一点,那就不是“通过引用传递”。
在JavaScript中,值的类型仅控制该值是由值副本分配还是由引用副本分配。
基本值始终由值副本分配/传递:
无效的未定义一串数字布尔型ES6中的符号
复合值始终由引用副本分配/传递
物体阵列作用
例如
var a = 2;
var b = a; // `b` is always a copy of the value in `a`
b++;
a; // 2
b; // 3
var c = [1,2,3];
var d = c; // `d` is a reference to the shared `[1,2,3]` value
d.push( 4 );
c; // [1,2,3,4]
d; // [1,2,3,4]
在上面的代码段中,因为2是标量原语,所以a保存该值的一个初始副本,而b被分配了该值的另一个副本。更改b时,绝对不能更改a中的值。
但c和d都是对同一共享值[1,2]的单独引用,这是一个复合值。需要注意的是,c和d都没有“拥有”[1,2,3]值——两者都只是对该值的对等引用。因此,当使用任意一个引用来修改(.push(4))实际的共享数组值本身时,它只影响一个共享值,并且两个引用都将引用新修改的值[1,2,3,4]。
var a = [1,2,3];
var b = a;
a; // [1,2,3]
b; // [1,2,3]
// later
b = [4,5,6];
a; // [1,2,3]
b; // [4,5,6]
当我们赋值b=[4,5,6]时,我们没有做任何事情来影响a仍然引用的位置([1,2,3])。要做到这一点,b必须是指向a的指针,而不是对数组的引用——但JS中不存在这样的功能!
function foo(x) {
x.push( 4 );
x; // [1,2,3,4]
// later
x = [4,5,6];
x.push( 7 );
x; // [4,5,6,7]
}
var a = [1,2,3];
foo( a );
a; // [1,2,3,4] not [4,5,6,7]
当我们传入参数a时,它将一个引用的副本分配给x。x和a是指向相同[1,2,3]值的独立引用。现在,在函数内部,我们可以使用该引用来改变值本身(push(4))。但是当我们赋值x=[4,5,6]时,这不会影响初始引用a指向的位置——仍然指向(现在已修改)[1,2,3,4]值。
要有效地通过值副本传递复合值(如数组),需要手动复制它,这样传递的引用就不会指向原始值。例如:
foo( a.slice() );
可以通过引用副本传递的复合值(对象、数组等)
function foo(wrapper) {
wrapper.a = 42;
}
var obj = {
a: 2
};
foo( obj );
obj.a; // 42
这里,obj充当标量基元属性a的包装器。当传递给foo(..)时,将传入obj引用的副本,并将其设置为wrapper参数。我们现在可以使用包装器引用来访问共享对象,并更新其属性。函数完成后,obj.a将看到更新的值42。
来源
变量不“保存”对象;它有一个参考。您可以将该引用分配给另一个变量,现在两者都引用同一个对象。它总是按值传递(即使该值是引用…)。
无法更改作为参数传递的变量所持有的值,如果JavaScript支持通过引用传递,这是可能的。
函数内部的简单值不会改变函数外部的值(通过值传递),而复杂值会(通过引用传递)。
function willNotChange(x) {
x = 1;
}
var x = 1000;
willNotChange(x);
document.write('After function call, x = ' + x + '<br>'); // Still 1000
function willChange(y) {
y.num = 2;
}
var y = {num: 2000};
willChange(y);
document.write('After function call y.num = ' + y.num + '<br>'); // Now 2, not 2000
JavaScript按值传递原语类型,按引用传递对象类型
现在,人们喜欢没完没了地争论是否“通过引用”是描述Java等实际操作的正确方式这是:传递对象不会复制对象。传递给函数的对象可以由该函数修改其成员。传递给函数的基元值不能由该函数修改。复制完成。在我的书中,这叫做通过引用传递。
-Brian Bi-哪些编程语言是通过引用传递的?
使现代化
以下是对此的反驳:
JavaScript中没有可用的“通过引用传递”。