Javascript-форум (https://javascript.ru/forum/)
-   Учебные материалы (https://javascript.ru/forum/study/)
-   -   Secrets of the Javascript Ninja (https://javascript.ru/forum/study/5724-secrets-javascript-ninja.html)

Zeroglif 01.11.2009 01:21

Secrets of the Javascript Ninja
 
Читали последнюю книжку от Ресига? Только открыл и уже:

To start, it's important to realize what that the function context represents: The object within which the function is being executed. For example, defining a function within an object structure will ensure that its context always refers to that object - unless otherwise overwritten... However, what about a function that isn't explicitly declared as a property of an object? Then the function's context refers to the global object.

Ну, то что наш ниндзя прибил точный и важнейший термин "контекст" его народным определением ещё можно понять и даже простить, если бы речь шла о вызове функции "в контексте чего-либо". Но он пишет об определении/объявлении функции в связи с чем "context always refers to that object", не о вызове. Типичная избитая ошибка javascript-ньюбов. Ещё 3 страницы осилил - на каждой по системной ошибке.

Резюме - начинающим читать по диагонали (хуже не будет), хорошо знающим - читать по диагонали (чтобы составить мнение о книге и авторе), уже не начинающим, но пока плавающим - лучше не читать. ;-)

Dmitry A. Soshnikov 01.11.2009 01:58

Ниндзюцу, блин :D

Кстати, 80% пишущих на JS, под термином "контекст" (или даже полно - контекст исполнения) понимают this-value (Ниндзя в данном случае тоже использует слово "context", но подразумевает this-value).

Да, вот так продвигается неграмотность. Zeroglif, надо выступать в том месте и в то время, где эти вопросы решаются. Польза будет, я думаю.

Интересно, Резиг же, вероятно, советовался со многими перед выпуском книги. Он же, вроде, в Мозилле работает (нет?) - ну, посоветовался бы с B.Eich-ом.

Цитата:

Сообщение от Википедия
Джон Резиг (англ. John Resig) — JavaScript евангелист в Mozilla Corporation.

А кто ему этот титул присвоил? Или он самозванно? ;) Или это Википедия так балуется?

Zeroglif 01.11.2009 02:29

Dmitry A. Soshnikov,

Ресиг давно мозильный javascript евангелист, получает деньги за это... так что... Ты почитай, как евангелист пиарит в книжке конструкцию with(), несколько страниц аж. Я уже до прототипов дошёл, там вообще труба, какая-то очередность присвоения свойств (сначала из prototype, потом из конструктора, поэтому затираются)... там же про то, что свойства объекта статичны!!!, а свойства прототипа live!!! и они bind к экземпляру даже!!! после его создания. Типа своя трактовка непонятного чуда.

В общем, вторая его аццкая книга и снова всё внесистемно, по вершкам, нагугленные куски, самопал... первая даже лучше... а ведь годы уже прошли.

Цитата:

Кстати, 80% пишущих на JS
Угу. "Вызов в контексте" нормальные люди используют, подразумевая 'this'. Вызов! Он говорит не про вызов, а про определение функции, это чушь.

Zeroglif 01.11.2009 02:32

Ему всего-то надо понять reference type, просто разобрать почему:
var obj = { m: function () { return this; } };

alert( obj.m() );           //-> object
alert( (obj.m)() );         //-> object
alert( (obj.m = obj.m)() ); //-> global

Octane 01.11.2009 03:27

Так что то я начал сомневаться. В таком варианте: вызов функции func в контексте объекта context — правильная терминология и именование аргумента функции?
function bind(func, context) {
    return function(arg) {
        func.call(context, arg);
   };
}

Всегда смущало, что вместо context многие пишут scope — это же не правильно? Или вообще может лучше thisObj называть :)

Riim 01.11.2009 03:28

Цитата:

Сообщение от Zeroglif
просто разобрать почему

а почему? :)

Я сталкивался с подобным в немного другом виде:
alert( (obj.m || obj.n)() ); //-> global


объяснил себе так: раз "obj.m || obj.n" в скобках, то они будут вычисляться и на выходе из скобок будет просто "m" или просто "n", т. е. это тоже самое что:
var x = obj.m || obj.n;
x(); //-> global


