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 страницы осилил - на каждой по системной ошибке. Резюме - начинающим читать по диагонали (хуже не будет), хорошо знающим - читать по диагонали (чтобы составить мнение о книге и авторе), уже не начинающим, но пока плавающим - лучше не читать. ;-) |
Ниндзюцу, блин :D
Кстати, 80% пишущих на JS, под термином "контекст" (или даже полно - контекст исполнения) понимают this-value (Ниндзя в данном случае тоже использует слово "context", но подразумевает this-value). Да, вот так продвигается неграмотность. Zeroglif, надо выступать в том месте и в то время, где эти вопросы решаются. Польза будет, я думаю. Интересно, Резиг же, вероятно, советовался со многими перед выпуском книги. Он же, вроде, в Мозилле работает (нет?) - ну, посоветовался бы с B.Eich-ом. Цитата:
|
Dmitry A. Soshnikov,
Ресиг давно мозильный javascript евангелист, получает деньги за это... так что... Ты почитай, как евангелист пиарит в книжке конструкцию with(), несколько страниц аж. Я уже до прототипов дошёл, там вообще труба, какая-то очередность присвоения свойств (сначала из prototype, потом из конструктора, поэтому затираются)... там же про то, что свойства объекта статичны!!!, а свойства прототипа live!!! и они bind к экземпляру даже!!! после его создания. Типа своя трактовка непонятного чуда. В общем, вторая его аццкая книга и снова всё внесистемно, по вершкам, нагугленные куски, самопал... первая даже лучше... а ведь годы уже прошли. Цитата:
|
Ему всего-то надо понять reference type, просто разобрать почему:
var obj = { m: function () { return this; } }; alert( obj.m() ); //-> object alert( (obj.m)() ); //-> object alert( (obj.m = obj.m)() ); //-> global |
Так что то я начал сомневаться. В таком варианте: вызов функции func в контексте объекта context — правильная терминология и именование аргумента функции?
function bind(func, context) { return function(arg) { func.call(context, arg); }; } Всегда смущало, что вместо context многие пишут scope — это же не правильно? Или вообще может лучше thisObj называть :) |
Цитата:
Я сталкивался с подобным в немного другом виде: alert( (obj.m || obj.n)() ); //-> global объяснил себе так: раз "obj.m || obj.n" в скобках, то они будут вычисляться и на выходе из скобок будет просто "m" или просто "n", т. е. это тоже самое что: var x = obj.m || obj.n; x(); //-> global Правильно я понял? |
Цитата:
Цитата:
|
Цитата:
- "вызов функции в контексте объекта"; - "контекст исполнения функции"; Но, в принципе говорить о вызове в контексте (именно о вызове) - это нормально, если вы посмотрите на родные доки JavaScript (начиная с 1.3), то в отношении 'apply' и 'call' эта терминология применяется: Цитата:
Цитата:
|
Цитата:
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. |
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
|
Zeroglif, Dmitry A. Soshnikov, спасибо за объяснение.
Получается, что аксессор - это, в понимании интерпретатора, свойство с привязкой к своему контексту и если есть что-то, что заставляет прочитать это свойство (вызвать GetValue), то привязка к контексту теряется и это уже не аксессор? |
Цитата:
var valueOfReferenceType = { base: <базовый объект>, propertyName: <имя свойства> }; Далее, если мы имеем в коде обращение к переменной, в силу вступает алгоритм (и механизм) разрешения имени идентификатора (этой переменной): var foo = 10; alert(foo); На выходе алгоритма разрешения имени - всегда значение типа Reference Type. Т.е. для нашей переменной foo, результатом разрешения имени будет: var fooReference = { base: Global, // т.к. foo - в глобальном объекте propertyName: "foo" }; Главным моментом разрешения имени является именно тот факт, что возвращается объект типа Reference Type, т.е. без получения значения этой переменной. Иными словами, если мы пишем код: foo; Мы получаем "на выходе" - fooRef. И только затем (в примере выше), когда вызывается alert, уже вызывается метод GetValue для fooRef. GetValue вернёт уже значение другого типа (в данном случае Number - 10), но не значение ReferenceType. Псевдокод алгоритма GetValue: function GetValue(fooReference) { var base = GetBase(fooReference); // Global return base.[[Get]](GetPropertyName(fooReference)); // 10 } Так вот, главный момент, касающийся вызова функции - выражение вызова ожидает слева (от скобок вызова) значение типа Reference Type. Если это так, то в качестве this-value будет база этого значения: // в первых скобках - значение типа // Reference Type, т.к. сработал алгоритм // разрешения имён идентификаторов, // базой является obj, именно он будет передан // в качестве this-value (obj.m)(); Если же слева стоит значение не Reference Type (т.е. любого другого типа), то в качестве this-value будет null. Исключение составляет лишь объект активации: в том случае, когда он является базой, также подставляется null. Повторю, что оператор присваивания вызывает GetValue, и, соответственно, на выходе мы получаем значение типа Object, а не Reference Type: // this-value будет null (obj.m = obj.m)(); Надеюсь, всё, более-менее, понятно объяснил. Если есть вопросы, сразу спрашивай, чтобы, пока свежо, полностью понять и разобраться. |
Цитата:
Цитата:
|
Цитата:
Если obj.m, то это MemberExpression.Identifier. Соответственно, для m. Ещё, акксессор (чтобы не путать терминологию) - это выражение доступа к свойству - точка или квадратные скобки, но не сами свойства. Цитата:
Ситуация, когда базовым объектом будет является объект активации, может быть, например, при вызове вложенной функции внутри родительской функции: function foo() { function bar() { return this; } alert(bar()); // равносильно AO.bar() => null.bar(); => Global.bar(); } Декларации функций, переменные и формальные параметры - являются свойствами объекта активации. |
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
В alert-e всё ещё Reference Type, и только потом будет получено значение. Цитата:
Цитата:
А MemberExpression . Identifier, вычисляется по своему алгоритму, где будет отрезолвен MemberExpression (на этапе PrimaryExpression : Identifier), получено его значение, получено значение Identifier, которое эквивалентно <identifier-string>, и возвращено новое значение типа Reference c базой ToObject(значение MemberExpression) и именем свойства ToString(значение Identifier). Спасибо, что поправил ;) Это важные замечания. |
Цитата:
|
Riim,
1) Аксессор (доступ к свойству): выражение.выражение выражение[выражение] 2) Идентификатор: foo Только в этих двух случаях (про скобки и функции хоста опускаю) результатом вычисления выражения будет значение Reference Type. Для аксессора к тому же вообще не важно, что там стоит слева или справа от точки - литерал, идентификатор или сложное выражение, всё равно левая часть станет объектом, правая часть станет строкой. |
Цитата:
MemberExpression . Identifier // получаем значение Reference Type для MemberExpression 1. Evaluate MemberExpression. // получаем значение Result(1) 2. Call GetValue(Result(1)). // вычисляем выражение для Expression, // в нашем случае - для Identifier // это может быть просто строка, // идентификатор, который преобразуется // в строку или выражение 3. Evaluate Expression. // получаем значение, если у нас просто // строка - она и вернётся из GetValue 4. Call GetValue(Result(3)). // преобразование к объекту значения MemberExpression 5. Call ToObject(Result(2)). // преобразование к строке значения Identifier // в нашем случае ничего не меняется 6. Call ToString(Result(4)). // возвращаем новое значение типа Reference // c базой MemberExpression и именем свойства Identifier // с учётом предыдущих преобразований 7. Return a value of type Reference whose base object is Result(5) and whose property name is Result(6). Цитата:
|
Отличная тема, грех не апнуть))
|
Спасибо. Посмеялся. На сколько бывают извращенные программисты.
Теме ап. Полезно, но забивает голову мусором. На счет Ресига. после просмотра кода JQ и парочки "тупых" багов и неудобности его UI-библиотек, его книги пропускаю глазами как только вижу John Re.. |
Цитата:
|
Рэсиг эвангелирует поддержку, а те с поддержки своих доказательств, видимо съехали. Главное тему зарисовать красочно. А я вот нихрена не знаю и всё читаю. Узнал с пары страниц всё новое, интересно пишут программисты. Жалко любой может обвинить и ведущих разработчиков и идеологов. Я знаю что JS разрабатывался 10 дней из "смерти JS видео" - так там на такой основе все будут виноваты. Специально для троллей собирать сделали, для обвинителей ради их правоты пъедестала...
|
xcislav,
лолшто? |
Здравствуйте.
Сразу попрошу оставить "за кадром" тему целесообразности чтения этой книги. Я уже прочёл пару глав, и хочу уже дочитать её. С джавоскриптом я знаком на любительском уровне, и из книги узнаю сейчас много нового. Был бы очень признателен, если кому-то из гуру окажется несложно объяснить мне один момент. Автор несколько раз пишет, и подчёркивает, что функции являются объектами высшего порядка. Как следует понимать слова "высшего порядка"? В смысле, что они в высшей степени являются объектами? Или в смысле, что существуют разные порядки объектов - высшие, низшие, средние, ещё какие-нибудь? Заранее благодарю. |
Поскольку всем гуру оказалось сложно :) я покопался в интернете, и вроде понял смысл слов "высшего порядка". На случай, если кому-то ещё тоже это оказалось интересным, напишу, что я выяснил. А гуры, если надо, поправят.
Итак, нету каких-то разных порядков объектов, типа высший, низший, или ещё какой-то. И первое моё предположение, что смысл этих слов просто "в высшей степени объекты" тоже неверен. А дело вот в чём. Некоторые языки программирования позволяют передавать объекты в функции (методы) в качестве аргументов, и возвращать объекты из функций (методов) в качестве возвращаемых значений. Некоторые другие языки программирования (видимо) этого не позволяют. Один какой-то англо-язычный дядя, писав про какой-то язык программирования, желая подчеркнуть, что этот язык позволяет делать с объектами то, что я написал, выразился образно, сравнив объекты в этом языке с гражданами высшего класса, типа аристократами (first class citizen). Другие дяди это подхватили, и так родился термин "объекты первого класса" или "объекты высшего класса". Это означает, что эти объекты можно передавать в качестве параметров, и получать в качестве возвращаемых значений. Позднее, этот же термин, распространился и на функции: "функции первого класса", "функции высшего порядка", и т.п. Это, опять же, означает, что функции в обсуждаемом языке могут быть переданы в другие функции в качестве аргументов, и возвращены из них в качестве возвращаемых значений. Добавлю, заодно, мои впечатления о книге вообще. Прежде всего, хочу отметить, что книга написана очень хорошим языком (я читаю на русском). Читается легко. Не в том смысле, что всё разжёвывается, а в том, что написана не сухим языком учебника, а живым повествовательным языком, который читается как роман. Мне лично это очень нравится. От учебников меня сразу клонит в сон. По поводу того, кому она будет полезна. Полезна она будет таким как я. Я в программировании самоучка, но программирую уже очень давно. Программировал на разных других языках. Яваскрипт специально никогда не изучал. Когда понадобилось написать что-то простенькое, ознакомился с синтаксисом, и стал писать, подглядывая в сети, что как делается. Теперь решил углубиться в него посерьёзней. И вот эта книга для этой цели - самое то. Я часто смотрел на чужие скрипты как баран на новые ворота, не понимая, что тут делают, зачем, почему, как? Теперь мне многое из этого становится понятно. Тем, кто вообще не знаком с яваскриптом, или вообще не знаком с программированием, эта книга будет, конечно, совершенно бесполезна, ибо она будет совсем непонятна. |
Часовой пояс GMT +3, время: 00:43. |