Я тоже этого не узнаю, иди домой и на ферме.
Кода -копия выглядит следующим образом:
Удалить этот isobject [ключ]
или
Удалить этот isobject.key
Кстати, давайте поговорим об использовании удаления
Несколько недель назад у меня была возможность прочитать, ориентированную на объектно-ориентированную книгу Стояна Стефанова. Эта книга высоко оценена на Amazon (12 обзоров, 5 звезд), поэтому мне было любопытно посмотреть, была ли это рекомендуемой книгой, поэтому я начал читать главу функций. Я действительно ценю то, как эта книга объясняет вещи, и примеры организованы очень красивым, постепенно, и кажется, что даже новички могут легко овладеть этим знанием. Однако почти сразу я обнаружил интересное недоразумение на протяжении всей главы - удаление функциональных функций. Есть также некоторые другие ошибки (такие как разница между объявлениями функций и выражением функций), но в настоящее время мы не будем обсуждать их.
Книга утверждает:
«Функция рассматривается как нормальная переменная - ее можно скопировать в разные переменные или даже удалять». Пример прикреплен к этому объяснению:
Кода -копия выглядит следующим образом:
var sum = function (a, b) {return a + b;}
var add = sum;
Удалить сумму
истинный
тип sum;
"неопределенный"
Игнорируйте некоторые отсутствующие полуколоны, вы видите, где ошибки в этих кодах? Очевидно, что ошибка состоит в том, что операция удаления переменной суммы не будет успешной. Выражение Delete не должно возвращать true, а сумма TypeOF не должна возвращать «неопределенную». Все это потому, что невозможно удалить переменные в JavaScript. По крайней мере, это невозможно в этом способе декларации.
Итак, что именно произошло в этом примере? Это ошибка? Или особое использование? Наверное, нет. Этот код на самом деле является реальным выводом в консоли Firebug, и Stoyan, должно быть, использовал его в качестве инструмента для быстрого тестирования. Это почти как Firebug следует за некоторыми другими правилами удаления. Это Firebug заставил Стояна сбиться с пути! Итак, что именно здесь произошло?
Прежде чем ответить на этот вопрос, нам сначала нужно понять, как работает оператор удаления в JavaScript: что именно можно удалить и что нельзя удалить? Сегодня я постараюсь объяснить это подробно. Мы посмотрим на «странное» поведение Firebug и поймем, что это не так странно. Мы углубимся в то, что скрыто за кулисами, где переменные, функционируют, присвоили значения атрибутам и удаляете их. Мы рассмотрим совместимость с браузером и некоторые из самых известных ошибок. Мы также обсудим строгую модель ES5 и то, как он меняет поведение операторов удаления.
Я собираюсь обмениваться JavaScript и Ecmascript, оба из которых означают Ecmascript (если только очевидно, что реализация Mozilla в JavaScript)
Как и ожидалось, в Интернете объяснения удаления довольно мало. Статья MDC, вероятно, является лучшим ресурсом для понимания, но, к сожалению, в ней не хватает некоторых интересных деталей темы. Как ни странно, одна из забытых вещей является причиной странного проявления Firebug. И ссылка MSDN почти бесполезна в этих аспектах.
Теория
Итак, почему мы можем удалить свойства объекта:
Кода -копия выглядит следующим образом:
var o = {x: 1};
Удалить OX; // истинный
бык; // неопределенный
Но объект, объявленный таким образом, не может быть удален:
Кода -копия выглядит следующим образом:
var x = 1;
Удалить x; // ЛОЖЬ
x; // 1
Или функция:
Кода -копия выглядит следующим образом:
Функция x () {}
Удалить x; // ЛОЖЬ
тип x; // "функция"
ПРИМЕЧАНИЕ. Когда свойство не может быть удалено, оператор удаления только вернет FALSE.
Чтобы понять это, нам сначала нужно освоить эти понятия о переменных экземплярах и свойствах атрибутов - эти концепции, к сожалению, редко упоминаются в книгах JavaScript. Я постараюсь кратко просмотреть эти концепции в следующих нескольких параграфах. Эти концепции трудно понять! Если вам все равно «почему эти вещи работают таким образом», просто пропустите эту главу.
Тип кода:
В Ecmascript существует 3 различных типа исполняемого кода: глобальный код, код функции и код Eval. Эти типы более или менее самоочевидны с точки зрения имени, вот краткий обзор:
Когда часть исходного кода рассматривается как программа, он будет выполняться в глобальной среде и считается глобальным кодом. В среде браузера содержимое элементов сценария обычно интерпретируется как программы и поэтому выполняется как глобальный код.
Любой код, который выполняется непосредственно в функции, явно считается кодом функции. В браузере содержание свойств события (например, <p onclick = "...">) обычно интерпретируется как код функции.
Наконец, текст кода, применяемый к встроенной функции, интерпретируется как код Eval. Вскоре мы узнаем, почему этот тип особенный.
Контекст исполнения:
Когда код ECMascript выполняется, он обычно происходит в конкретном контексте выполнения. Контекст исполнения - это несколько абстрактная концепция сущности, которая может помочь понять, как работают применение и переменные экземпляры. Для каждого из трех исполняемых кодов существует контекст выполнения, соответствующий ему. Когда функция выполняется, мы говорим «Управление программой входит в контекст выполнения кода функции»; Когда выполняется часть глобального кода, управление программой входит в контекст выполнения глобального кода и т. Д.
Как видите, контекст выполнения может логически сформировать стек. Во -первых, может быть часть глобального кода и его собственный контекст выполнения, и тогда этот фрагмент кода может вызвать функцию с его (функциональным) контекстом выполнения. Эта часть функции может вызвать другую функцию и т. Д. Даже если функция называется рекурсивно, она будет введена в новый контекст выполнения каждый раз, когда она вызывается.
Active Object (объект активации) / объект переменной:
Каждый контекст выполнения имеет так называемый объект переменной, связанный с ним. Подобно контексту выполнения, объект переменной - это абстрактная сущность, механизм, используемый для описания экземпляров переменных. Интересно, что переменные и функции, объявленные в исходном коде, обычно добавляются в этот объект переменной в качестве свойств.
Когда управление программой входит в контекст выполнения глобального кода, глобальный объект используется в качестве объекта переменной. Именно поэтому переменные функции объявляют Global стать глобальными свойствами объекта.
Кода -копия выглядит следующим образом:
/ * Помните, что «это» относится к глобальному объекту, когда в глобальном масштабе */
var global_object = this;
var foo = 1;
Global_object.foo; // 1
foo === global_object.foo; // истинный
Функциональный bar () {}
typeof global_object.bar; // "функция"
Global_object.bar === bar; // истинный
Хорошо, глобальные переменные станут свойствами глобальных объектов, но что происходит с локальными переменными (которые определены в коде функции)? На самом деле, они ведут себя очень одинаково: они станут свойствами переменных объектов (переменные объекты). Единственное отличие состоит в том, что в коде функции элемент-объект не является глобальным объектом, а так называемый объект активации. Активный объект создается каждый раз, когда он входит в контекст выполнения кода функции.
Не только переменные и функции, объявленные в коде функции, станут свойствами активного объекта; Это также будет происходить в каждом параметре функции (имя, соответствующее соответствующему формальному параметру) и объекту специальных аргументов (имя аргументов). Обратите внимание, что активный объект является механизмом внутреннего описания и не может быть доступен в коде программы.
Кода -копия выглядит следующим образом:
(function (foo) {
var bar = 2;
function baz () {}
/*
В абстрактных терминах,
Специальный объект «аргументы» становится свойством объекта активации содержания функции:
Active_object.arguments; // Аргументы объект
... а также аргумент `foo`:
Active_object.foo; // 1
... а также переменная `bar`:
Active_object.bar; // 2
... а также функция, объявленная локально:
typeof activation_object.baz; // "функция"
*/
}) (1);
Наконец, переменные, объявленные в коде оценки, становятся свойствами объектов переменных в контексте вызывающего абонента. Eval Code просто использует объекты переменных в контексте выполнения кода, который его вызывает.
Кода -копия выглядит следующим образом:
var global_object = this;
/* `foo` создается как свойство вызова контекстного переменного объекта,
который в этом случае является глобальным объектом */
eval ('var foo = 1;');
Global_object.foo; // 1
(function () {
/* `bar
который в этом случае является объектом активации содержания функции */
eval ('var bar = 1;');
/*
В абстрактных терминах,
Active_object.bar; // 1
*/
}) ();
Атрибуты собственности
Мы почти здесь. Теперь, когда мы хорошо знаем о том, что происходит с переменными (они становятся свойствами), единственная оставшаяся концепция, которую нужно понять, - это атрибуты собственности. Каждый атрибут может иметь 0 или более свойств, которые выбираются из следующих наборов: Readonly, Dontenum, DontDelete и Internal. Вы можете думать о них как о флагах - функции, которая может существовать или нет в свойствах. Для нашего обсуждения сегодня мы заинтересованы только в DontDelete.
Когда объявленные переменные и функции становятся атрибутами объектов переменных (или активных объектов кода функции или глобальных объектов глобального кода), эти атрибуты создаются с атрибутом DontDelete. Однако любые явные (или неявные) атрибуты не будут включены в атрибут DontDelete. Вот почему мы можем удалить некоторые атрибуты, но не можем удалить других.
Кода -копия выглядит следующим образом:
var global_object = this;
/* `foo` - это свойство глобального объекта.
Он создан с помощью объявления переменной, и поэтому имеет атрибут DontDelete.
Вот почему его нельзя удалить. */
var foo = 1;
Удалить foo; // ЛОЖЬ
TypeOf foo; // "число"
/* `bar` является свойством глобального объекта.
Он создан с помощью объявления функций, и так же имеет атрибут DontDelete.
Вот почему это также не может быть удалено. */
Функциональный bar () {}
Удалить бар; // ЛОЖЬ
Typeof Bar; // "функция"
/* `Baz` также является свойством глобального объекта.
Тем не менее, он создается с помощью назначения свойств, и поэтому не имеет атрибута DontDelete.
Вот почему его можно удалить. */
Global_object.baz = 'blah';
Удалить Global_object.baz; // истинный
typeof global_object.baz; // "неопределенный"
Встроенные объекты и DontDelete
Итак, это все об этом (DontDelete): специальное свойство имущества, которое контролирует, можно ли удалить это свойство. Обратите внимание, что определенные встроенные объекты содержатся в том, чтобы содержать DontDelete, поэтому их нельзя удалить. Например, специальная переменная аргумента (или, как мы знаем сейчас, свойство активного объекта) имеет DontDelete. Свойство длины функционального экземпляра также имеет свойство DontDelete.
Кода -копия выглядит следующим образом:
(function () {
/ * Не удается удалить `аргументы
Удалить аргументы; // ЛОЖЬ
тип аргументов; // "объект"
/* Не удается удалить функцию `length`; У него также нерелита */
Функция f () {}
Удалить f.length; // ЛОЖЬ
typeof f.length; // "число"
}) ();
Атрибут, соответствующий параметру функции, также имеет функцию DontDelete с момента его создания, поэтому мы не можем его удалить.
Кода -копия выглядит следующим образом:
(function (foo, bar) {
Удалить foo; // ЛОЖЬ
foo; // 1
Удалить бар; // ЛОЖЬ
бар; // 'blah'
}) (1, 'blah');
Необъявленное задание:
Вы также можете помнить, что не выявленное назначение создает свойство для глобального объекта, если только собственность не была найдена в других местах этой цепочки сфера до глобального объекта. И теперь мы знаем разницу между назначением свойств и объявлением переменной - последнее устанавливает свойство DontDelete, но первое - нет. Мы должны быть ясно, почему незадефицитное назначение создает удаленное свойство.
Кода -копия выглядит следующим образом:
var global_object = this;
/* Создать глобальное свойство через объявление переменной; Собственность имеет DontDelete */
var foo = 1;
/* Создать глобальное свойство с помощью не выявленного назначения; Собственность не имеет DontDelete */
бар = 2;
Удалить foo; // ЛОЖЬ
TypeOf foo; // "число"
Удалить бар; // истинный
Typeof Bar; // "неопределенный"
Обратите внимание: свойства определяются при создании атрибута, а последующие назначения не изменяют свойства существующих атрибутов. Очень важно понять эту разницу.
Кода -копия выглядит следующим образом:
/ * `foo` создается как свойство с DontDelete */
функция foo () {}
/* Позднее назначения не изменяют атрибуты. DontDelete все еще там! */
foo = 1;
Удалить foo; // ЛОЖЬ
TypeOf foo; // "число"
/* Но присвоение свойству, которого не существует,
Создает это свойство с пустыми атрибутами (и так без DontDelete) */
this.bar = 1;
Удалить бар; // истинный
Typeof Bar; // "неопределенный"
Путаница Firebug:
Что происходит в Firebug? Почему переменные, объявленные в консоли, могут быть удалены? Разве это не противоречит тому, что мы узнали раньше? Что ж, как я уже говорил, код Eval имеет особую производительность при столкновении с переменными объявлениями. Переменные, объявленные в Eval, фактически создаются как атрибуты без атрибута DontDelete.
Кода -копия выглядит следующим образом:
eval ('var foo = 1;');
foo; // 1
Удалить foo; // истинный
TypeOf foo; // "неопределенный"
Точно так же, когда вы вызываете в коде функции:
Кода -копия выглядит следующим образом:
(function () {
eval ('var foo = 1;');
foo; // 1
Удалить foo; // истинный
TypeOf foo; // "неопределенный"
}) ();
Это основа для ненормального поведения Firebug. Весь текст в консоли будет проанализирован и выполнен как код Eval, а не как глобальный код или функциональный код. Очевидно, что все переменные, объявленные здесь, в конечном итоге станут свойствами без атрибута DontDelete, поэтому все они могут быть легко удалены. Мы должны понять разницу между глобальным кодом и консоли Firebug.
Удалить переменные через Eval:
Это интересное поведение Eval в сочетании с другим аспектом Ecmascript, технически может позволить нам удалить свойства «не удаляемых». Одна вещь о объявлениях функции заключается в том, что они способны переопределять переменные с тем же именем в одном и том же контексте выполнения.
Кода -копия выглядит следующим образом:
Функция x () {}
var x;
тип x; // "функция"
Обратите внимание, как объявления функции получают переменные приоритета и перезапись с тем же именем (или, другими словами, одинаковые свойства в объекте переменной). Это связано с тем, что объявления функций создаются после объявления переменной, и им разрешено перезаписывать их (переменные объявления). Объявления функций не только заменяют значение свойства, но и заменяют свойства этого свойства. Если мы объявим функцию через Eval, эта функция должна заменить свойства исходного (замененного) свойства своими собственными свойствами. И, поскольку переменные, объявленные через Eval, создают свойства без атрибута DontDelete, создание этой новой функции фактически удаляет существующий атрибут DontDelete из свойства, чтобы свойство было удалено (и, очевидно, указывает на его значение на недавно созданную функцию).
Кода -копия выглядит следующим образом:
var x = 1;
/ * Не удается удалить, `x` имеет нерелит */
Удалить x; // ЛОЖЬ
тип x; // "число"
eval ('function x () {}');
/ * `x` Свойство сейчас ссылается на функцию, и не должно иметь не DontDelete */
тип x; // "функция"
Удалить x; // должен быть `true
тип x; // должен быть "неопределенным"
К сожалению, этот «обман» не работает ни в какой реализации в настоящее время. Может быть, я что -то упускаю здесь, или, может быть, поведение слишком неясно, что исполнитель не замечает этого.
Совместимость браузера:
Теоретически полезно понять, как все работает, но практика - самая важная вещь. Следует ли браузер по стандартам, когда дело доходит до создания/удаления переменных/свойств? Ответ: в большинстве случаев, да.
Я написал простой набор тестов для тестирования совместимости браузера с операторами Delete, включая тесты в рамках глобального кода, кода функции и кода Eval. Испытательный набор проверяет, действительно ли удалены возвращаемое значение и значения атрибута оператора удаления (как они должны вести). Возвращаемое значение удаления не так важно, как его реальный результат. Если Delete возвращает true вместо false, это не важно, и важно, чтобы атрибуты с атрибутом DontDelete не удалены, и наоборот.
Современные браузеры, как правило, довольно совместимы. Помимо функций Eval, которые я упоминал ранее, следующие браузеры прошли все испытательные наборы: Opera 7.54+, Firefox 1.0+, Safari 3.1.2+, Chrome 4+.
Safari 2.x и 3.0.4 имеют проблемы при удалении параметров функции; Эти свойства, кажется, создаются без DontDelete, поэтому их можно удалить. Safari 2.x имеет больше проблем - удаление не ссылочных переменных (например, Delete 1) будет бросить исключения; Объявления функций создают удаленные свойства (но, как ни странно, декларации переменных этого не делают); Объявления переменных в Eval станут несекретными (но объявления функций являются удаленными).
Подобно Safari, Konqueror (3,5, а не 4,3), бросает исключение при удалении типа без ссылки (например: удаление 1), и неправильно делает переменные функции удаленными.
Примечание переводчика:
Я проверил последние версии Chrome, Firefox и IE, и в основном сохранил ситуацию, когда все остальные проходы, кроме 23 и 24, потерпят неудачу. В то же время я тестировал UC и несколько мобильных браузеров. За исключением встроенного браузера Nokia E72, который также имеет сбой 15 и 16, другие встроенные браузеры в основном такие же, как настольные браузеры. Но стоит отметить, что встроенный браузер Blackberry Curve 8310/8900 может пройти 23, что удивило меня.
Гекко нельтерет ошибка:
Gecko 1.8.x Browser - Firefox 2.x, Camino 1.x, Seamonkey 1.x и т. Д. - показывает очень интересную ошибку, явное назначение свойства удалит свое свойство DontDelete, даже если это свойство создается с помощью объявлений переменных или объявлений функций.
Кода -копия выглядит следующим образом:
функция foo () {}
Удалить foo; // Неверно (как и ожидалось)
TypeOf foo; // "функция" (как и ожидалось)
/ * Теперь назначают свойство явно */
this.foo = 1; // ошибочно очищает атрибут DontDelete
Удалить foo; // истинный
TypeOf foo; // "неопределенный"
/ * Обратите внимание, что этого не происходит при назначении свойства неявно */
Функциональный bar () {}
бар = 1;
Удалить бар; // ЛОЖЬ
Typeof Bar; // "номер" (хотя назначение заменило свойство)
Удивительно, но Internet Explorer 5.5 - 8 прошел полный набор тестирования, за исключением того, что удаление типов без применения (например, Delete 1) будет выбросить исключения (точно так же, как старое сафари). Тем не менее, в IE есть более серьезные ошибки, что не так очевидно. Эти ошибки связаны с глобальным объектом.
Т.е. ошибки:
В этой главе рассказывается о ошибках Internet Explorer? Ух ты! Это потрясающе!
В IE (по крайней мере, т.е. 6-8), следующее выражение бросает исключение (при выполнении в глобальном коде):
this.x = 1;
Удалить x; // typeError: объект не поддерживает это действие
Это также будет, но вызовет разные исключения, что делает вещи еще более интересными:
var x = 1;
Удалить это.x; // typeError: не удается удалить 'this.x'
Это выглядит так, как в IE, объявления переменных в глобальном коде не создают атрибуты на глобальном объекте. Создание атрибутов путем назначения (this.x = 1), а затем удалив их путем удаления X после этого, бросает ошибку. Создание атрибутов путем объявления (var x = 1) и удаления их впоследствии бросает другую ошибку.
Но это еще не все. Создание свойств явными заданиями на самом деле всегда вызовет исключения при удалении. Здесь не только ошибки, но и созданные свойства, кажется, имеют атрибут DontDelete, что, конечно, не должно быть.
this.x = 1;
Удалить это.x; // typeError: объект не поддерживает это действие
тип x; // "номер" (все еще существует, не был удален, как следовало бы!)
Удалить x; // typeError: объект не поддерживает это действие
тип x; // "номер" (не удалось снова)
Теперь мы думаем, что в соответствии с т.е. не обнаруженные задания (свойства должны создаваться на глобальных объектах) создают удаленные свойства.
x = 1;
Удалить x; // истинный
тип x; // "неопределенный"
Однако, если вы удалите это свойство с помощью этой ссылки в глобальном коде (Delete This.x), появится аналогичная ошибка.
x = 1;
Удалить это.x; // typeError: не удается удалить 'this.x'
Если мы хотим суммировать это поведение, кажется, что использование Delete This.x для удаления переменных из глобального кода никогда не будет успешным. Когда свойство в вопросе создается явным назначением (this.x = 1), удаляет ошибку; Когда свойство создается неопроверженным назначением (x = 1) или объявлением (var x = 1), удаляет другую ошибку.
Удалить x, с другой стороны, ошибка должна быть выброшена только тогда, когда свойство создается явным назначением - this.x = 1. Если свойство создается объявлением (var x = 1), операция удаления никогда не происходит, и операция удаления правильно возвращает False. Если свойство создается неопроверженным назначением (x = 1), операция удаления работает, как и ожидалось.
Я снова подумал об этой проблеме в сентябре. Гарретт Смит предположил, что под т.е.
«Объект глобальной переменной реализован как объект JScript, а глобальный объект реализован Host».
Гаррет использовал запись блога Эрика Липперта в качестве ссылки.
Мы можем более или менее подтвердить эту теорию, внедрив некоторые тесты. Обратите внимание, что это и окно, кажется, указывают на один и тот же объект (если мы можем доверять оператору ===, но объект переменной (объект, в котором находится объявление функции) отличается от того, на что указывает это.
Кода -копия выглядит следующим образом:
/ * В глобальном коде */
функция getBase () {вернуть это; }
getBase () === this.getBase (); // ЛОЖЬ
this.getBase () === this.getBase (); // истинный
window.getBase () === this.getBase (); // истинный
window.getBase () === getBase (); // ЛОЖЬ
недоразумение:
Красота понимания, почему так работает таким образом, нельзя недооценивать. Я видел некоторые недоразумения о операторе Delete в Интернете. Например, ответ на Stackoverflow (с удивительно высоким рейтингом), уверенно объясняет
«Когда целевой операнд не является свойством объекта, удаление должно быть в эксплуатации».
Теперь, когда мы поняли ядро операционного поведения удаления, ошибка в этом ответе становится очевидной. Удалить не различает переменные и атрибуты (на самом деле, для удаления, они оба являются ссылками) и фактически заботится только о атрибутах DontDelete (и существуют ли сами атрибуты).
Также очень интересно видеть различные недоразумения, опровергающие друг друга. В той же теме один человек сначала предположил, что удаление только переменных (это не будет работать, если не будет объявлено в Eval), в то время как другой человек обеспечил коррекцию ошибки в том, как удаление используется для удаления переменных в глобальном коде, но не в коде функции.
Будьте очень осторожны с объяснением JavaScript в Интернете. Идеальный метод - всегда понимать суть проблемы. ;)
Удалить и объект хоста (объект хоста):
Алгоритм удаления примерно так:
Вернуть True, если операнд не является ориентировочным типом
Если объект не имеет прямых атрибутов этого имени, верните True (как мы знаем, объект может быть активным объектом или глобальным объектом)
Если свойство существует, но имеет атрибут DontDelete, верните ложный
В других случаях удалите атрибут и верните True
Тем не менее, поведение оператора удаления на объекте хоста непредсказуемо. И это поведение на самом деле не ошибочно: (по стандарту), объекту хоста разрешено реализовать любое поведение для нескольких операторов, таких как чтение (внутренний [get]] метод), метод записи (внутренний [[put]]) и удаление (внутренний [[delete]] метод). Эта грация для пользовательского [[удалить]] поведение делает объект хоста таким запутанным.
Мы видели некоторые причуды IE, где удаление определенных объектов (которые, очевидно, реализованы в виде объектов хоста), будет выносить ошибки. Некоторые версии Firefox будут бросать при удалении Window.location. Когда операнды являются хост -объектами, вы не можете доверять возвратной стоимости удаления. Посмотрим, что происходит в Firefox:
Кода -копия выглядит следующим образом:
/ * «Оповещение» - это прямое свойство `window` (если мы поверили` hasownproperty`) *//
window.hashownproperty ('alert'); // истинный
Удалить window.alert; // истинный
typeof window.alert; // "функция"
Delete Window.Alert возвращает True, даже если нет причин, чтобы это свойство вообще вызвало такой результат. Это будет решается к ссылке (так что он не вернет True на первом шаге). Это прямое свойство окно -объекта (поэтому он не вернет истин во втором шаге). Таким образом, единственный случай, когда Delete может вернуть True, - это достичь четвертого шага и фактически удалить это свойство. Однако это свойство никогда не удаляется.
Мораль этой истории: никогда не доверяйте объекту хозяина.
ES5 строгий режим:
Итак, что приносит нам строгий режим Ecmascript5? Это вводит мало ограничений. Когда выражение оператора удаления является прямой ссылкой на переменную, параметр функции или идентификатор функции, будет выброшена синтаксическая ошибка. Кроме того, если свойство имеет внутреннее свойство [[[настраивается]] == false, будет выброшена ошибка типа.
Кода -копия выглядит следующим образом:
(function (foo) {
«Использовать строго»; // включить строгий режим в этой функции
var bar;
function baz () {}
Удалить foo; // синтаксисерсор (при удалении аргумента)
Удалить бар; // синтаксисерсор (при удалении переменной)
Удалить баз; // SyntaxError (при удалении переменной, созданной с объявлением функции)
/ * `длина` экземпляров функции имеет {[[[настраивается]]: false} *//
delete (function () {}). Length; // typeError
}) ();
Кроме того, удаление невернованных переменных (или неразрешенных ссылок) также будет выбросить синтаксические ошибки:
«Использовать строго»;
удалить i_dont_exist; // синтаксисерсор
Необъявленное назначение ведет себя так же, как и не объявленные переменные в строгом режиме (за исключением на этот раз, он увеличивает ошибку цитаты вместо синтаксической ошибки):
«Использовать строго»;
i_dont_exist = 1; // reveliceError
Как вы понимаете сейчас, все ограничения имеют более или менее смысл, потому что удаление переменных, объявлений функций и параметров может вызвать такую большую путаницу. Вместо того, чтобы молча игнорировать операцию удаления, строгая картина принимает более радикальную и описательную меру.
Суммировать:
Этот пост в блоге оказался довольно длинным, поэтому я не собираюсь говорить о чем -то вроде использования Delete для удаления объекта массива или о том, что это значит. Вы можете ссылаться на специальное объяснение статьи MDC (или прочитать стандарты и провести свои собственные эксперименты).
Вот краткое изложение того, как работают операции по удалению в JavaScript:
Переменные и объявления функций являются свойствами активных объектов или глобальных объектов
Атрибуты имеют некоторые характеристики, а DontDelete - это атрибут, который определяет, можно ли удалить этот атрибут.
Переменные и функциональные объявления в глобальном коде или функции всегда создают атрибуты с атрибутами DontDelete.
Параметры функции всегда являются атрибутами активного объекта и сопровождаются DontDelete.
Переменные и функции, объявленные в коде Eval, всегда создают свойства без DontDelete.
Новые свойства не имеют никаких атрибутов, когда они создаются (конечно, нет никакой DontDelete).
Объект хоста разрешается самим решать, как отреагировать на операцию удаления.
Если вы хотите быть более знакомым с тем, что здесь описано, см. Спецификацию 3-го издания ECMA-262.
Я надеюсь, что вы сможете насладиться этой статьей и узнать что -то новое. Любые вопросы, предложения или исправления приветствуются.