Какова семантика механизма интерпретатора Gecko Javascript?

Редактировать

Принимая во внимание ответ ниже относительно ссылки на Спецификацию языка ECMAScript - 11.13.2 Составное назначение

Учитывая, почему эти,

javascript:
   o="";  o = o + (o+=1)    ; alert(o);
   o="";  o =     (o+=1) + o; alert(o);

НЕ одинаковы. Существуют временные семантические проблемы с оценкой сценария слева направо (ref:Спецификация ECMA. Оператор сложения). Одним из следствий этого является то, что оператор + не обязательно является коммутативным.

Это также можно увидеть с помощью:

javascript:
   o=1;  o = o + (o+=1)    ; alert(o);
   o=1;  o =     (o+=1) + o; alert(o);

or

javascript:
   o=" _ ";  o = o + (o+=1)    ; alert(o);
   o=" _ ";  o =     (o+=1) + o; alert(o);

Парадигма ленивых вычислений, ошибочно и неуместно используемая мной и создающая описанную ниже проблему, также является плохим признаком моего личного образа действий.


Исходное сообщение

Следующие соображения, возможно, уже были рассмотрены, хотя, похоже, нет. Если да, можно ли дать ссылки на обсуждения?

Формальная денотационная семантика механизма выполнения Gecko Javascript является загадкой. Эмпирическое тестирование утомительно и не может быть исчерпывающим.

  • Доступна ли авторитетная формальная спецификация или официальная ссылка, точно определяющая, как Gecko интерпретирует Javascript?

Ссылка, Спецификация языка ECMAScript кажется неадекватным, хотя создание таких скриптов, как

javascript: alert( function(){return {}}().life=42 )

с вытекающим значением таких конструкций при связывании значений.

  • Существует ли определенная парадигма, описывающая интерпретацию кода Javascript для оценки объектов и экземпляров?

Это прояснит концепции вызова по потребности (или, скорее, использования по) потребности, значения, ссылки, вывода, имени, ... как релевантные или нет. То, что Javascript является интерпретатором прототипов, придает неявное значение некоторым из приведенных ниже проблем.

Каков ожидаемый результат:

javascript: o={n:0}; f=function(){o.n+=1; return 10};
   alert([
      o.n,            f(),
      o.n,       o.n+=f(),
      o.n, eval('o.n+=f()'), 
      o.n, eval('o.n+='+f()),
      o.n,
   ].join(",\t"));

? Легко ли предсказать результаты (правильно!)?

Вопрос немного риторический, поскольку он был специально придуман с помощью eval, чтобы усилить и подчеркнуть тонкие нюансы интерпретации. Может ли оценка этого скрипта (и приведенного ниже) быть решена с помощью Спецификация языка ECMAScript или другой документ, о котором упоминалось ранее?

(Кроме того, рассмотрим:

javascript: ra=[];
   alert([
      ra, ra[ra.length]=" partially defined.",
      ra, ra.push("\n RA is not shown"),
      ra, ra.reverse()[42],
   ].join(",\t\t"));

который отображает:

 RA is not shown, partially defined.,        partially defined.,        
 RA is not shown, partially defined.,       2,      
 RA is not shown, partially defined.,       

где частичные оценки ra НЕ аналогичны o.n!

и следующее, что менее экзотично, чем использование on:

javascript: o=""; f=function(){o+=1; return 0};
   alert([
      o,          f(),
      o,       o+=f(),
      o, eval('o+=f()'), 
      o, eval('o+='+f()),
      o,
   ].join(",\t"));

который отображает:

,   0,  1,  10, 10, 100,    100,    10010,  10010

)

Учитывая следующий скрипт:

javascript:
   asn="\t\t and so now,\t o.n is "; nl="\n\n";
   o={}; f=function(){o.n+=1; return 10};
   alert(["Using:\n",window.navigator.userAgent,
   nl,"The function f() is:\n ",f,
   nl,"What the!!?!? \t\t\t\t\t\t\t initially \t\t o.n is ",          o.n = 0,
 nl,"Called as a procedure: \t\tf() is ", f(),                   asn, o.n,
nl,"but, instead of 12 \t\to.n+=f() is ", o.n+=f(),              asn, o.n,
     nl,"however eval'd\t\to.n+=f() is ", eval("o.n+="+f()),     asn, o.n,
    "!\n\nIt makes no functional difference if, instead of o.n, o['n'] is used.",
    "\nThe expected o.n evaluation sequence is 0, 1, (+1+10=) 12, (+1+10=) 23.",
    "\n_____ _____ _____ _____ _____ _____ _____ _____^^ missing in result",
  ].join(""));

Двигатель Gecko выдает:

Using:
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3)
        Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3

The function f() is:
 function () {
    o.n += 1;
    return 10;
}

What the!!?!?                                initially       o.n is 0

Called as a procedure:      f() is 10        and so now,     o.n is 1

but, instead of 12      o.n+=f() is 11       and so now,     o.n is 11

however eval'd          o.n+=f() is 22       and so now,     o.n is 22!

It makes no functional difference if, instead of o.n, o['n'] is used.
The expected o.n evaluation sequence is 0, 1, (+1+10=) 12, (+1+10=) 23.
_____ _____ _____ _____ _____ _____ _____ _____^^ missing in result

person Ekim    schedule 16.04.2011    source источник
comment
Я не языковой юрист, но, кажется, это имеет смысл. o.n оценивается каждый раз отдельно, давая вам целое число, хранящееся в настоящее время в поле o n - поле позже перезаписывается, целое число, ранее сохраненное в нем, не изменяется. Второй пример помещает несколько ссылок на один и тот же объект в массив результатов и тем временем изменяет его, поэтому, когда вы смотрите на конечный результат, вы смотрите на один и тот же объект несколько раз.   -  person    schedule 17.04.2011
comment
Не знаю, почему вы несколько раз называете Gecko (на самом деле это SpiderMonkey от Mozilla). Почему вы не провели тестирование в Chrome и Internet Explorer?   -  person Nayuki    schedule 22.02.2021


Ответы (1)


JavaScript имеет модель исполнения с нетерпеливой оценкой (вызов по значению), четко описанную в стандарте ECMA. Все эти вопросы можно решить путем внимательного прочтения стандарта. Например, причина, по которой выше результат 11, а не 12, четко прописана в 11.13.2 стандарта. o.n оценивается до вызова f(), а не после, как указано в шаге 2.

person chuckj    schedule 16.04.2011
comment
Большое спасибо - заставил меня задуматься - см. редактирование, предшествующее исходному сообщению. - person Ekim; 17.04.2011
comment
Все языки, допускающие побочные эффекты, имеют одинаковую проблему. Некоторые языки, такие как C и C++, даже заходят так далеко, что говорят, что порядок оценки не определен, что позволяет реализации варьироваться в зависимости от того, какой результат дается. JavaScript не может, поэтому явно указывает порядок. В любом случае, в процедурном языке с побочными эффектами избегайте конструкций, делающих побочный эффект видимым, таких как o = o + (o+=1) или, что более традиционно, o = o + ++o. - person chuckj; 18.04.2011
comment
или даже ((o=1)+(++o)) вместо ((++o)+(o=1)) ! - person Ekim; 19.04.2011
comment
Да, всего этого следует избегать в языках под влиянием C или C. Они стандартизированы в Java, C# и JavaScript, оставлены неопределенными в C и C++ и во всех них уродливы. - person chuckj; 19.04.2011