Копирование и удаление переменных(обьектов).
Здравствуйте, меня интересуют особенности внутренней работы интерпретатора и браузера.
Например: В каком порядке удаляются объекты? Когда переменная копируется по значение а когда по ссылке? ... Может кто то подскажет книжки или статьи с данной инфой. Заранее благодарен. |
Yazla,
В js переменные со значениями любого типа передаются/копируюся "по-значению", никаких ссылок и проч. в стандарте нет, есть только значения. ECMAScript весь построен на by-value. Нужно только помнить, что в отношении объектов мы работаем со свойствами по ссылке. Но работа со свойствами объекта и работа с переменными - две большие разницы. ;-) Объекты удаляет сборщик мусора (garbage collector), порядок и алгоритм в руках той или иной реализации языка, например, подробнее о JScript . Для программиста важно контролировать, чтобы объект, который он об-null-ил не зацепился за что-либо, что он не увидел. Иначе сборщик его не затрёт. |
Zeroglif, тут, на самом деле, людей сбивает с толку (тех, кто слышал о Reference Type из ES) само слово "Reference", которое ассоциируется со "ссылкой".
В технической же реализации (и описании в стандарте), то поведение, которое осуществляется для объектов, в общей теории - это передача by-sharing. Там как раз чётко описано отличие от передачи by-reference. |
Ну, давай ещё добавим нечто, чтоб не разгрести было вообще. By-value - самое простое, объяснимое и вполне в рамках.
|
Цитата:
function foo(bar) { bar.a = 2; } var baz = {a: 1}; foo(baz); alert(baz.a); // ...если бы вот тут было 1 |
Kolyaj,
Что есть value переменной, если тип объектный? Стандарт этого не раскрывает, но раскрыли давно разработчики языков, там адрес/указатель/нечто... и это не отменяет того факта, что это нечто копируется, стандарт даже не подразумевает ничего другого. Brendan Eich: - value is a *reference* to the object, not the object itself; - the only thing that's copied is a *reference* (a safe pointer, if you will) that uniquely addresses the object; - v2 = v just copies the reference in v into v2, making both variables denote the same object; Выше по ссылке есть ещё несколько цитат от разрабов языков. |
Цитата:
|
Kolyaj,
Ты прав совершенно в первой части - это ссылка, которая передаётся по значению. Именно эта ссылка и есть значение переменной в отношении объектного типа. Круг замкнулся, переменные by-value всегда. ;-) Работа же с объектом (конкретно с его свойствами) происходит по ссылке из любой точки... но это не работа с переменными, это свойства. |
Цитата:
А остальное - это уже локальная терминология: ES называет by-value, Java называет by-value, Ruby называет by-reference - но во всех них в данном случае используется by-sharing. Здесь фишка завязана ещё на связывание имён и объектов в памяти. Именно из-за того, что присваивание переменной объекта, отвязывает переменную от старого места в памяти, и не получается чистый by-reference. Если бы был by-reference, было бы так: function test(a) { a = {x: 20}; } var b = {x: 10}; test(b); alert(b.x); // 20 Если бы был by-value, было бы так: function test(a) { a.x = 20; } var b = {x: 10}; test(b); alert(b.x); // 10 А вот by-sharing, как раз имеет чёткую разницу от них двоих: function test(a) { a.x = 20; } var b = {x: 10}; test(b); alert(b.x); // 20 function test2(a) { // присваивание связывает "а" с новым объектом // старый остаётся нетронутым a = {x: 30}; } test2(b); alert(b.x); // 20 Но именно это связывание переменной с объектом ничем не отличается, если сделать то же самое вне функции и её параметров: var a = {x: 10}; var b = a; // a и b указывают на одно место в памяти alert(b.x); // 10 b = {x: 20}; // связывание с новым объектом, но не апдейт "а" alert(a.x); // 10 Если в рамках ES, то, конечно, можно и by-value говорить, главное знать, что выше этого стоит определение общей теории. С другой стороны, ECMA-262-3 точно это не описывает. Есть куча ссылок (в том числе, которые приводил ты), где, действительно, говорят by-value, но это, опять же, локальная терминология для by-sharing. Может смущать, что работает оператор ===, который возвращает true для локального формального параметра и внешнего объекта (а он возвращает true в данном случае, если операнды указывают на один и тот же объект): function test(a) { alert(a === b); // true } var b = {x: 10}; test(b); Т.е. здесь тоже с толку может сбивать людей - кажется, что "a" - точно не локальный объект, а как будто бы переданный by-reference. Но, во всяком случае, при разрешении "a" и "b", базовые объекты у них разные - для "а" - объект активации, для "b" - глобальный: aRef = {baseObject: AO(test), propertyName: "a"}; bRef = {baseObject: Global, propertyName: "b"}; Каким-то образом затем [[Get]] получает value aRef и bRef и определяет, что они указывают на один объект. |
Цитата:
|
Цитата:
|
Цитата:
Цитата:
|
В javascript было принято говорить by-val в отношении примитивов, и by-ref в отношении объектов. Это даже в доках было. Eсли ты видел на vingrad-e на меня с моим by-value смотрели как на марсианина. Потом постепенно начали исправлять по аналогии с java в онлайн-доках mdc, уточняя ситуацию с помощью разъяснений dev-ов.
By-value мне кажется очевидней, наиболее точным по отношению к стандарту, где есть только значения, где есть внутренние методы [[Get]], GetValue, промежуточный внутренний тип Reference Type, конкретизация переменных, где значения всегда копируются. И потом этот проще для понимания по сравнению с двойным случаем и уж тем более по сравнению с не используемым в быту by-sharing... Можете включать голосовалку, я за by-value... ;-) |
Цитата:
Цитата:
Цитата:
С другой стороны, технически, тогда обычное присвоение тоже создаёт копию ссылки и ничем не отличает от передачи в качестве параметра функции: var a = {x: 10}; var b = a; aRef = {baseObject: Global, propertyName: "a"}; // address: 0xFF bRef = {baseObject: Global, propertyName: "b"}; // address: 0xFF (скопировался) var a = {x: 20}; aRef = {baseObject: Global, propertyName: "a"}; // address: 0xFА (новый) bRef = {baseObject: Global, propertyName: "b"}; // address: 0xFF (старый) Вот в этом отношении говорить о значении (скопированном value адреса, ссылки) - да, конечно, правильно. И, повторю, тогда вообще нет разницы от присваивания и передачи в функции в качестве формального параметра (или есть, как думаешь?). Но, теоретическая evaluation strategy - остаётся by-sharing, как специально выделенная и обособленная от by-value и by-reference и именно по этому критерию. |
Ты просто на объекте замкнулся, представь, что объект не меняет свойств, почему сразу свойства дёргать внутри функции. Речь ведь о переменной и изменении её значения, а не о свойствах объекта. Если значением переменной не является объект, а только URL до объекта, то почему изменение свойств объекта (отражаемое везде) является аргументом в пользу by-sharing, и тем более by-ref. Меняем ведь не значение переменной. Это ж очевидно.
|
Zeroglif, на самом деле, мы говорим об одном и том же. Даже в статье об evaluation strategy из Википедии в подразделе by-value говорится о нашем случае:
Цитата:
Цитата:
by-value - это правильно (особенно, если учесть, что данную терминологию использует создатель языка). Но обособление by-sharing для этого случая (что означает ровно то же самое - копирование не целиком массивного объекта (как это было бы в Cи в случае by-value), а копирование лёгкой ссылки), мне кажется оправданным - чтобы не путать именно с by-value, когда передался бы объект-бегемот и менялся бы там внутри функции независимо. Хотя, с другой стороны, by-value в Си - это всего лишь одна из реализаций. Но, эта реализация (и её понятие by-value) появилась раньше JS. |
Хорошие цитаты. Особенно "but should not be understood as being call-by-reference". В общем, я сегодня почти поставил для себя в этом вопросе окончательную точку. Только вот разберусь с этим твоим call-by-sharing основательнее...
|
А я, пожалуй, найду время и напишу заметку по этому поводу, чтобы, опять же, ссылаться на неё, а не на вырванные из контекста ответы, если возникнет похожий вопрос. Мотивацией будет этот тред. В общем, будет "by-value" (a.lso k.nown a.s "by-sharing").
|
Dmitry A. Soshnikov,
Пиши, пиши, вот цитаты B.E. со ссылками: ...the property's value is a *reference* to the object, not the object itself. http://groups.google.com/group/mozil...ff6fa9deb204e1 JS is not C++. There is no deep or shallow copy on assignment. Object is a reference type, so v2 = v just copies the reference in v into v2, making both variables denote the same object. http://groups.google.com/group/netsc...dd2121f1fb8424 There is no copy of any object data. The only thing that's copied is a *reference* (a safe pointer, if you will) that uniquely addresses the object. http://groups.google.com/group/netsc...95f5eef93c1734 Just the reference - objects are reference types in JS, as in Java http://groups.google.com/group/netsc...79c0c9f86a6336 Что-то по JScript на винграде есть... liskov-y я прочитал (manual языка), да, это был бы подходящий термин, если бы прижился, там они чётко описывают, что значением переменной является reference на объект. Но раз не прижился, то пиарить не буду, только в качестве экскурса... меня полностью удовлетворяет то, как компактно и точно звучит первая цитата в твоём предыдущем сообщении. |
Цитата:
|
Всем большое спасибо за ответы и ссылки, всё очень понятно и доступно.
|
Ещё один вопрос созрел насчёт удаления объектов.
Пример кода: var objectA = {a:1}; var objectB = {b:1}; objectA.property1 = objectB; Вопрос в следующем: Как правильно обнулить объекты в данном случае и нужно ли их обнулять(может уборщик мусора сам справиться)? Как я понял правильнее было бы вначале objectA.property1 = null потом обнулить объекты но я не совсем уверен нужно ли это. Заранее благодарен. |
Цитата:
for(x in objectA){ delete x; } objectA = null; |
Часовой пояс GMT +3, время: 01:04. |