хитросплетения 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, время: 03:37. |