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中通过引用模拟标量参数的最好方法是使用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。

其他回答

“全局”JavaScript变量是窗口对象的成员。您可以将引用作为窗口对象的成员访问。

var v = "initialized";

function byref(ref) {
  window[ref] = "changed by ref";
}

byref((function(){for(r in window){if(window[r]===v){return(r);}}})());
// It could also be called like... byref('v');
console.log(v); // outputs changed by ref

注意,上面的例子不适用于函数中声明的变量。

与C语言一样,最终,所有内容都是通过值传递的。不像C语言,你不能实际备份和传递变量的位置,因为它没有指针,只有引用。

它所引用的都是对象,而不是变量。有几种方法可以达到相同的结果,但它们必须手工完成,而不仅仅是在调用或声明站点上添加关键字。

在人们试图证明这一点的例子中,我看不到参考传递。我只看到值传递。

对于包含对象引用的变量,引用就是那些变量的值,因此引用被传递,然后被值传递。

在这样的陈述中,

var a = {
  b: "foo",
  c: "bar"
};

“a”的值不是对象,而是(到目前为止唯一的)对它的引用。换句话说,对象不在变量a中——对它的引用在。我认为这对于只熟悉JavaScript的程序员来说似乎很难。但是对于懂Java、c#和C的人来说,这是很容易的。

原语是按值传递的。但如果你只需要读取一个原语的值(在函数被调用时,值是不知道的),你可以传递一个函数,在你需要它的时候检索它的值。

function test(value) {
  console.log('retrieve value');
  console.log(value());
}

// call the function like this
var value = 1;
test(() => value);

你可以这样想:

无论何时在ECMAscript中创建一个对象,这个对象都是在一个神秘的ECMAscript通用的地方形成的,没有人能够得到。你只能得到这个神秘地方的那个物体的参考。

var obj = { };

即使obj也只是对对象的引用(它位于那个特殊的位置),因此,你只能传递这个引用。实际上,任何访问obj的代码段都会修改很远很远的对象。