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沙箱中试试,比如https://js.do/)。
不幸的是,你不能只保留参数的地址;还保留了所有原始成员值。
a = { key: 'bevmo' };
testRetain(a);
document.write(' after function ');
document.write(a.key);
function testRetain (b)
{
document.write(' arg0 is ');
document.write(arguments[0].key);
b.key = 'passed by reference';
var retain = b; // Retaining the original address of the parameter
// Address of left set to address of right, changes address of parameter
b = {key: 'vons'}; // Right is a new object with a new address
document.write(' arg0 is ');
document.write(arguments[0].key);
// Now retrieve the original address of the parameter for pass by reference
b = retain;
document.write(' arg0 is ');
document.write(arguments[0].key);
}
结果:
Arg0是bevmo Arg0是vons Arg0是在引用传递的函数之后通过引用传递
没有纯粹主义,我认为在JavaScript中通过引用模拟标量参数的最好方法是使用object,就像前面的答案告诉。
然而,我的做法有点不同:
我已经在函数调用内部进行了对象赋值,因此可以在函数调用附近看到引用形参。它增加了源代码的可读性。
在函数声明中,我像注释一样放置属性,出于同样的原因:可读性。
var r;
funcWithRefScalars(r = {amount:200, message:null} );
console.log(r.amount + " - " + r.message);
function funcWithRefScalars(o) { // o(amount, message)
o.amount *= 1.2;
o.message = "20% increase";
}
在上面的例子中,null清楚地表示输出引用参数。
退出:
240 - 20% Increase
在客户端,console.log应该替换为alert。
★★★
另一个方法可读性更强:
var amount, message;
funcWithRefScalars(amount = [200], message = [null] );
console.log(amount[0] + " - " + message[0]);
function funcWithRefScalars(amount, message) { // o(amount, message)
amount[0] *= 1.2;
message[0] = "20% increase";
}
在这里,您甚至不需要创建新的虚拟名称,如上面的r。