Иногда вы можете получить только количество месяцев между двумя датами, полностью игнорирующими дневную часть. Например, если у вас были две даты - 2013/06/21 и 2013/10/18 - и вы заботились только о частях 2013/06 и 2013/10, вот сценарии и возможные решения:
var date1=new Date(2013,5,21);//Remember, months are 0 based in JS
var date2=new Date(2013,9,18);
var year1=date1.getFullYear();
var year2=date2.getFullYear();
var month1=date1.getMonth();
var month2=date2.getMonth();
if(month1===0){ //Have to take into account
month1++;
month2++;
}
var numberOfMonths;
1.Если вы хотите просто количество месяцев между двумя датами, исключая как month1, так и month2
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) - 1;
2.Если вы хотите включить один из месяцев
numberOfMonths = (year2 - year1) * 12 + (month2 - month1);
3.Если вы хотите включить оба месяца
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) + 1;
Это интересно в Javascript. Рассмотрим этот пример:
function changeStuff(a, b, c)
{
a = a * 10;
b.item = "changed";
c = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);
console.log(obj2.item);
Это приводит к выходу:
10
changed
unchanged
obj1.item
не повлияет на obj1
вне функции. num
будет 100
, а obj2.item
будет читать "changed"
. Вместо этого ситуация заключается в том, что переданный элемент передается по значению. Но элемент, который передается по значению, является самой ссылкой. Технически это называется вызовом по обмену .
В практическом плане это означает, что если вы измените сам параметр (как в num
и obj2
), что не повлияет на элемент, который был подан в параметр. Но если вы измените INTERNALS параметра, который будет распространяться обратно (как с obj1
).
Объект вне функции передается в функцию, указывая ссылку на внешний obejct. Когда вы используете эту ссылку для манипулирования своим объектом, объект наружу, таким образом, затрагивается. Однако, если внутри функции вы решили указать ссылку на что-то еще, вы вообще не повлияли на объект снаружи, потому что все, что вы делали, перенаправляло ссылку на что-то еще.
Для юристов на языке программирования я просмотрел следующие разделы ECMAScript 5.1 (который легче читать, чем последнее издание), и дойдите до , задав его в списке рассылки ECMAScript ,
TL; DR : все передаются по значению, но свойства объектов - это ссылки, а определение объекта, как правило, отсутствует в стандарте.
Раздел 11.2.4 «Списки аргументов» говорит следующее о создании списка аргументов, состоящего всего из 1 аргумента:
Вывод ArgumentList: AssignmentExpression оценивается следующим образом:
- Пусть ref является результатом оценки AssignmentExpression.
- Пусть arg - GetValue (ref).
- Возвращает список, единственным элементом которого является arg.
В этом разделе также перечислены случаи, когда список аргументов имеет 0 или> 1 аргумент.
Таким образом, все передается по ссылке.
Доступ к свойствам объекта
Раздел 11.2.1 «Аксессоры свойств»
Вывод MemberExpression: MemberExpression [Expression] оценивается следующим образом:
- Пусть baseReference будет результатом оценки MemberExpression.
- Пусть baseValue будет GetValue (baseReference).
- Пусть свойствоNameReference является результатом вычисления выражения.
- Пусть свойствоNameValue будет GetValue (свойствоNameReference).
- Вызов CheckObjectCoercible (baseValue).
- Пусть свойствоNameString будет ToString (propertyNameValue).
- If синтаксическое производство, которое оценивается, содержится в коде строгого режима, пусть строгое истинно, иначе пусть строгое будет ложным.
- Возвращает значение типа Reference , базовое значение которого baseValue и ссылочным именем которого является свойствоNameString, а флаг строгого режима - строгий.
Таким образом, свойства объектов всегда доступны как рефери се.
On Reference
Описан в разделе 8.7 «Тип ссылочной спецификации», что ссылки не являются реальными типами на языке - они используются только для описания поведения delete, typeof и операторы присваивания.
Определение «Object»
В редакции 5.1 определено, что «Object - это совокупность свойств». Поэтому мы можем заключить, что значение объекта - это коллекция, но что касается того, что значение коллекции плохо определено в спецификации, и требует немного усилий для понимания.
Мой простой способ понять это ...
var var1 = 13;
var var2 = { prop: 2 };
//13 and var2's content (reference) are being passed here
foo(var1, var2);
inVar1
и inVar2
получают переданное содержимое. function foo(inVar1, inVar2){
//changing contents of inVar1 and inVar2 won't affect variables outside
inVar1 = 20;
inVar2 = { prop: 7 };
}
inVar2
получил ссылку { prop: 2 }
, вы можете изменить значение свойства объекта. function foo(inVar1, inVar2){
inVar2.prop = 7;
}
Рассмотрим следующее:
Итак, забудьте о «pass by reference / value» не зацикливаться на «pass by reference / value», потому что:
Чтобы ответить на ваш вопрос : указатели переданы.
// code
var obj = {
name: 'Fred',
num: 1
};
// illustration
'Fred'
/
/
(obj) ---- {}
\
\
1
// code
obj.name = 'George';
// illustration
'Fred'
(obj) ---- {} ----- 'George'
\
\
1
// code
obj = {};
// illustration
'Fred'
(obj) {} ----- 'George'
| \
| \
{ } 1
// code
var obj = {
text: 'Hello world!'
};
/* function parameters get their own pointer to
* the arguments that are passed in, just like any other variable */
someFunc(obj);
// illustration
(caller scope) (someFunc scope)
\ /
\ /
\ /
\ /
\ /
{ }
|
|
|
'Hello world'
Некоторые окончательные комментарии:
var a = [1,2];
var b = a;
a = [];
console.log(b); // [1,2]
// doesn't work because `b` is still pointing at the original array
{'George', 1}
значений, но только один из них за один раз, то как другие управляются? И что происходит, когда я присваиваю переменную значение другой переменной? Я тогда указываю на указатель или указывая на указатель правильного операнда? Имеет ли var myExistingVar = {"blah", 42}; var obj = myExistingVar;
результат obj
, указывающий на {"blah", 42}
, или на myExistingVar
?
– Michael Hoffmann
4 March 2017 в 22:43
1)
я запустил профиль памяти в инструментах браузера dev для функции цикла, такой как описанная вами, и увидел всплески в использовании памяти во время цикла. Казалось бы, это указывает на то, что на каждой итерации цикла действительно создаются новые идентичные объекты. Когда пики внезапно падают, сборщик мусора просто очистил группу этих неиспользуемых объектов.
– geg
14 March 2017 в 05:14
2)
Что касается чего-то вроде var a = b
, javascript не предоставляет механизм для использования указателей, и поэтому переменная никогда не может указывать на указатель (как вы можете на C), хотя базовый механизм javascript, несомненно, использует их. Поэтому ... var a = b
будет указывать a
"на указатель правильного операнда"
– geg
14 March 2017 в 05:16
Очень подробное объяснение о копировании, прохождении и сравнении по значению и по ссылке содержится в в этой главе книги «JavaScript: окончательное руководство».
До мы оставляем тему манипуляции объектами и массивами по ссылке, нам нужно прояснить точку номенклатуры. Фраза «пройти по ссылке» может иметь несколько значений. Для некоторых читателей фраза относится к методу вызова функции, которая позволяет функции назначать новые значения своим аргументам и изменять эти измененные значения вне функции. Это не значит, что термин используется в этой книге. Здесь мы имеем в виду просто, что ссылка на объект или массив - не сам объект - передается функции. Функция может использовать ссылку для изменения свойств объекта или элементов массива. Но если функция перезаписывает ссылку ссылкой на новый объект или массив, эта модификация не видна вне функции. Читатели, знакомые с другим значением этого термина, могут предпочесть сказать, что объекты и массивы передаются по значению, но переданное значение на самом деле является ссылкой, а не самим объектом.
One вещь, которую я до сих пор не могу понять. Проверьте код ниже. Любые мысли?
function A() {} A.prototype.foo = function() { return 'initial value'; } function B() {} B.prototype.bar = A.prototype.foo; console.log(A.prototype.foo()); //initial value console.log(B.prototype.bar()); //initial value A.prototype.foo = function() { return 'changed now'; } console.log(A.prototype.foo()); //changed now console.log(B.prototype.bar()); //Why still 'initial value'???
Я нашел метод extend библиотеки Underscore.js очень полезен, когда я хочу передать объект в качестве параметра, который может быть либо изменен, либо полностью заменен .
function replaceOrModify(aObj) {
if (modify) {
aObj.setNewValue('foo');
} else {
var newObj = new MyObject();
// _.extend(destination, *sources)
_.extend(newObj, aObj);
}
}
Передача аргументов функции в JavaScript аналогична передаче параметров по значению указателя в C:
/*
The following C program demonstrates how arguments
to JavaScript functions are passed in a way analogous
to pass-by-pointer-value in C. The original JavaScript
test case by @Shog9 follows with the translation of
the code into C. This should make things clear to
those transitioning from C to JavaScript.
function changeStuff(num, obj1, obj2)
{
num = num * 10;
obj1.item = "changed";
obj2 = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);
console.log(obj2.item);
This produces the output:
10
changed
unchanged
*/
#include <stdio.h>
#include <stdlib.h>
struct obj {
char *item;
};
void changeStuff(int *num, struct obj *obj1, struct obj *obj2)
{
// make pointer point to a new memory location
// holding the new integer value
int *old_num = num;
num = malloc(sizeof(int));
*num = *old_num * 10;
// make property of structure pointed to by pointer
// point to the new value
obj1->item = "changed";
// make pointer point to a new memory location
// holding the new structure value
obj2 = malloc(sizeof(struct obj));
obj2->item = "changed";
free(num); // end of scope
free(obj2); // end of scope
}
int num = 10;
struct obj obj1 = { "unchanged" };
struct obj obj2 = { "unchanged" };
int main()
{
// pass pointers by value: the pointers
// will be copied into the argument list
// of the called function and the copied
// pointers will point to the same values
// as the original pointers
changeStuff(&num, &obj1, &obj2);
printf("%d\n", num);
puts(obj1.item);
puts(obj2.item);
return 0;
}
Все аргументы функции в ECMAScript передаются по значению. Это означает, что значение вне функции копируется в аргумент внутри функции так же, как значение копируется из одной переменной в другую. Если значение является примитивным, то оно действует так же, как и примитивная переменная, и если значение является ссылкой, оно действует как копия ссылочной переменной. Это часто является путаницей для разработчиков, поскольку к переменным обращаются как по значению, так и по ссылке, но аргументы передаются только по значению. Когда аргумент передается по значению, значение копируется в локальную переменную (именованный аргумент и в ECMAScript - слот в объекте arguments). Когда аргумент передается по ссылке, местоположение значения в памяти сохраняется в локальной переменной, что означает, что изменения в локальной переменной отражаются вне функции. (Это невозможно в ECMAScript.)
В некоторых случаях это может быть полезно изменить anArg
:
function alterMyArg(func) {
// process some data
// ...
func(data);
}
alertMyArg(function(d) {anArg = d;});
Наиболее кратким объяснением, которое я нашел, было в руководстве по стилю AirBNB :
Например:
var foo = 1,
bar = foo;
bar = 9;
console.log(foo, bar); // => 1, 9
Например:
var foo = [1, 2],
bar = foo;
bar[0] = 9;
console.log(foo[0], bar[0]); // => 9, 9
Т.е. эффективно примитивные типы передаются по значению, а сложные типы передаются по ссылке.
Я бы сказал, что это pass-by-copy -
. Рассмотрение аргументов и объектов переменных - это объекты, созданные во время контекста выполнения, созданного в начале вызова функции, - и ваше фактическое значение / ссылка, переданная в функция просто хранится в этих аргументах + объекты переменных.
Проще говоря, для примитивных типов значения копируются в начале вызова функции, для типа объекта ссылка копируется.
Javascript всегда pass-by-value , все имеет тип значения. Объекты являются значениями, функции-члены объектов сами являются значениями (помните, что функции являются первоклассными объектами в Javascript). Кроме того, в отношении концепции, что все в Javascript является объектом , это неверно. Строками, символами, числами, булевыми значениями, нулями и неопределенными являются примитивы . Иногда они могут использовать некоторые функции-члены и свойства, унаследованные от их базовых прототипов, но это только для удобства, это не значит, что они сами объекты. Попробуйте следующее для справки
x = "test";
alert(x.foo);
x.foo = 12;
alert(x.foo);
В обоих предупреждениях вы найдете неопределенное значение.
x = "teste"; x.foo = 12;
и т. Д. Просто потому, что свойство не является постоянным, это не значит, что это не объект. Как говорит MDN: В JavaScript почти все является объектом. Все примитивные типы, кроме null и undefined, рассматриваются как объекты. Им могут быть назначены свойства (назначенные свойства некоторых типов не являются постоянными), и у них есть все характеристики объектов. I> link
– slacktracer
16 August 2012 в 02:49
Здесь обсуждается использование термина «передать по ссылке» в JS здесь , но для ответа на ваш вопрос:
Объект автоматически передается ссылка, без необходимости конкретно указывать его
(Из статьи, упомянутой выше.)
object1 = {item: "car"};
array1=[1,2,3];
здесь вы назначаете новый объект или массив старым. Вы не меняете значение свойства старого объекта. Так что это пропуск по значению. если вы изменяете значение свойства объекта или массива, то оно передается по ссылке. object1.key1= "car";
array1[0]=9;
здесь вы меняете значение свойства старого объекта. Вы не назначаете новый объект или массив старым. Также он передается по ссылке. Код
function passVar(object1, object2, number1) {
object1.key1= "laptop";
object2 = {
key2: "computer"
};
number1 = number1 + 1;
}
var object1 = {
key1: "car"
};
var object2 = {
key2: "bike"
};
var number1 = 10;
passVar(object1, object2, number1);
console.log(object1.key1);
console.log(object2.key2);
console.log(number1);
Output: -
laptop
bike
10
На языке низкого уровня, если вы хотите передать переменную по ссылке, вы должны использовать определенный синтаксис при создании функции:
int myAge = 14;
increaseAgeByRef(myAge);
function increaseAgeByRef(int &age) {
*age = *age + 1;
}
&age
является ссылкой на myAge
, но если вам нужно значение, которое вы должны преобразовать ссылку, используйте *age
.
Javascript - это язык высокого уровня, который делает это преобразование для вас. Таким образом, хотя объекты передаются по ссылке, язык преобразует ссылочный параметр в значение. Вам не нужно использовать &
в определении функции, чтобы передать его по ссылке, а не *
, в тело функции, чтобы преобразовать ссылку на значение, JS делает это для вас.
Поэтому, когда вы пытаетесь изменить объект внутри функции, заменив его значение (т.е. age = {value:5}
), это изменение не сохраняется, но если вы измените его свойства (например, age.value = 5
), , он делает.
Простые значения внутри функций не изменят эти значения вне функции (они передаются по значению), тогда как сложные (будут переданы по ссылке).
function willNotChange(x) {
x = 1;
}
var x = 1000;
willNotChange(x);
document.write('After function call, x = ' + x + '<br>'); //still 1000
function willChange(y) {
y.num = 2;
}
var y = {num: 2000};
willChange(y);
document.write('After function call y.num = ' + y.num + '<br>'); //now 2, not 2000
Подумайте об этом так: он всегда проходит по значению. Однако значение объекта не является самим объектом, а ссылкой на этот объект.
Вот пример, передающий число (примитивный тип)
function changePrimitive(val) {
// At this point there are two '10's in memory.
// Changing one won't affect the other
val = val * 10;
}
var x = 10;
changePrimitive(x);
// x === 10
Повторение этого с объектом дает разные результаты:
function changeObject(obj) {
// At this point there are two references (x and obj) in memory,
// but these both point to the same object.
// changing the object will change the underlying object that
// x and obj both hold a reference to.
obj.val = obj.val * 10;
}
var x = { val: 10 };
changeObject(x);
// x === { val: 100 }
One еще пример:
function changeObject(obj) {
// Again there are two references (x and obj) in memory,
// these both point to the same object.
// now we create a completely new object and assign it.
// obj's reference now points to the new object.
// x's reference doesn't change.
obj = { val: 100 };
}
var x = { val: 10 };
changeObject(x);
// x === { val: 10}
Теперь люди любят бесконечно препираться о том, является ли «пройти по ссылке» правильным способом описать, что такое Java et al. действительно делаю. Дело в том, что:
- Передача объекта не копирует объект.
- Объект, переданный функции, может иметь свои члены, модифицированные функцией.
- Первичное значение, переданное функции, не может быть изменено функцией. Копия сделана.
В моей книге это называется передачей по ссылке.
- Брайан Би - Какие языки программирования проходят по ссылке?
Мои 2 цента ... Я так понимаю. (Не стесняйтесь исправить меня, если я ошибаюсь)
Пришло время выбросить все, что вы знаете о прохождении по значению / ссылке.
Поскольку в JavaScript не имеет значения, передается ли оно по значению или по ссылке или что-то еще. Важна мутация против назначения параметров, переданных в функцию.
Хорошо, позвольте мне изо всех сил объяснить, что я имею в виду. Допустим, у вас есть несколько объектов.
var object1 = {};
var object2 = {};
То, что мы сделали, это «назначение» ... Мы назначили 2 отдельных пустых объекта для переменных «object1» и «object2».
Теперь скажем, что нам нравится object1 лучше ... Итак, мы «назначаем» новую переменную.
var favoriteObject = object1;
Далее, по какой-то причине мы решили, что нам нравится объект 2 лучше. Итак, мы просто немного переустановили.
favoriteObject = object2;
Ничего не случилось с object1 или object2. Мы вообще ничего не изменили. Все, что мы сделали, было переназначением того, что наш любимый объект. Важно знать, что объекты object2 и favoriteObject назначаются одному и тому же объекту. Мы можем изменить этот объект с помощью любой из этих переменных.
object2.name = 'Fred';
console.log(favoriteObject.name) // logs Fred
favoriteObject.name = 'Joe';
console.log(object2.name); // logs Joe
OK, теперь давайте посмотрим на примитивы, такие как строки, например
var string1 = 'Hello world';
var string2 = 'Goodbye world';
Опять же, мы выбираем любимую.
var favoriteString = string1;
Обе наши переменные favoriteString и string1 присваиваются «Hello world». Теперь, что, если мы хотим изменить наш любимыйString ??? Что произойдет ???
favoriteString = 'Hello everyone';
console.log(favoriteString); // Logs 'Hello everyone'
console.log(string1); // Logs 'Hello world'
Э-э ... Что случилось. Мы не можем изменить string1, изменив функцию favoriteString ... Почему? потому что строки неизменяемы, и мы не мутировали их. Все, что мы сделали, это «RE ASSIGN» favoriteString для новой строки. Это существенно отключило его от string1. В предыдущем примере, когда мы переименовали наш объект, мы ничего не назначали. (Ну, на самом деле ... мы это сделали, мы присвоили свойство name новой строке.) Вместо этого мы просто мутировали объект, который поддерживает связи между двумя переменными и базовыми объектами.
Теперь, на функции и параметры передачи .... Когда вы вызываете функцию и передаете параметр, то, что вы по существу делаете, это «назначение» новой переменной, и она работает точно так же, как если бы вы просто назначили использование равного ( =).
Возьмем эти примеры.
var myString = 'hello';
// Assign to a new variable (just like when you pass to a function)
var param1 = myString;
param1 = 'world'; // Re assignment
console.log(myString); // logs 'hello'
console.log(param1); // logs 'world'
Теперь то же самое, но с функцией
function myFunc(param1) {
param1 = 'world';
console.log(param1); // logs 'world'
}
var myString = 'hello';
// Calls myFunc and assigns param1 to myString just like param1 = myString
myFunc(myString);
console.log(myString); // logs 'hello'
OK, теперь давайте несколько примеров с использованием объектов вместо этого ... во-первых, без функции.
var myObject = {
firstName: 'Joe',
lastName: 'Smith'
};
// Assign to a new variable (just like when you pass to a function)
var otherObj = myObject;
// Let's mutate our object
otherObj.firstName = 'Sue'; // I guess Joe decided to be a girl
console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Sue'
// Now, let's reassign
otherObj = {
firstName: 'Jack',
lastName: 'Frost'
};
// Now, otherObj and myObject are assigned to 2 very different objects
// And mutating one object no longer mutates the other
console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Jack';
Теперь то же самое, но с вызовом функции
function myFunc(otherObj) {
// Let's mutate our object
otherObj.firstName = 'Sue';
console.log(otherObj.firstName); // Logs 'Sue'
// Now let's re-assign
otherObj = {
firstName: 'Jack',
lastName: 'Frost'
};
console.log(otherObj.firstName); // Logs 'Jack'
// Again, otherObj and myObject are assigned to 2 very different objects
// And mutating one object no longer mutates the other
}
var myObject = {
firstName: 'Joe',
lastName: 'Smith'
};
// Calls myFunc and assigns otherObj to myObject just like otherObj = myObject
myFunc(myObject);
console.log(myObject.firstName); // Logs 'Sue', just like before
OK, если вы прочитайте весь этот пост, возможно, теперь у вас есть лучшее понимание того, как вызовы функций работают в javascript. Не имеет значения, передается ли что-то по ссылке или по значению ... Что важно, так это назначение vs mutation.
Каждый раз, когда вы передаете переменную функции, вы «назначаете» любое имя переменной параметра, как если бы вы использовали знак равенства (=).
Всегда помните, что знак равенства (=) означает назначение. Всегда помните, что передача параметра функции также означает назначение. Они одинаковы, и 2 переменные связаны точно так же.
Единственный раз, когда изменение переменной влияет на другую переменную, - это когда основной объект мутирован.
Там нет смысла проводить различия между объектами и примитивами, поскольку он работает точно так же, как если бы у вас не было функции, и просто использовал знак равенства для назначения новой переменной.
Единственный gotcha - это когда имя переменной, которую вы передаете в функцию, совпадает с именем параметра функции. Когда это происходит, вы должны обрабатывать параметр внутри функции, как если бы это была целая новая переменная, закрытая для функции (потому что это так)
function myFunc(myString) {
// myString is private and does not affect the outer variable
myString = 'hello';
}
var myString = 'test';
myString = myString; // Does nothing, myString is still 'test';
myFunc(myString);
console.log(myString); // logs 'test'
foo(char *a){a="hello";}
ничего не делает, но если вы делаете foo(char *a){a[0]='h';a[1]='i';a[2]=0;}
, это изменяется вне, потому что a
- это ячейка памяти, переданная по значению, которая ссылается на строку (массив символов). Передача структур (подобно объектам js) по значению в C разрешена, но не рекомендуется. JavaScript просто применяет эти лучшие практики и скрывает ненужные и обычно нежелательные трещины ... и это, безусловно, облегчает чтение.
– technosaurus
26 March 2015 в 10:49
source = { "id":"1"}; copy = source /*this is wrong*/; copy.id="2"
, этот источник все еще {& quot; id & quot;: & quot; 1 & quot;}?
– Machtyn
22 February 2016 в 21:23
Легкий способ определить, является ли что-то «пройденным по ссылке», можно ли написать функцию «своп». Например, в C вы можете сделать:
void swap(int *i, int *j)
{
int t;
t = *i;
*i = *j;
*j = t;
}
Если вы не можете сделать эквивалент этого в Javascript, это не «передать по ссылке».
Переменная не «удерживает» объект, он содержит ссылку. Вы можете назначить эту ссылку другой переменной, теперь оба ссылаются на один и тот же объект. Он всегда проходит по значению (даже если это значение является ссылкой ...).
Невозможно изменить значение, удерживаемое переменной, переданной как параметр, что было бы возможно, если бы JS поддерживала передачу по ссылке.
Я читал эти ответы несколько раз, но НЕ ДЕЙСТВИТЕЛЬНО добирался до тех пор, пока не узнал о техническом определении «Вызов путем совместного использования» , как это называется Барбарой Лисков
< blockquote>Семантика вызова путем совместного использования отличается от вызова по ссылке в том, что назначения для аргументов функции внутри функции не отображаются вызывающему (в отличие от ссылочной семантики) [например, если переменная была передана, невозможно смоделировать присвоение этой переменной в области вызывающего. Однако, поскольку функция имеет доступ к тому же объекту, что и вызывающий (без копирования), мутации для этих объектов, если объекты изменяемы, внутри функции видны вызывающему, которые могут отличаться от вызова по значению семантика. Мутации изменяемого объекта внутри функции видны вызывающему, потому что объект не копируется и не клонируется - он является общим.
То есть, ссылки на параметры изменяются, если вы идете и получаете доступ к самого параметра. С другой стороны, назначение параметра исчезает после оценки и не доступно для вызывающего функции.
Он всегда проходит по значению, но для объектов значение переменной является ссылкой. Из-за этого, когда вы передаете объект и меняете его членов , эти изменения сохраняются вне функции. Это делает выглядеть как пропуск по ссылке. Но если вы действительно измените значение переменной объекта, вы увидите, что это изменение не сохраняется, доказывая, что оно действительно передается по значению.
Пример:
function changeObject(x) {
x = {member:"bar"};
alert("in changeObject: " + x.member);
}
function changeMember(x) {
x.member = "bar";
alert("in changeMember: " + x.member);
}
var x = {member:"foo"};
alert("before changeObject: " + x.member);
changeObject(x);
alert("after changeObject: " + x.member); /* change did not persist */
alert("before changeMember: " + x.member);
changeMember(x);
alert("after changeMember: " + x.member); /* change persists */
Выход:
before changeObject: foo
in changeObject: bar
after changeObject: foo
before changeMember: foo
in changeMember: bar
after changeMember: bar
changeObject
я изменил x
, чтобы содержать ссылку на новый объект. x = {member:"bar"};
эквивалентно x = new Object(); x.member = "bar";
То, что я говорю, также относится и к C #.
– Tim Goodman
19 July 2011 в 22:47
ref
, вы можете передать ссылку по ссылке (вместо значения по умолчанию для передачи ссылки по значению), а затем изменить на пункт a new Object()
будет i> сохраняться.
– Tim Goodman
19 July 2011 в 22:55
Примитивы передаются по значению, а объекты передаются по ссылке. Это сильно отличается от других языков, таких как C, VB или Delphi. Я не могу сказать, как они точно обрабатывают объекты и примитивы, но я знаю VB и Delphi, что он может (и должен) быть указан.
php делает что-то подобное с версии 5: все объекты передаются но все примитивы могут быть переданы по ссылке, если предшествует амперсанд (& amp;). В противном случае примитивы передаются по значению.
Итак, в javascript, если передать объект X в функцию через параметр, он все равно будет X. Если вы меняете данные внутри функция (или любой другой объект, но это не важно), что новое значение также доступно вне функции.
var x = {hi : 'hi'}; change(x); console.log(x.hi); function change(x) { x.hi = 'changed'; }
изменяет поведение.
– Olgun Kaya
6 September 2017 в 09:01
разделяет то, что я знаю о ссылках в javascript
blockquote>В Javascript объекты хранятся в виде ссылок:
var a = { a: 1, b: 2, c: 3 }; var b = a; //b.c is referencing to a.c value console.log(b.c) //output: 3 //changing value of b.c b.c = 4 //also changes the value of a.c console.log(a.c) //output: 4
В JavaScript тип значения исключительно определяет, будет ли это значение присвоено копией значения или копией-копией.
Примитивные значения всегда назначаются / передаются с помощью copy-копии :
null
undefined
ES6
Соединение значения всегда назначаются / передаются с помощью reference-copy
Например
var a = 2;
var b = a; // `b` is always a copy of the value in `a`
b++;
a; // 2
b; // 3
var c = [1,2,3];
var d = c; // `d` is a reference to the shared `[1,2,3]` value
d.push( 4 );
c; // [1,2,3,4]
d; // [1,2,3,4]
В приведенном выше фрагменте, поскольку 2
является скалярным примитивом, a
содержит одну начальную копию этого значения, а b
присваивается другая копия значения , При изменении b
вы никоим образом не изменяете значение в a
.
Но оба c
и d
являются отдельными ссылками на одно и то же общее значение [1,2,3]
, которое является составная величина. Важно отметить, что ни c
, ни d
больше не «владеют» значением [1,2,3]
- оба равны равным равноправным ссылкам на значение. Таким образом, при использовании любой ссылки для изменения (.push(4)
) фактического общего значения array
, это влияет только на одно общее значение, и обе ссылки будут ссылаться на вновь измененное значение [1,2,3,4]
.
var a = [1,2,3];
var b = a;
a; // [1,2,3]
b; // [1,2,3]
// later
b = [4,5,6];
a; // [1,2,3]
b; // [4,5,6]
Когда мы выполняем присваивание b = [4,5,6]
, мы ничего не делаем, чтобы повлиять на a
, где [1,2,3]
все еще ссылается. Для этого b
должен быть указателем на a
, а не ссылкой на array
, но в JS нет такой возможности
function foo(x) {
x.push( 4 );
x; // [1,2,3,4]
// later
x = [4,5,6];
x.push( 7 );
x; // [4,5,6,7]
}
var a = [1,2,3];
foo( a );
a; // [1,2,3,4] not [4,5,6,7]
Когда мы проходим аргумент a
, он присваивает копию ссылки a
на x
. x
и a
- отдельные ссылки, указывающие на то же значение [1,2,3]
. Теперь внутри функции мы можем использовать эту ссылку для мутации самого значения (push(4)
). Но когда мы выполняем присваивание x = [4,5,6]
, это никоим образом не влияет на то, где указывается начальная ссылка a
, - все еще указывает на значение (теперь измененное) [1,2,3,4]
.
Чтобы эффективно пройти составное значение (например, array
) по копированию значения, вам нужно вручную сделать его копию, чтобы переданная ссылка не все еще указывала на оригинал. Например:
foo( a.slice() );
Составное значение (объект, массив и т. Д.), Которое может быть передано посредством reference-copy
function foo(wrapper) {
wrapper.a = 42;
}
var obj = {
a: 2
};
foo( obj );
obj.a; // 42
Здесь obj
действует как обертка для скалярное примитивное свойство a
. Когда передано foo(..)
, копия ссылки obj
передается и устанавливается в параметр wrapper
. Теперь мы можем использовать ссылку wrapper
для доступа к общему объекту и обновить его свойство. После завершения функции obj.a
вы увидите обновленное значение 42
.
item
объекта, на которое ссылается obj1, вы меняете значение свойства элемента, которое изначально было установлено так «без изменений». Когда вы назначаете obj2 значение {item: & quot; changed & quot;}, вы меняете ссылку на новый объект (который сразу выходит из области действия при выходе из функции). Становится более очевидным, что происходит, если вы называете функцию params такими, как numf, obj1f и obj2f. Затем вы видите, что параметры скрывали внешние имена переменных. – jinglesthula 30 January 2012 в 21:26ref
.) Обычно вы просто должны вернуть функцию новому объекту , и выполняйте назначение в том месте, где вы вызываете функцию. Например,foo = GetNewFoo();
вместоGetNewFoo(foo);
– Tim Goodman 5 August 2013 в 16:26var obj1 = { item: 'unchanged' }; var obj2 = obj1; obj2.item = 'changed';
и наблюдать тот же эффект, что и в вашем примере. Поэтому я лично ссылаюсь на ответ Тима Гудмана – chiccodoro 2 May 2014 в 10:19