何时复制值?

时间:2011-10-21 17:37:05

标签: javascript

我知道Javascript总是通过引用传递对象。但其他类型呢?

号码 - ?
string - Immuteable,所以无所谓 对象 - 参考
数组 - ?
功能 - ?
regexp - ?

我得出的结论是,Javascript中的所有值都不是对象,也不能通过following code引用传递:

function SomeFunc(func) {
    var numba = 0;
    var innerFunc = function() {
       numba = func(numba);//try commenting me out and switching to next line
        //func(numba);//numba fails to increment
       return numba;
    };
   return innerFunc;
}

//this variable should persist the numba variable through closure.  Incrementing each call by 1.
var closure = SomeFunc(function(numba) {
    numba = numba + 1;
    return numba;
});

document.writeln(closure());
document.writeln(closure());
document.writeln(closure());

因为numba无法递增,除非我返回数字并更新闭包中的变量...然后告诉我这不是通过引用传递的。我错过了什么吗?

<小时/> 或采取非常基本的

function UpdateNumber(numba) {
    numba = 10;  
   document.writeln('in func number becomes ' + numba);
}

var numba2 = 5;
UpdateNumber(numba2);

document.writeln('back to caller number is ' + numba2);
//in func number becomes 10 
//back to caller number is 5 

3 个答案:

答案 0 :(得分:4)

没有。 JavaScript总是按值传递,而不是按引用传递。

人们常常混淆修改方法中对象的能力,并且修改在外部可见,因为它是通过引用传递的。不是这种情况。通过引用传递意味着修改值指向的函数外部可见的内容。例如

var f1 = function (p1) {
  p1 = 42;
};
var x = {};
f1(x);

在此示例中,如果JavaScript通过引用传递,则x === 42将为真。但事实并非如此。变量x仍然具有值{}

答案 1 :(得分:2)

我认为考虑这样做会更有成效:

  • 有可变的(对象,数组等)和不可变的(数字,布尔值,字符串)值。
  • 参数传递始终是通过赋值。
  • 在函数外部看不到参数赋值,因为您只是将局部变量更改为指向其他位置。
  • 如果对象是可变的并且您调用方法或分配给属性,那么这些更改将在函数外部看到(即,当对象传递给函数时,没有对该对象进行复制)

因此,您无需了解是否通过引用传递类型,您需要检查它是否可变。

答案 2 :(得分:1)

每个对象都通过引用传递。事实上,一切都是一个对象。

function addProperty( o ) {
    o.property = 'value';
}

// here, we can see that even numbers are passed by reference
var n = new Number( 1 );
addProperty( n );
console.log( n.property );// 'value'

但即使所有内容都是通过引用传递的,对于litterals,您可以认为它们是按值传递的,因为您无法修改它们。

var n = 1;
n.property = 'value';
console.log( n.property );// undefined

在ES 5中,有一个新功能Object.freeze使对象无法修改。 基本上,你在传递一个litteral时正在做的是传递一个不可变的对象。

var n = 1;
var o = Object.create( null );
Object.freeze( o );
doWhatTheFuckYouWant( o );
doWhatTheFuckYouWant( n );

在这两种情况下,您都可以确定该函数不会更改对象的任何内容,因为没有任何内容可以更改。因此,您只是不关心它是否被克隆。