Когда копируются значения?

#javascript

#javascript

Вопрос:

Я знаю, что Javascript всегда передает объекты по ссылке. Но как насчет других типов?

число — ?
строка — неизменяемая, поэтому это не должно иметь значения
object — ref
array — ?
функция — ?
регулярное выражение — ?

Я пришел к выводу, что не все значения в 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 
  

Комментарии:

1. Я отправил электронное письмо Дугласу Крокфорду, и его ответ на эту ситуацию таков: «Когда вы присваиваете переменной, вы даете переменной ссылку. Когда вы передаете переменную в качестве аргумента, вы передаете ссылку, которую содержит переменная, а не саму переменную. » Я считаю, что проблема просто в том, что мне еще многому предстоит научиться.

Ответ №1:

Нет. JavaScript всегда передается по значению, а не по ссылке.

Люди часто путают возможность изменять объект в методе и делают так, чтобы модификация была видна снаружи как передаваемая по ссылке. Это не так. Передача по ссылке означает изменение того, на что указывает значение, видимое вне функции. Например

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

В этом примере, если JavaScript реализовал передачу по ссылке, тогда x === 42 было бы true. Однако это не так. Переменная x все равно будет иметь значение {}

Комментарии:

1. «Объекты передаются по ссылке. Они никогда не копируются» — «Javascript: хорошие части» Дугласа Крокфорда

2. @П.Брайан. Mackey ссылки по-прежнему передаются по значению. Существует разница между «передачей по ссылке» и «передачей ссылки по значению». JavaScript выполняет последнее.

3. В JavaScript нет указателя, поэтому передача по ссылке приобретает другое значение…

4. @xavierm02 не совсем. Другие языки поддерживают понятие передачи по ссылке без необходимости указателей (C # без unsafe , F # и VB. Например, Net). Понятие передачи по ссылке можно рассматривать независимо от указателей. Это способ передачи местоположения вместо значения. C также может делать это вместо указателей.

5. @xavierm02, не верь всему, что читаешь в книгах по JS ;). Если вам интересна тема, прочитайте эту статью: ECMA-262 подробно: стратегия оценки 1 Джареду.

Ответ №2:

Я думаю, что более продуктивно думать примерно так:

  • Существуют изменяемые (объекты, массивы и т.д.) и неизменяемые (числа, логические значения, строки) значения.
  • Передача параметров всегда осуществляется по назначению.
  • Присвоение параметров невозможно увидеть вне функции, поскольку вы просто меняете локальную переменную, чтобы указать где-то в другом месте.
  • Если объект является изменяемым, и вы вызываете методы или присваиваете свойства, эти изменения видны за пределами функции (т. Е. Объект не был скопирован, когда он был передан в функцию)

Поэтому вам не нужно узнавать, передается ли тип по ссылке, вам нужно проверить, является ли он изменяемым.

Ответ №3:

Каждый объект передается по ссылке. И на самом деле все является объектом.

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

В обоих случаях вы можете быть уверены, что функция ничего не изменит в вашем объекте, потому что в объекте ничего нельзя изменить. Поэтому вам просто все равно, клонировано оно или нет.