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 f1 = function(inputObject){
    inputObject.a = 2;
}

var f2 = function(){
    var inputObject = {"a": 1};
    f1(inputObject);
    console.log(inputObject.a);
}

调用f2会将“a”值打印为2而不是1,因为引用被传递并且引用中的“a”值被更新。

使用primitive的示例:

var f1 = function(a){
    a = 2;
}
var f2 = function(){
    var a = 1;
    f1(a);
    console.log(a);
}

调用f2会将“a”值打印为1。

其他回答

实际上,Alnitak是正确的,而且很容易理解,但最终在JavaScript中,一切都是通过值传递的。

对象的“值”是什么?它是对象引用。

当你传入一个对象时,你得到这个值的一个副本(因此Alnitak描述的“引用的副本”)。如果你改变了这个值,你不会改变原来的对象;您正在更改该引用的副本。

我的两分钱....JavaScript是通过引用还是值传递参数无关紧要。真正重要的是赋值还是变异。

我在这个链接里写了一个更长的,更详细的解释。

当你传递任何东西(无论是一个对象还是一个原语)时,JavaScript所做的只是在函数内部分配一个新变量……就像使用等号(=)一样。

这个参数在函数内部的行为和你用等号赋值一个新变量的行为是完全一样的。举几个简单的例子。

var myString = '测试字符串1'; //赋值-指向myString相同位置的链接 var sameString = myString; //如果我改变了sameString, myString将不会改变, //它只是重新赋值给一个全新的字符串 sameString = '新字符串'; console.log (myString);//记录'测试字符串1'; console.log (sameString);//记录'新字符串';

如果我将myString作为参数传递给一个函数,它的行为就好像我简单地将它赋给了一个新变量。现在,让我们做同样的事情,但是用一个函数而不是简单的赋值

函数myFunc(sameString) { / /重置手术……同样,它不会修改myString sameString = '新字符串'; } var myString = '测试字符串1'; //它的行为与sameString = myString相同 myFunc (myString); console.log (myString);//再次,日志'测试字符串1';

当你将对象传递给函数时,你可以修改对象的唯一原因是你没有重新赋值…相反,对象可以更改或突变....同样,它的工作方式是一样的。

var myObject = { name: 'Joe'; }

// Assignment - We simply link to the same object
var sameObject = myObject;

// This time, we can mutate it. So a change to myObject affects sameObject and visa versa
myObject.name = 'Jack';
console.log(sameObject.name); // Logs 'Jack'

sameObject.name = 'Jill';
console.log(myObject.name); // Logs 'Jill'

// If we re-assign it, the link is lost
sameObject = { name: 'Howard' };
console.log(myObject.name); // Logs 'Jill'

如果我将myObject作为参数传递给一个函数,它的行为就好像我简单地将它赋给了一个新变量。同样的事情,同样的行为,但是是一个函数。

函数myFunc(sameObject) { //我们改变了对象,所以myObject也得到了改变…就像以前一样。 sameObject.name = 'Jill'; //但是,如果我们重新分配它,链接就丢失了 sameObject = { 名称:“霍华德” }; } var myObject = { 名称:“乔” }; //这就像我们说sameObject = myObject一样; myFunc (myObject); console.log (myObject.name);//日志'Jill'

每次将变量传递给函数时,你都是在“赋值”给参数的名称,就像使用等号一样。

永远记住等号=表示赋值。 将参数传递给函数也意味着赋值。 它们是相同的两个变量以完全相同的方式连接在一起。

修改一个变量影响另一个变量的唯一情况是底层对象发生变化。

区分对象和原语是没有意义的,因为它的工作方式就像你没有一个函数,只是用等号赋值给一个新变量一样。

对象总是按引用传递,原语总是按值传递。只要将参数保持在对象的相同地址即可。

下面是一些代码来说明我的意思(在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是在引用传递的函数之后通过引用传递

原语通过值传递,对象通过“引用的副本”传递。

具体来说,当你传递一个对象(或数组)时,你是在(无形地)将一个引用传递给那个对象,并且有可能修改那个对象的内容,但如果你试图覆盖引用,它不会影响调用者持有的引用的副本——即引用本身是按值传递的:

function replace(ref) {
    ref = {};           // this code does _not_ affect the object passed
}

function update(ref) {
    ref.key = 'newvalue';  // this code _does_ affect the _contents_ of the object
}

var a = { key: 'value' };
replace(a);  // a still has its original value - it's unmodfied
update(a);   // the _contents_ of 'a' are changed

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

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

在这样的陈述中,

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

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