хитросплетения Global,контекст,this,Reference
Не въезжаю в стандарт, может кто поможет:
Вот почему так получается : function al(o){document.write(o,'<br>')} // для html function al(o){WScript.Echo(o)} ; // для WSH for (var x in this) al([[x]]) // Здесь Ошибка после распечатки первого значения свойства Глобального объекта (или this, не знаю - совпадут ли они ...) // Ошибка выполнения Microsoft JScript: Предполагается наличие объекта (function qq() {})(); // - вызывает ошибку в for in см выше, если строчку закоментировать, или сделать так v=(function qq() {})() , то ошибки нет ! // даже так (function qq() {return {}})() , т.е. вроде как я возвращаю обхект в качестве свойства, но все равно возникает та же ошибка в for in выше (1); // - та же ошибка в for in 1 ;// - не вызывает ошибки, т.е. вроде как свойствами глобального объекта могут быть примитивные значения . а не только объекты ?! Если кто понимает хитросплетения Global,контекст,this,Reference (в стандарте) , объясните, плз, понятными словами , я пока никак не могу въехать. |
Точку с запятой надо ставить после al([[x]]).
пысы: "Хитросплетения Global,контекст,this,Reference" понимаю, но желательно получить более конкретный вопрос. ;) |
2 Zeroglif > на точку с зпт я - то и не подумал. В этом-то собствно и была причина непоняток.
Вот правда еще есть - ведь все реализации обязаны делать расширяемыми свойства всех своих объектов в том числе и объектов среды типа WScript? Или я не правильно понимаю? Но MS почему-то сделал this.WScript не могущим добавлять новые /переопределять существующие свойства у этог объекта. Как такое понимать ? |
Цитата:
|
Вот еще вопрос :
function al(o){document.write(o,'<br>')} ; for (var x in this) {al([[x]]) } ; // здесь будет function Person() { al("qqq") } ; function Person() { al("zxc") } ; ///* var Person = function () {al("123")}; // */ function Person() { al("qqq") } ; al(Person) ; // Здесь распечатается function () {al("123")} Person() ; // 123 здесь вызовется, соответствующая var Person=function Почему глобальный объект получает в качестве свойства Person то , которое в строке function Person() ... , а не которое в строке var Person = function ... ? |
потому что вы переопределили Person, т.е. объявили еще раз эту функцию, но другим способом.
|
twolf,
я тоже так подумал сперва.но это не так. как вы объясните такой код, тогда function al(o){document.write(o,'<br>')} ; al(Person) ; var Person = function () {al("123")}; function Person() { al("zxc") } ; al(Person) ; как видите второй вывод показываете первую функцию, а первый вывод показывает вторую функцию но с первым выводом понятно.он показывает именованную функцию, поэтому успешно срабатвает до ее определения. PS я так подозреваю, что сперва в глобальную область видимости пихаются именованные функции, и лиш затем по порядку анонимные.в свете такой теории, становится понятно почему эти два примера так работают |
2 twolf ,Gvozd> Да я подправил предыдущий пост
|
походу мои измышления верны только для общего контекста
то есть достаточно обернуть любой из кодов выше просто в фигурные скобочки, для смены контекста, и уже будет работать нормальная логика, с переопределением все, что я сейчас написал было результатом моих размышлений, а не точным знанием |
Цитата:
|
Цитата:
|
2 Gvozd >
Насчет анонимных функций как-то еще нужно проверить ... И еще - ведь можно сделать var Person = function PPP ... // - результат не изменится !! PS . Что-то не получается меня со скобочками , опубликуйте пример, плз. |
читаем тут. http://javascript.ru/tutorial/basic/...aniie-funktsii
Gvozd, в вашем примере сначала выводится person который определен с помощью function(виден везде), а var Person еще не определен. После определения var Person заменяется соответствующая функция Person, и выводится новое значение |
function al(o){document.write(o,'<br>')} ; al(Person) ;//здесь будет указана именованая функция.та, которая была объявлена последней function Person() { al("zxc") } ; al(Person) ;// та же ботва var Person = function () {al("123")}; al(Person) ;//опаньки.появилась анонимная.ее и пишем function Person() { al("qqq") } ; al(Person) ; //та же ботва al('-----------------') ; { //создали новый контекст исполнения al(Person_) ;//нету еще никакой функции function Person_() { al("zxc") } ; al(Person_) ;//каждая новая функция переопределяет старую var Person_ = function () {al("123")}; al(Person_) ;//каждая новая функция переопределяет старую function Person_() { al("qqq") } ; al(Person_) ; //каждая новая функция переопределяет старую } //судя по всему интепретатор сначала прогоняет глобальный контекст, на предмет наличия именованных функций, и создавая их //причем в подконтексты он не лезет //в памяти остается последняя из именованных функций //потом неспеша строку за строкой выполняет программу, переопределяя по мере необходимости //в подконтекстах то же самое, но без предвариловки с именованными функциями PS IMHO. |
Цитата:
|
2 Gvozd > Дайте плз ссылку , в ECMA не нашел, не понял этой синтаксической структуры :
{ //создали новый контекст исполнения // .... } |
http://javascript.ru/ecma/part10#a-10.1.3
Для объявленных функций: Цитата:
Цитата:
|
Цитата:
|
kefi,
блин даже не знаю. термин взял из головы. справки по тому что написал дать не могу, ибо теперь я не понимаю, почему оно так!) походу такое поведение не подчиняется каким-либо стандартам более того, поведение указанное мною в коментариях наблюдается только в мозилле. в остальных же все в порядке вещей, независимо от "контекста исполнения" согласно стандартам должно быть так: Цитата:
Код:
function Person() { al("qqq") } Код:
function Person() { al("qqq"); } протестируйте код ниже в огнелисе, и в другом браузере. реально странные вещи творятся у огнелиса function al(o){document.write(o,'<br>')} ; al(Person) ;//здесь будет указана именованая функция.та, которая была объявлена последней function Person() { al("zxc") } ; al(Person) ;// та же ботва var Person = function () {al("123")}; al(Person) ;//опаньки.появилась анонимная.ее и пишем function Person() { al("qqq") } ; al(Person) ; //та же ботва al('-----------------') ; { //создали новый контекст исполнения al(Person_) ;//нету еще никакой функции function Person_() { al("zxc_") } ; al(Person_) ;//каждая новая функция переопределяет старую var Person_ = function () {al("123_")}; al(Person_) ;//каждая новая функция переопределяет старую function Person_() { al("qqq_") } ; al(Person_) ; //каждая новая функция переопределяет старую } al('-----------------') ; (function(){ //создали новый контекст исполнения al(Person__) ;//нету еще никакой функции function Person__() { al("zxc__") } ; al(Person__) ;//каждая новая функция переопределяет старую var Person__ = function () {al("123__")}; al(Person__) ;//каждая новая функция переопределяет старую function Person__() { al("qqq__") } ; al(Person__) ; //каждая новая функция переопределяет старую })() al('-----------------') ; for(i=0;i<1;i++) { //создали новый контекст исполнения al(Person__1) ;//нету еще никакой функции function Person__1() { al("zxc__1") } ; al(Person__1) ;//каждая новая функция переопределяет старую var Person__1 = function () {al("123__1")}; al(Person__1) ;//каждая новая функция переопределяет старую function Person__1() { al("qqq__1") } ; al(Person__1) ; //каждая новая функция переопределяет старую } |
Цитата:
var a = function a() {...}; Основных отличий FE от FD (Function Declaration) два: 1. FE создаётся в рантайме (тогда как FD создается до построчного выполнения скрипта); 2. FE не воздействует на Variable object (VO) функции/контекста. Первый пункт, вроде, и так все знают (кто более-менее знаком с JS). Однако, во многих статьях он описан поверхностно, и в основном FE приравнивается лишь к анонимной функции (что и создаёт путаницу). В то время как, разновидностей FE гораздо больше. (function a() {...}); // это тоже, например, FE alert(a); // как видим, на VO это не повлияло, и такой переменной нет - ошибка. Цитата:
Новый контекст исполнения здесь не создаётся. Однако, в новых версиях, блок из фигурных скобок может создавать отдельный scope (если интересно, почитайте про let на MDC и т.д.). upd: Цитата:
|
Цитата:
this.action1=function(){ /* код функции */; }, то оно будет создавать новую функцию при каждом вызове этого конструктора для построения объекта ? Если да, то тогда будет лучше для экономии памяти и времени делать в конструкторе так : function F (){ /* код функции */; }, this.action1=F ; ? |
kefi, нет. Всё-таки, слово "скрипт" получилось несколько путанным в этой формулировке (вот только недавно насчёт этого же вопрос был).
Перефразирую точнее: FD создается при входе в контекст исполнения, до построчного его выполнения. Если контекст один - глобальный, то тут можно сказать и "весь скрипт". Всего есть три контекста: глобальный, функция и eval (подробней - в ссылке ниже). Поэтому, при входе в функцию её Variable object (Объект переменных, пункт 10.1.3) наполняется снова. В случае же с Вашим конструктором, - да, функция будет создаваться каждый раз новая - для каждого порождаемого этим конструктором объекта. В первом случае, у Вас FE: this.action1=function(){ /* код функции */; }; Такая функция, как было сказано, создаётся в рантайме и не воздействует на VO, однако, последующее присвоение её свойству this.action1 оставляет функцию в памяти (иначе FE можно выполнить только сразу при объявлении, т.к. в VO они не попадают и дальше вызвать их нельзя). Во втором случае, у Вас FD: function F (){ /* код функции */; } this.action1=F ; И, хотя, эта функция будет создана при входе в контекст исполнения (до выполнения кода функции), всё равно, функция будет так же создана новая - для каждого объекта своя. Цитата:
function A(state) { this.state = state; // у каждого объекта своё свойство this.fn = function () {}; // тоже своё function fn2() {} this.fn2 = fn; // тоже своё } // а вот методы - описаны единожды, // но так же доступны всем порождённым // объектам - за счёт делегации к прототипу A.prototype = { constructor: A, test: function () { alert(this.a); } }; // можно и отдельно описывать методы в прототипе A.prototype.test2 = function () { alert(this.state + ' test2'); }; var a = new A(10); var b = new A(20); a.test(); // 10 b.test(); // 20 alert([ a.hasOwnProperty('state'), // true b.hasOwnProperty('state'), // true a.hasOwnProperty('fn'), // true b.hasOwnProperty('fn'), // true a.hasOwnProperty('fn2'), // true b.hasOwnProperty('fn2'), // true a.hasOwnProperty('test'), // false, нет родного свойства, возьмётся из прототипа b.hasOwnProperty('test') // false, аналогично ]); Ссылка: http://javascript.ru/ecma/part10#a-10. Особенно можно посмотреть пункт 10.1.3, именно там говорится, что (var'ы, FD, и формальные параметры) и когда (при входе в контекст исполнения) создаётся (попадает в Variable object функции). |
Цитата:
|
Цитата:
Но! Как же так получается для второго случая с FD, функция определяется единожды - еще до run-time, но опять каждый объект содержит отдельную копию тела функции ? Или все же не тела в обоих случаях, а ссылки на одно и тоже тело ? В чем причина? В ECMA упорно не могу догнать, что написано. PS Цитата:
|
Цитата:
|
Цитата:
function fn () { var a = function _a() {}; function b() {} } Что произошло: 1. Входим в контекст исполения функции "fn": - Заполняется VO: VO['a'] - создалась переменная "а", значение undefined; VO['b'] - создалась FD "b"; 2. Выполняем код контекста функции "fn" (вот он, runtime контекста): - создалась FE "_a" - VO['a'] = FE "_a" Цитата:
name ---> блок кода Или: function name() { // блок кода } Далее, присваиваем _name ссылку (тип Reference) на тот же блок кода: var _name = name; name ---> блок кода <--- _name alert(name === _name); // true Старое имя связываем с новым блоком кода: name = function () { // новый блок кода }; _name ---> блок кода name ---> новый блок кода alert(name === _name); // false Восстанавливаем: name = _name; P.S.: а, отвлекался, долго писал, Zeroglif ответил уже. |
Цитата:
Что же получается, что если в теле функции опредлены внутренние функции, то при каждом вызове этой функции ( входе в ее контекст ) будут создаваться и компилироваться новые копии тел вложеных функций ? Но зачем их создавать заново, и компилировать заново, если и после первого одного входа в контекст внешней функции уже интерпретатору должно быть понятно, что текстуально все нутро этой функции определено и меняться более оно текстуально не будет ? Где же тогда рациональность спецификации ? |
Цитата:
С другой стороны стандарт предусматривает оптимизацию, разрешая 'joined objects', но я чего-то сейчас не вижу, чтобы этим кто-то пользовался. Внутренняя самодельная оптимизация наверняка существует, но нам это не важно, если это не противоречит установленной логике или не выпячивает разницу в скорости. |
2 Zeroglif > А ну так все же у вложенной функции для разных объектов разный 'scope chain' , но "при одном и том же 'body' " ?
Т.е. на каждом объекте замыкается только свой [[scope]], но текст тела для всех один общий ? |
Даже не знаю, как объяснять. Ну, вот вы видите внутри конструктора некую функцию:
this.x = function(){...}; Представьте, что вместо функции там объект: this.x = {}; Создавая "экземпляры", вы создаёте разные объекты 'this.x' иначе у каждого экземпляра был бы один и тот же. Та же самая история с функциями, которые те же объекты, только сложнее. У них разница усиливается необходимостью удерживать scope chain, которая (цепь) теоретически всегда разная, т.к. создаётся в момент вызова и "привязывается" к создаваемой функции в момент создания. К тому же у каждой функции при создании есть пара - прототип будущих экземпляров, это тоже уникальная черта каждого потенциального конструктора. |
Цитата:
|
Цитата:
|
kefi, реализация может создавать объединённые объекты (join object's), тем самым, обеспечивая оптимизацию. Вот у таких объектов, тело (блок кода) будет использоваться одно, а внутренние свойства (включая [[scope]]) будут разделены.
Могу продемонстрировать на Python'e, если есть желание (там два одинаковых метода у двух созданных инстансов будут разные (False на ==), но внутреннее свойство функции этих методов - будет ссылаться на один и тот же блок кода (True на ==)). |
Вот еще пример, в котрый я не могу въехать :
function al(o){document.write(o,'<br>')} function Class2(arg1) { this._featureAction1=function(){ al(["Class2._featureAction1"]) } ; this._featureAction1() ; // как и ожидалось вызывается метод объекта, на который показывает this, т.е. function(){ al(["Class2._featureAction1"]) } ; //this.constructor.prototype._featureAction1.call(this); this.constructor.prototype._featureAction1(); }; Class2.prototype._featureAction1=function(){ this._featureAction1(); // переполнение стека . //al(["Class2.prototype._featureAction1"]) }; c=new Class2(); На строке "this._featureAction1(); // переполнение ... " происходит зацикливание(переполнение стека). Хотя я ожидал , что this сработает так же как и в строке " this._featureAction1() ; // как и ожидалось ..." , т.е. просто будет вызван как Собственый метод this.функция из тела Конструктора. Почему же при вызове из тел функций прототипа работает иначе, чем из тела Конструктора ? |
Цитата:
В js значение 'this' меняется динамически и зависит от контекста вызова (от того, каким образом вызывается функция). Вам нужно просто почитать про это. |
Цитата:
Гдк сказано , что значением this в теле метода прототипа будет прототип ? |
Цитата:
|
А ну где читал , там не обращено внимание видно на то, что this в теле вызываемой функции укажет на "все, что стоит перед вызовом"
т.е. я подумал, что this внутри будет равен (this) : (this).constructor.prototype._featureAction1() а он на самом деле равен (this.constructor.prototype) : (this.constructor.prototype)._featureAction1() |
Цитата:
И, кстати, не зависимо от того, есть ли у Вас собственный метод this._featureAction1 - всё равно будет зацикливанием (в этом случае this будет указывать на объект "с", но вызываться будет снова этот метод из прототипа). |
Может кто-нибудь понятно объяснить, что называют
- контекстом функции ; - объектом переменных функции (VO) ; - [[scope]] функции ? Например для функции верхнего уровня F: var I ; function F() { var i;} ; Говоря "контекст функции F" имеют ввиду глобальный код , в котором находится функция F с переменной I или же - ее внутренний код с переменной i ? Говоря "[[scope]] функции F" - аналогичный вопрос, что имеют ввиду ?. Говоря "VO функции F" - аналогичный вопрос , что имеют ввиду ? Мне кажется , что порой эти понятия путаются (у меня в голове так точно, чтение стандарта не помогло ) ... |
Часовой пояс GMT +3, время: 13:35. |