JS: Если переменная получает объект из функции, хранит ли переменная содержимое объекта или ссылку на объект?

Я новичок в Java Script и не понимаю, что хранит переменная, если она получает возвращаемое значение функции, которая является объектом. Я боюсь, что такая переменная не хранит значение, а только ссылку на память, которая может быть перезаписана чуть позже.

Я попробовал это, чтобы узнать это:

Эта функция возвращает объект с содержимым: name="first" или name="second":

var returnObject = function (theSecond) {
    var obj = { name : "first" };
    if (theSecond) {
        obj.name = 'second';
    }
    return obj;
};

Сейчас получают 2 переменные, что возвращает функция:

var obj1 = returnObject(false); // obj3.name==first
var obj2 = returnObject(true);  // obj2.name==second

Хранят ли переменные копии объекта, находящегося в функции, или они ссылаются на объекты в функции? Если это только ссылка, то они ссылаются на очищенную память, которая может быть неожиданная перезапись. Поэтому я надеюсь, что они хранят копии объекта.

Является ли obj3 только ссылкой на ojb1?

var obj3 = obj1;        // obj3 is a link to obj1?

Кажется, что obj3 хранит не копию obj1, а только ссылку на obj1, потому что:

obj3.name = "third";    // obj3.name==third and immediately obj1.name==third

Хорошо, теперь переменная obj1 отображается так же, как и переменная obj3, потому что это ссылка на obj3.

Запутанно:

obj1 = returnObject(false); // obj1.name==first BUT still obj3.name==third. WHY???

Почему сейчас ссылка не работает? obj3.name по-прежнему «третий», но obj1.name «первый»!? Как obj3 может хранить значение, отличное от obj1?

Функция копирования?

var copy = function (obj) { return obj; };

Используй это:

obj2 = copy(obj1);      // obj2.name==first

Является ли obj2 копией obj1 или ссылкой на obj1?

obj2.name = "secondAgain";  

obj2.name теперь является secondAgain, но сразу же obj1.name также становится secondAgain. Кажется, что это не функция копирования. obj2 - это только ссылка на obj1. :-(

Теперь я сбитый с толку новичок в JavaScript. :-((

Теги: javascript объект копировать функция ссылка возвращаемое значение указатель клонировать назначать присвоение

ОБНОВИТЬ:

Я понимаю 2 ответа, что:

var retObj = function { return { name : "first" }; };
var objA = retObj();

... имеет тот же эффект, что и:

var objA = { name : "first" };

А также:

var copy = function (obj) { return obj; };
var objB = copy(objA);

... имеет тот же эффект, что и:

var objB = objA;

Но почему:

... может ли переменная, которая является ссылкой на другую переменную, хранить отдельный объект?

var retObjX  = function () { return { name : "X"  }; };
var retObjX2 = function () { return { name : "X2" }; };
var objX = retObjX();   // objX=X
var objY = objX;        // Y refers X
objX = retObjX2();      // objX=X2 BUT! objY=X

Я думаю, что переменная objY является не ссылкой на переменную objX, а ссылкой на объект в retObjX(), потому что: objY все еще показывает X, а не X2.

Что, если объект, который возвращает функция, является не константным литералом, а объектом, который строится динамически? Будет ли ссылочная переменная показывать объект, который был создан этой функцией в последний раз?

var retObjDyn = function () { return { rnd : Math.floor(Math.random() * 100) }; };
var objDynX = retObjDyn();  // 44
var objDynY = objDynX;      // 44
objDynX = retObjDyn();      // objDynX=78 BUT STILL: objDynY=44

objDynY, который является ссылкой на объект, который был сохранен в objDynX, по-прежнему показывает этот объект, даже когда objDynX показывает другой объект.

Теперь я думаю, что retObjDyn() создает новый объект при каждом вызове. Но сохраняются ли эти объекты, или память освобождается для других целей? Чем objDynY может неожиданно изменить свое содержимое.


person Inherent    schedule 29.01.2014    source источник
comment
Посмотрите на: Javascript по ссылке и по значению   -  person Givi    schedule 30.01.2014
comment
@ Givi: Спасибо, ваша ссылка посвящена тому же вопросу. Я все еще не уверен, что память, в которой хранятся объекты, созданные функцией, защищена и не будет неожиданно перезаписана.   -  person Inherent    schedule 31.01.2014


Ответы (2)


Это кажется запутанным, но на самом деле это простая концепция. Объекты в JavaScript передаются по ссылке, например, массивы и объекты; это суть.

В первой функции вы создаете новый объект при каждом вызове:

var returnObject = function (theSecond) {
    var obj = { name : "first" }; // create a new object
    if (theSecond) {
        obj.name = 'second';
    }
    return obj; // return the new object
};

Обозначение литерала объекта {} создает новый объект.

Хранят ли переменные копии объекта, находящегося в функции, или они ссылаются на объекты в функции? Если это только ссылка, они ссылаются на очищенную память, которая может быть неожиданно перезаписана. Поэтому я надеюсь, что они хранят копии объекта.

Переменные obj1 и obj2 содержат разные объекты. Они не связаны с функцией. Как только функция возвращает объект, это делается, и объект присваивается вашей переменной. Память не течет. Вы можете проверить, что это разные объекты:

obj1 === obj2 // false, not the same object

Является ли obj3 только ссылкой на ojb1?

var obj3 = obj1; 

Да, переменная obj3 содержит тот же объект, что и переменная obj1, таким образом:

obj3 === obj1 // true, same object, just a reference

Итак, согласно этому правилу, ваша функция copy не копирует объект, а просто берет объект и возвращает тот же самый объект. Это не копия. Чтобы скопировать объект, вы должны создать новый объект и зациклить все свойства старого объекта, присвоить их новому объекту и вернуть результат. Простой пример:

function copy(obj) {
  var newObj = {}; // a brand new object
  for (var i in obj) {
    if (obj.hasOwnProperty(i)) {
      newObj[i] = obj[i]; // copy property
    }
  }
  return newObj;
}
person elclanrs    schedule 29.01.2014

Переменная не содержит object, но содержит reference. Если вы присвоите эту переменную другой, они обе будут иметь одну и ту же ссылку.

Из того, что я слышал: когда вы передаете объект (что-либо не примитивное) функции в качестве параметра, будет передана ссылка. Это означает, что ваша функция копирования фактически присваивает ссылку. Ваш returnObject возвращает новый

obj1 = returnObject(false) создаст новый объект (который вы создаете в функции)

person Flame    schedule 29.01.2014