Правильно я понял?

Riim 01.11.2009 03:37

Цитата:

Сообщение от Octane
что вместо context многие пишут scope

т. е. получается:
Цитата:

вызов функции func в scope объекта context
разве у объектов есть scope? Он же у функций.

Zeroglif 01.11.2009 12:21

Цитата:

Сообщение от Octane
Всегда смущало, что вместо context многие пишут scope — это же не правильно? Или вообще может лучше thisObj называть

'thisObj' было бы идеально, тогда не будут перекрещиваться термины, обозначающие разные вещи:

- "вызов функции в контексте объекта";
- "контекст исполнения функции";

Но, в принципе говорить о вызове в контексте (именно о вызове) - это нормально, если вы посмотрите на родные доки JavaScript (начиная с 1.3), то в отношении 'apply' и 'call' эта терминология применяется:
Цитата:

Allows you to apply a method of another object in the context of a different object (the calling object).
что в переводе на формальный язык ES расшифровывается с точки зрения вызова прямо там же:
Цитата:

assign a different this object
Отсюда, говоря о "вызове в контексте объекта" мы однозначно говорим об определении 'this'...

Zeroglif 01.11.2009 12:52

Цитата:

Сообщение от Riim
Правильно я понял?

Не совсем, но близко. Согласно Дж.Ресигу "определение функции в качестве метода объекта гарантирует, что вызов всегда будет в контексте этого объекта". Это само собой глупость, так как 'this' определяется 'caller'-ом, попросту говоря тем, как записана форма вызова, а не тем как и где определена функция. Обычную объявленную функцию уже с ходу можно вызывать по-разному, меняя 'this':

function f() {
    alert( this );
}
f();
f.prototype.constructor();

Не говоря уже о том, что её можно передавать, присваивать и т.д.

При вызове интерпретатор определяет, что стоит слева от "оператора вызова", от скобок. Вычисляется выражение и определяется тип вычисленного промежуточного результата... а это одно из двух - Reference type или не Reference type. Если там (слева) стоит идентификатор (foo) или аксессор (foo.x или foo['x']), то мы имеем дело с Reference type, а значит определённый объект, "владелец" метода в момент вызова, станет значением 'this' (activation object не в счёт). Если там любое другое выражение, например:

(foo.x || foo.y)();
(foo.x, foo.y)();
(function () {})();


то это не Reference type, значением 'this' станет null->global.

Dmitry A. Soshnikov 01.11.2009 13:41

Цитата:

Сообщение от Zeroglif
Ты почитай, как евангелист пиарит

Ага, полистаю.

Цитата:

Сообщение от Zeroglif
alert( (obj.m)() ); //-> object
alert( (obj.m = obj.m)() ); //-> global

Да, я подробней покажу, всем остальным, кому интересно:

Цитата:

Сообщение от 11.1.6 The Grouping Operator
NOTE
This algorithm does not apply GetValue to Result(1). The principal motivation for this is so that
operators such as delete and typeof may be applied to parenthesised expressions.

Поэтому, в первом случае после оператора группировки, у нас всё ещё Reference Type, а во втором случае, оператор присваивания (как и другие - "ИЛИ", или "запятая"), вызовет для AssignmentExpression GetValue, который, вызвав в свою очередь [[Get]], вернёт уже значение свойства, т.е. функцию, и будет уже не тип Reference. Для выражения вызова, это означает использовать Global в качестве this-value.

Цитата:

Сообщение от 11.13.1 Simple Assignment ( = )
2. Evaluate AssignmentExpression.
3. Call GetValue(Result(2)).

Цитата:

Сообщение от Octane
Всегда смущало, что вместо context многие пишут scope — это же не правильно?

С точки зрения Scope и [[Scope]] в ES (и основной точки зрения - понимания этих сущностей) - конечно, это неправильно. Этим, кстати, грешит фреймворк ExtJS, который везде для handler-ов событий указывает вторым параметром - scope: this, имея в виду thisValue.


Часовой пояс GMT +3, время: 14:41.