Насколько я вижу,
blockquote>strict
ссылается на внутренний слот[[Strict]]
объекта функции.No. И да. Это относится к строгости функции ( или script ) , в которой происходит блок, содержащий объявление функции. Не строгость функции, которая (или не) должна быть объявлена.
«Веб-расширения» применяются только к неаккуратным (нестрогим) кодам и только если внешний вид функции оператор является «нормальным», то есть, например, если его имя не сталкивается с формальным параметром или лексически объявленной переменной.
Обратите внимание, что нет никакой разницы между строгим и неаккуратным кодом без веб- семантика совместимости. В чистом ES6 существует только одно поведение для объявлений функций в блоках.
Итак, у нас в основном есть
| web-compat pure -----------------+--------------------------------------------- strict mode ES6 | block hoisting block hoisting sloppy mode ES6 | it's complicated ¹ block hoisting strict mode ES5 | undefined behavior ² SyntaxError sloppy mode ES5 | undefined behavior ³ SyntaxError
1: См. Ниже. Прошу прощения. 2: Как правило, бросается
SyntaxError
3: примечание в ES5.1 §12 говорит о « значительных и непримиримых вариациях среди реализаций » (таких как эти [/ д2]). Предупреждения рекомендуются.Итак, как теперь реализуется реализация ES6 с совместимостью в Интернете для объявления функции в блоке в режиме sloppy-mode с унаследованной семантикой? Прежде всего, чистая семантика все еще применяется. То есть объявление функции поднимается вверху лексического блока. Тем не менее, есть также объявление
var
, которое поднимается в верхней части закрывающей функции. И когда объявление функции оценивается (в блоке, как если бы оно выполнялось как оператор), объекту функции присваивается эта переменная с ограниченной функциональностью.Это лучше объясняется кодом:
function enclosing(…) { … { … function compat(…) { … } … } … }
работает так же, как
function enclosing(…) { var compat₀ = undefined; // function-scoped … { let compat₁ = function compat(…) { … }; // block-scoped … compat₀ = compat₁; … } … }
Да, это немного сбивает с толку, имея два разных привязки (обозначенные нижними индексами 0 и 1) с тем же именем. Поэтому теперь я могу кратко ответить на ваши вопросы:
Видимый вне блока?
blockquote>Да, как
var
. Тем не менее, есть вторая привязка, которая видна только внутри блока.Поднято?
blockquote>Да - дважды.
До какой точки?
blockquote>Обе функции (однако инициализированы с помощью
undefined
) и блоком (инициализируются функциональным объектом).«TDZ»?
blockquote>Не в смысле временной мертвой зоны лексически объявленной переменной (
let
/const
/class
), которая выбрасывает ссылку, no. Но до того, как объявление функции встречается при выполнении тела, переменная с функциональной областью -undefined
(особенно перед блоком), и вы также получите исключение, если попытаетесь вызвать его.
Дерево выражений то, что Вы относитесь, действительно ли Вычисление выражения является деревом?
, Если да тогда это - дерево, созданное синтаксическим анализатором. Синтаксический анализатор использовал Лексический анализатор/Токенизатор для идентификации Маркеров из программы. Синтаксический анализатор создает Двоичное дерево из маркеров.
Здесь подробное объяснение
IIUC, дерево выражений подобно Абстрактному синтаксическому дереву, но выражение обычно yiels единственное значение, тогда как AST может представить всю программу (с классами, пакетами, функцией, операторами, и т.д.)
Так или иначе, для выражение (2 + 3) * 5, дерево:
*
/ \
+ 5
/ \
2 3
Оценивают каждый узел рекурсивно (вверх дном) для получения значения в корневом узле, т.е. значения выражения.
Вы можете, конечно, иметь унарный (отрицание) или trinary (if-then-else) операторы также и функции (не, т.е. любое число операции в секунду), если Ваш язык выражения позволяет его.
типы Оценки и выполнение управления типа сделан по подобным деревьям.
Деревья выражений являются представлением в оперативной памяти выражения, например, арифметическим или булевым выражением. Например, рассмотрите арифметическое выражение
a + b*2
, Так как * имеет более высокий приоритет оператора, чем +, дерево выражений создается как этот:
[+]
/ \
a [*]
/ \
b 2
Наличие этого дерева, это может быть оценено для любых значений a и b. Кроме того, можно преобразовать его в другие деревья выражений, например, для получения выражения.
, Когда Вы реализуете дерево выражений, я предложил бы создать Выражение базового класса . Полученный из этого, класс BinaryExpression использовался бы для всех двоичных выражений, такой как + и *. Тогда Вы могли представить VariableReferenceExpression к ссылочным переменным (таким как a и b), и другой класс ConstantExpression (для 2 от примера).
дерево выражений во многих случаях создается как результат парсинга входа (от пользователя непосредственно, или из файла). Для оценки дерева выражений я предложил бы использовать Шаблон "посетитель" .
Дерево выражений является механизмом для перевода исполняемого кода в данные. Используя дерево выражений, можно произвести структуру данных, которая представляет программу.
В C#, можно работать с деревом выражений, произведенным лямбда-выражениями при помощи Expression<T>
класс.
В традиционной программе, Вы пишете код как это:
double hypotenuse = Math.Sqrt(a*a + b*b);
Этот код заставляет компилятор генерировать присвоение, и вот именно. В большинстве случаев это - все, о чем Вы заботитесь.
Со стандартным кодом, Ваше приложение не может пойти задним числом назад и взгляд hypotenuse
, чтобы решить, что это было произведено путем выполнения Math.Sqrt()
вызов; этой информацией является просто не часть того, что включено.
Теперь, рассмотрите лямбда-выражение как следующее:
Func<int, int, int> hypotenuse = (a, b) => Math.Sqrt(a*a + b*b);
Это немного отличается, чем прежде. Теперь hypotenuse
на самом деле ссылка на [1 110] блок исполняемого кода . Если Вы будете звонить
hypotenuse(3, 4);
, то Вы доберетесь, значение 5
возвратилось.
Мы можем использовать деревья выражений для исследования блока исполняемого кода, который был произведен. Попробуйте это вместо этого:
Expression<Func<int, int, int>> addTwoNumbersExpression = (x, y) => x + y;
BinaryExpression body = (BinaryExpression) addTwoNumbersExpression.Body;
Console.WriteLine(body);
Это производит:
(x + y)
Более усовершенствованные методы и манипуляции возможны с деревьями выражений.
Краткий ответ: Приятно иметь возможность написать такой же запрос LINQ и указать его на любой источник данных. Без него у вас не было бы запроса "Language Integrated".
Длинный ответ: Как вы, наверное, знаете, когда вы компилируете исходный код, вы переводите его с одного языка на другой. Обычно с языка высокого уровня (C #) на более низкий уровень (IL).
В основном это можно сделать двумя способами:
Последнее - это то, что все программы, которые мы знаем как это делают «компиляторы».
Если у вас есть дерево синтаксического анализа, вы можете легко перевести его на любой другой язык, и это то, что деревья выражений позволяют нам делать. Поскольку код хранится в виде данных, вы можете делать с ним все, что захотите, но, возможно, вы просто захотите перевести его на какой-нибудь другой язык.
Теперь в LINQ to SQL деревья выражений превращаются в команду SQL, а затем отправляются по сети на сервер базы данных. Насколько я знаю, они этого не делают При переводе кода они не делали ничего необычного, но они могли . Например, поставщик запросов может создать другой код SQL в зависимости от условий сети.