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());

当前回答

为了创建一个使用const的简单示例…

const myRef = { foo: 'bar' };
const myVal = true;

function passes(r, v) {
  r.foo = 'baz';
  v = false;
}

passes(myRef, myVal);

console.log(myRef, myVal); // Object {foo: "baz"} true

其他回答

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

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

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

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

下面是一些代码来说明我的意思(在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 test(value) {
  console.log('retrieve value');
  console.log(value());
}

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

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

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

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

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。