Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 24.07.2012, 12:16
Интересующийся
Отправить личное сообщение для dump Посмотреть профиль Найти все сообщения от dump
 
Регистрация: 14.07.2011
Сообщений: 26

Почему некоторые операторы возвращают значения, а не ссылки?
Вот код:

Код:
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
(foo.bar, foo.bar)(); // 1
Почему он в последовательно выводит 22121, хотя должен бы 22222? Вот здесь - http://dmitrysoshnikov.com/ecmascrip...#tip-reference сказано, что это из-за того, что если вызывается значение не ссылочного типа, то this равно null, а следовательно global. Но я не могу понять, почему оператор присваивания возвращает значение не типа reference? И почему та же запятая, возвращает значение, а не ссылку? Ведь функция - это ссылочный тип, как и любой другой объект, а значит (foo.bar = foo.bar)(); должно вызвать по ссылке и установить this в значение foo...
Ответить с цитированием
  #2 (permalink)  
Старый 24.07.2012, 12:42
Аватар для vasa_c
Профессор
Отправить личное сообщение для vasa_c Посмотреть профиль Найти все сообщения от vasa_c
 
Регистрация: 12.03.2008
Сообщений: 183

нет никакого типа reference. он только теоретически в ECMA.
foo.bar = foo.bar возвращает функцию. а функция в JS не привязана ни к какому объекту.
Ответить с цитированием
  #3 (permalink)  
Старый 24.07.2012, 14:18
Интересующийся
Отправить личное сообщение для dump Посмотреть профиль Найти все сообщения от dump
 
Регистрация: 14.07.2011
Сообщений: 26

Цитата:
а функция в JS не привязана ни к какому объекту.
Но в последних трёх примерах она привязана к объекту foo. Но значение this там не такое однозначное...
Ответить с цитированием
  #4 (permalink)  
Старый 24.07.2012, 15:44
что-то знаю
Отправить личное сообщение для devote Посмотреть профиль Найти все сообщения от devote
 
Регистрация: 24.05.2009
Сообщений: 5,176

Сообщение от dump
Но в последних трёх примерах она привязана к объекту foo.
и где же вы там привязку нашли?
(foo.bar = foo.bar)();
это всеравно что вызвать так:
var a = foo.bar; // привязка объекта к безымянной переменной
a(); // вызов безымянной переменной

и это:
(foo.bar, foo.bar)();
тоже что и:
foo.bar; // просто бесмысленая конструкция, ничего совсем не делает
var a = foo.bar; // далее привязка объекта к безымянной переменной
a(); // вызов безымянной переменной
__________________
хм Russians say завтра but завтра doesn't mean "tomorrow" it just means "not today."
HTML5 history API рассширение для браузеров не поддерживающих pushState, replaceState
QSA CSS3 Selector Engine
Ответить с цитированием
  #5 (permalink)  
Старый 24.07.2012, 16:16
Профессор
Отправить личное сообщение для oneguy Посмотреть профиль Найти все сообщения от oneguy
 
Регистрация: 31.05.2012
Сообщений: 396

Сообщение от dump
Почему он в последовательно выводит 22121, хотя должен бы 22222?
Вообще-то он выводит 22111. Я уже писал пост по этому поводу. Почему оператор ++ генерирует искючение, а не NaN в случае со строкой?
Reference - это тип спецификации, отличный от языкового типа объект. Только операторы . и [], а также () в редких случаях возвращают значение Reference, все остальные операторы, в том числе ||, = и запятая всегда возвращают языковое значение.
Ответить с цитированием
  #6 (permalink)  
Старый 24.07.2012, 17:22
Интересующийся
Отправить личное сообщение для dump Посмотреть профиль Найти все сообщения от dump
 
Регистрация: 14.07.2011
Сообщений: 26

Т.е. получается, что оператор (foo.bar, foo.bar) образно говоря проходит по ссылке foo.bar, извлекает объект(функцию) bar и представляет её в качестве значения в отдельной области памяти? Тогда почему в таком случае следующий код:
Код:
o={x:2,y:3};
b=(false , o);
b.x=7;
alert(o.x);
выведет 7? Он же по идее должен вывести 2, потому что оператор запятая возвратит значение, что приведёт к копированию всего объекта(а не его ссылки), следовательно b в станет не ссылкой, а значением. Но этого не происходит, запятая возвращает ссылку, а не сам объект, это видно если поменять свойство x. Тогда почему же (foo.bar, foo.bar) возвращает само значение?

Цитата:
Вообще-то он выводит 22111.
У меня он выводит 22121. Почему так? Какой программой для запуска пользуетесь?
Ответить с цитированием
  #7 (permalink)  
Старый 24.07.2012, 18:06
что-то знаю
Отправить личное сообщение для devote Посмотреть профиль Найти все сообщения от devote
 
Регистрация: 24.05.2009
Сообщений: 5,176

Сообщение от dump
огда почему же (foo.bar, foo.bar) возвращает само значение?
а кто сказал что оно значение возвращает? оно так же возвращает ссылку на метод(функцию), просто контекст у функции теряется.
__________________
хм Russians say завтра but завтра doesn't mean "tomorrow" it just means "not today."
HTML5 history API рассширение для браузеров не поддерживающих pushState, replaceState
QSA CSS3 Selector Engine
Ответить с цитированием
  #8 (permalink)  
Старый 24.07.2012, 23:01
Профессор
Отправить личное сообщение для oneguy Посмотреть профиль Найти все сообщения от oneguy
 
Регистрация: 31.05.2012
Сообщений: 396

Здесь возникает путаница в понятиях. Есть 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) и возвращает.
Сообщение от dump
У меня он выводит 22121. Почему так? Какой программой для запуска пользуетесь?
Запускал на тестовой странице, проверял в IE, Firefox, Chrome. А вы какой программой пользуетесь?

Последний раз редактировалось oneguy, 24.07.2012 в 23:11.
Ответить с цитированием
  #9 (permalink)  
Старый 25.07.2012, 05:44
что-то знаю
Отправить личное сообщение для devote Посмотреть профиль Найти все сообщения от devote
 
Регистрация: 24.05.2009
Сообщений: 5,176

Сообщение от oneguy
(false || foo.bar)(); // 2 (у меня 1)
опера выводит двойку
__________________
хм Russians say завтра but завтра doesn't mean "tomorrow" it just means "not today."
HTML5 history API рассширение для браузеров не поддерживающих pushState, replaceState
QSA CSS3 Selector Engine
Ответить с цитированием
  #10 (permalink)  
Старый 25.07.2012, 16:17
Профессор
Отправить личное сообщение для oneguy Посмотреть профиль Найти все сообщения от oneguy
 
Регистрация: 31.05.2012
Сообщений: 396

Сообщение от devote
опера выводит двойку
Ну и дура
По спецификации там должно быть 1.
По-видимому, Опера при выполении операторов || и && не делает разыменование значения правого операнда перед возращением, хотя это неправильное поведение с точки зрения спецификации.

Последний раз редактировалось oneguy, 25.07.2012 в 16:25.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
почему нельзя объявить переменную и в ней использовать совмещенные операторы?!! alexben Общие вопросы Javascript 23 13.02.2012 00:32
Некоторые клавиши возвращают одинаковый код: что делать? Cooskon Events/DOM/Window 2 20.10.2010 11:20
Почему значения св-в undefined? Bakuryu Events/DOM/Window 4 18.07.2008 19:49