JavaScript是通过引用传递还是通过值传递?
下面是一个来自JavaScript: The Good Parts的例子。我对矩形函数的参数很困惑。它实际上是未定义的,并在函数内部重新定义。没有原始参考文献。如果我从函数参数中删除它,内部区域函数就不能访问它。
它是一个闭包吗?但是没有返回函数。
var shape = function (config) {
var that = {};
that.name = config.name || "";
that.area = function () {
return 0;
};
return that;
};
var rectangle = function (config, my) {
my = my || {};
my.l = config.length || 1;
my.w = config.width || 1;
var that = shape(config);
that.area = function () {
return my.l * my.w;
};
return that;
};
myShape = shape({
name: "Unhnown"
});
myRec = rectangle({
name: "Rectangle",
length: 4,
width: 6
});
console.log(myShape.name + " area is " + myShape.area() + " " + myRec.name + " area is " + myRec.area());
函数参数通过值或共享传递,但在JavaScript中从来不通过引用!
"值
基元类型按值传递:
var num = 123, str = “foo”;
函数 f(num, str) {
数字 += 1;
str += “bar”;
console.log(“inside of f:”, num, str);
}
f(数字, str);
console.log(“Out of f:”, num, str);
函数作用域中的重赋在周围的作用域中是不可见的。
这也适用于string,它是一个复合数据类型,但不可变:
Var STR = "foo";
函数f(str) {
Str [0] = "b";//不起作用,因为字符串是不可变的
Console.log ("in of f:", str);
}
f (str);
Console.log ("outside of f:", str);
Call-by-Sharing
对象,也就是说所有不是基元的类型,都是通过共享传递的。保存对象引用的变量实际上只保存该引用的副本。如果JavaScript采用引用调用求值策略,则变量将保存原始引用。这是共享和引用之间的关键区别。
这种区别的实际后果是什么?
Var o = {x: "foo"}, p = {y: 123};
函数f(o, p) {
O.x = "bar";/ /突变
P = {x: 456};/ /重新分配
Console.log ("o within f:", o);
Console.log ("p inside of f:", p);
}
f (o p);
Console.log ("o outside of f:", o);
Console.log ("p outside of f:", p);
突变是指修改现有对象的某些属性。变量所绑定的引用副本和引用该对象的引用副本保持不变。因此,突变在调用者的作用域中是可见的。
重赋值意味着替换绑定到变量的引用副本。由于它只是一个副本,持有同一引用副本的其他变量不受影响。因此,重赋在调用者的作用域中是不可见的,就像在引用调用求值策略中那样。
关于ECMAScript中评估策略的进一步信息。
函数参数通过值或共享传递,但在JavaScript中从来不通过引用!
"值
基元类型按值传递:
var num = 123, str = “foo”;
函数 f(num, str) {
数字 += 1;
str += “bar”;
console.log(“inside of f:”, num, str);
}
f(数字, str);
console.log(“Out of f:”, num, str);
函数作用域中的重赋在周围的作用域中是不可见的。
这也适用于string,它是一个复合数据类型,但不可变:
Var STR = "foo";
函数f(str) {
Str [0] = "b";//不起作用,因为字符串是不可变的
Console.log ("in of f:", str);
}
f (str);
Console.log ("outside of f:", str);
Call-by-Sharing
对象,也就是说所有不是基元的类型,都是通过共享传递的。保存对象引用的变量实际上只保存该引用的副本。如果JavaScript采用引用调用求值策略,则变量将保存原始引用。这是共享和引用之间的关键区别。
这种区别的实际后果是什么?
Var o = {x: "foo"}, p = {y: 123};
函数f(o, p) {
O.x = "bar";/ /突变
P = {x: 456};/ /重新分配
Console.log ("o within f:", o);
Console.log ("p inside of f:", p);
}
f (o p);
Console.log ("o outside of f:", o);
Console.log ("p outside of f:", p);
突变是指修改现有对象的某些属性。变量所绑定的引用副本和引用该对象的引用副本保持不变。因此,突变在调用者的作用域中是可见的。
重赋值意味着替换绑定到变量的引用副本。由于它只是一个副本,持有同一引用副本的其他变量不受影响。因此,重赋在调用者的作用域中是不可见的,就像在引用调用求值策略中那样。
关于ECMAScript中评估策略的进一步信息。