何时复制值

When are values copied?

本文关键字:复制 何时      更新时间:2023-09-26

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

number - ?
string -不可变,所以不应该影响
对象- ref
数组- ?
函数- ?
Regexp - ?

我得出的结论是,不是Javascript中的所有值都可以是对象,也不能通过引用传递,下面的代码:

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 

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

人们常常把在方法中修改对象并使修改在外部可见的能力与通过引用传递的能力混为一谈。事实并非如此。引用传递意味着修改函数外部可见的值所指向的内容。例如

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

在这个例子中,如果JavaScript实现了引用传递,那么x === 42将为真。然而,事实并非如此。变量x的值仍然是{}

我认为这样想更有成效:

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

所以你不需要知道一个类型是否是通过引用传递的,你需要检查它是否是可变的

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

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'

但是即使所有都是通过引用传递的,对于字面量,你可以认为它们是通过值传递的,因为你不能修改它们。

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

在ES 5中,有这个新函数Object.freeze,它使对象无法修改。基本上,当你传递字面量时,你所做的就是传递一个不可变对象。

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

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