Pull to refresh
1
0
Dmitry Soshnikov @dsCode

User

Send message
У него включена премодерация комментов, он публикует только слащавые комменты, которые ему нравятся, в которых говорится, «какой этот чел крутой, ой, какой хороший тест придумал». А то, «что по уровню сложности этот quiz на слабую троечку, в отличии от теста kangax-а, который, объективно, сложнее — на 4» — это надо игнорить и не показывать в комментах". Дешёвый PR на «хороших» комментах — признак дилетантизма (не важно, сколько у него на счет книг и т.д.).

И вообще, кто включает модерацию комментов не только ради избавления от спама и троллинга, а для выбора, что публиковать, а что нет связанное с темой и по делу — дилетант и трус.
Привет, Юра, вэлкам ту русские IT-просторы ;)
Почти (но ход мысли хороший).

На самом деле правило одно:

Определяется, что стоит слева от выражения вызова (грубо, от скобок — ( )). Главное, что интересует — это тип вычисленного промежуточного значения, который может быть либо Reference type, либо не Reference type.

Первый случай (Reference type) возможен, когда слева стоит либо идентификатор (identifier), либо выражение доступа к свойству (property accessor). Второй случай (не Reference type) — всё остальное.

Далее, у этого значения Reference type берется базовый объект (base), и именно он будет использован в качестве значения this (Если нужно пояснить про Reference type, скажите).

В случае же, когда значение — не Reference type, this получает значение null. Но, т.к. null особого смысла для this не несёт, автоматом подставляется глобальный объект.

Поэтому:

var foo = {bar: function () {}};

foo.bar(); // Reference type (accessor), база - foo
(foo.bar)(); // тоже, Reference type, база - foo, используется оператор группировки

function test() {}

test(); // тоже Reference type (identifier), база - global
this.test(); // равносильно предыдущему, база видна явно

А вот здесь, оператор присваивания (в отличие от оператора группировки в примере выше), вызовет GetValue, и в итоге будет уже не Reference type, а Function:

(foo.bar = foo.bar)(); // не Reference type, this = null => global

Аналогично другие выражения (всё тоже — не Reference type, поэтому this в итоге будет global):

(foo.bar || foo.bar)();
(foo.bra, foo.bra)();
(function () {})();

По поводу with: будет Reference type с базой — объект with добавленный к scope chain; поэтому не global.

Есть одно исключение, когда будет получен Reference type (и даже база будет не global, как выше в случае с test), но всё же this будет global. Это в том случае, когда базой будет является объект активации (activation object). Если упрощенно, это объект контекста функции, в котором хранятся вложенные функции, переменные и параметры:

function foo() {
  function bar() { alert(this); }
  bar(); // global
}

При вызове bar будет определено значение Reference type (т.к. это идентификатор), но с базой — объект активации контекста функции foo. Т.е. эта запись образно равносильна:

AO.bar();

где АO — объект активации контекста foo.

Так вот для этого случае в стандарте тоже прописано — использовать в качестве this не объект активации (базу), а null, и, как следствие, global.
> Если точки нет или используется какое-то хитрое выражение типа (x=«q».toString)(), то он равен глобальному объекту

Ага ;) Самое сбиваеющее с толку, если не знать, как точно это работает, может быть:

foo.prototype.constructor(); // foo.prototype
(foo.prototype.constructor)(); // тоже foo.prototype

// но
(foo.prototype.constructor = foo.prototype.constructor)(); // global


Так же, не всегда при вызове, как функции (т.е. «нет» слева от точки «ничего»), this будет global (например, при использовании with):

with ({foo: function () {alert(this);}}) {
  foo(); // объект with, добавленный к scope chain, но не global
}
> foo() вернёт window, foo.prototype.constructor() вернёт foo.prototype, который не равен window.

А почему именно так?
Кому интересно, здесь ещё дополнительные вопросы есть: groups.google.ru/group/comp.lang.javascript/browse_thread/thread/2e6e542c9e02965c?hl=en

Некоторые с небольшими дополнениями:

1. Каков результат?

var a = 1, b = 3;
a
++
b;

a) a = 2, b = 3
b) a = 1, b = 4
c) Syntax error

2. Каков результат?

var x;
foreach (x in {})
{
  // ...
}

1) ReferenceError
2) SyntaxError
3) Iterate over all values of object properties.
4) Possibly no error

var x;
foreach (x in {}) {
  // ...
}

1) TypeError
2) SyntaxError
3) Iterate over all values of object properties.
4) Possibly no error
Очень хороший ход мысли. Чтобы сразу не раскрывать ответы (может, кто-нибудь ещё захочет попытать «удачу»), скажу: на некоторые вопросы Вы дали совершенно правильные ответы, на некоторые — совершенно неправильные.
(блин, как отключить в настройках этот гребанный Ctrt-Enter?)

1. What will 1..z provide:

a) SyntaxError
b) New Range object (equivalent to new Range(1, 'z')) including all numbers and letters
c) undefined
d) Error of Range object (incompatible types for range: number and string)
e) ReferenceError 'z' is not defined

2. What the result of 100['toString']['length']:

a) 100
b) 3
c) 1
d) 8
d) SyntaxError

3. What the result of:

function foo() {
  return this;
}
 
alert(foo === foo.prototype.constructor); // true
alert(foo() === foo.prototype.constructor()); // ?

a) true
b) false
c) depends on implementation
Ок, ещё три вопроса:

