Почему некоторые операторы возвращают значения, а не ссылки?
Вот код:
Код:
v=1; |
нет никакого типа reference. он только теоретически в ECMA.
foo.bar = foo.bar возвращает функцию. а функция в JS не привязана ни к какому объекту. |
Цитата:
|
Цитата:
(foo.bar = foo.bar)();это всеравно что вызвать так: var a = foo.bar; // привязка объекта к безымянной переменной a(); // вызов безымянной переменной и это: (foo.bar, foo.bar)();тоже что и: foo.bar; // просто бесмысленая конструкция, ничего совсем не делает var a = foo.bar; // далее привязка объекта к безымянной переменной a(); // вызов безымянной переменной |
Цитата:
Reference - это тип спецификации, отличный от языкового типа объект. Только операторы . и [], а также () в редких случаях возвращают значение Reference, все остальные операторы, в том числе ||, = и запятая всегда возвращают языковое значение. |
Т.е. получается, что оператор (foo.bar, foo.bar) образно говоря проходит по ссылке foo.bar, извлекает объект(функцию) bar и представляет её в качестве значения в отдельной области памяти? Тогда почему в таком случае следующий код:
Код:
o={x:2,y:3}; Цитата:
|
Цитата:
|
Здесь возникает путаница в понятиях. Есть 6 языковых типов, среди которых объект, а есть тип спецификации Reference. Значения типа Reference часто называют ссылками, и значения типа Object часто называют ссылками на объект. Хотя на самом деле Object и Reference - это два совершенно разных типа. Значение переменной и свойства объекта всегда принадлежит языковому типу и не может принадлежать типу Reference.
Значения Reference состоят из 2-х компонент: базы и имени (ещё и флага Strict, но в большинстве случаев его можно не рассматривать). Значение Object являются некоторым внутренним значением (адрес, идентификатор), с помощью которого можно однозначно определить структуру данных, состоящую из свойств, в памяти. Часто называют объектами сами такие структуры данных. o={x:2,y:3}; b=(false , o); // в данном случае b имеет тип Object, значение переменной никогда не может иметь тип Reference b.x=7; alert(o.x); v=1; var foo = {bar: function () {alert(this.v);}, v:2}; foo.bar(); // 2 (foo.bar)(); // 2 (foo.bar = foo.bar)(); // 1 (false || foo.bar)(); // 2 (у меня 1) (foo.bar, foo.bar)(); // 1 В данном случае выражение foo.bar возвращает значение Reference с базой, равной значению переменной foo, и именем "bar". Оператор запятая, если правый операнд возвращает значение Reference, его разыменовывает, и возвращает разыменованное значение. В данном случае это значение типа Reference разыменовывается в функцию с кодом { alert(this.v) }, точнее ссылку на эту функцию и выражение (foo.bar, foo.bar) её (ссылку на функцию, значение типа Object) и возвращает. Цитата:
|
Цитата:
|
Цитата:
По спецификации там должно быть 1. По-видимому, Опера при выполении операторов || и && не делает разыменование значения правого операнда перед возращением, хотя это неправильное поведение с точки зрения спецификации. |
Цитата:
|
Да, вот ваша писулька :) http://es5.javascript.ru/x11.html#x11.11
Семантика, вычисление LogicalORExpression : LogicalORExpression || LogicalANDExpression, шаг 5. |
Цитата:
А во вторых скажу сразу что Опера лучше других браузеров поддерживает ECMAScript, советую провести тесты. Хотя тут: http://test262.ecmascript.org/ хотя я и не буду утверждать того что опера права, но и пока четких слов не увижу по вычислению выражений в скобках, я буду нейтрален, и к опере и к другим. |
Цитата:
Цитата:
|
Причина этих разногласий между браузерами в вычислении оператора ||.
Выражение false || foo.bar в Опере возвращает значение Reference с базой foo и именем "bar", в остальных браузерах - функцию foo.bar. Поэтому при вызове результата этого выражения как функции в Опере значение foo передаётся в качестве аргумента this, а в других браузерах - глобальный объект (или undefined в строгом режиме). Та же особенность Оперы проявляется в следующем коде: var a=1; (0||a)=2; // во всех браузерах, кроме Оперы что-то типа ReferenceError: invalid assignment left-hand side alert(a); // в Опере выдаёт 2 |
oneguy,
ясно, поинтересуюсь на эту тему потом. |
Часовой пояс GMT +3, время: 12:30. |