Ну, кстати сказать, Флэнэган абсолютно здесь не при чём (особенно в тегах к посту) ;) Тест придумал kangax (русский парень, кстати), он же — один из core-dev-ов Prototype.js.
> «зачем?»

Никто не предлагает, я ж отметил, что на практике вряд ли кто-то так будет делать. Вопрос в теории и понимании.
> а какая по сути раница?

В реализации, в изменении значений. В грамотности. В незаблуждении.

Однако, стоит сказать, что в Ruby, например, называют это (при той же реализации) — по ссылке (вероятно, по той же причине ;)).

> присваивание = изменения адреса ссылки, а изменение переменной = изменение объекта по ссылке

Да, это и есть передача «по значение (адреса)» или «по разделению», но не «по ссылке».

> помоему такие штуки в других языках называются указатели?

Да (с определёнными уточнениями). Для С++ из boost-a больше по смыслу подойдёт shared_ptr.
Да, в Java (как в ECMAscript, да и как во многих языках) принята терминология «по значению» (если более полно — особый случай по значению, когда значением является адрес).
> Мне больше всего нравиться вот этот пример: a[[[[«item»]]]]==a[«item»]; // результат true

Можно сделать, чтобы не было true ;) Хотя, на практике, вряд ли кто-то так будет делать. Здесь всё завязано на методы .toString и .valueOf: измените их в прототипе Array-я, и получите другой результат.
Поразительно. Шестеро человек, которые вас плюсанули — так и не понимают, как работает JS. При это ещё и меня минусанули :D Деградация Хабра.

Ещё раз: объекты в JS не передаются по ссылке, а передаются по особому виду «по значению», либо, так же известному как, «по разделению».
Значение undefined (по словам B.Eich) было введено для обособления инициализирующего значения переменных, либо, когда свойство не может быть найдено в базовом объекте.

Значение же null, в отличие от undefined, по смыслу больше связано с объектами, означает пустую ссылку на объект, возможно, зарезервированное место под объект.

Хотя, на мой взгляд, можно было выбрать что-то одно ;)

Здесь есть одна особенность и связана она с оператором typeof, который часто может сбивать с толку, если не знать, как он работает. В большей мере это относится к значению null: несмотря на то, что тип null-a, по определению, Null, typeof для этого значения выдаёт «object»:
alert(typeof null); // «object»

А дело в том, что оператор typeof возвращает строковое значение, взятое из жёстко закреплённой таблицы, где прописано: «для null — возвращать „object“.

Причины этого в стандарте не разъясняются, однако B. Eich (создатель Javascript) отмечал, что null, в отличии от undefined (который означает неопределённость, „нет значения“), используется в большинстве случаев там, где фигурируют объекты, т.е. является некой сущностью, тесно связанной с объектами (конкретно, означающей нулевую ссылку на объект, „пустышку“, возможно, зарезервировавшую место для будущих целей). Но, в некоторых черновиках (например, в невышедшем ECMAscript4 aka Javascript 2.0), был заведён документ, где данный „феномен“ описан, как обычный баг. Также, данный баг поднимался в одном из баг-треккеров, в котором B. Eich также участвовал; в итоге было решено оставить typeof null, как есть, т.е. „object“, хотя сам стандарт ECMA-262-3 описывает тип null-a, как Null.

javascript.ru/blog/Dmitry-A.-Soshnikov/Tonkosti-ECMA-262-3.-CHast-7.-OOP.#tipy-dannyh
> Объекты в JS передаются по ссылке

«По разделению» (либо по особому виду «по значению»): javascript.ru/blog/dmitry-a.-soshnikov/tonkosti-ecma-262-3.-chast-8.-strategiya-peredachi-parametrov-funkciu.

Переменные «разделяют» (share) один объект. Но если одной из этих переменных присвоить другое значение, это не значит, что все остальные переменные начнут ссылаться на этот новый объект, как было бы при передаче «по ссылке».
> в отличии от undefined где значения по сути нет

Значение undefined есть ;) Свойство undefined глобального объекта имеет значение undefined.
Да, здорово, после того, как прошёл всю вдоль и поперёк Tiberium Wars (которая, кстати, тоже — очень крутая), вернулся к первой C&C — и тоже снова прошёл всю за GDI и NOD; а ведь, когда-то, после школы играл =) До C&C была ещё Dune (The battle for Arrakis) — хоть менее динамичная, чем C&C, но всё равно, тоже классная стратегия.
Какой старый топик Вы подняли, полугодичной давности =)

Это читается следующим образом (позволю процитировать себя же):

… из примитива 1 создаётся wrapper-объект new Number(1) и у этого wrapper-a вызывается унаследованный метод .toString(). Почему унаследованный? Потому, что объекты в ECMAscript могут иметь собственные (own) свойства, а wrapper-объект, в данном случае, не имеет собственного метода .toString(), соответственно, он наследует его от прототипа, на который, если ничего не менялось, указывает Number.prototype

Обратите внимание, две точки в примере выше — это не ошибка, просто первая точка распознаётся как отделение дробной части числа, а вторая — уже, как выражение доступа к свойству.

Подробней: javascript.ru/blog/Dmitry-A.-Soshnikov/Tonkosti-ECMA-262-3.-CHast-7.-OOP.#nasledovanie

А лучше статью по ссылке прочесть полностью.

Information

Rating
Does not participate
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity