Причиной ошибки синтаксиса строгого режима при удалении неквалифицированного идентификатора?

Мне трудно понять, почему в строгом режиме возникает синтаксическая ошибка, когдаdelete используется для неквалифицированного идентификатора.

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

Однако есть случаи, когда выcan't удалить идентификаторы, которыеare квалифицированный:

(function() {

  // "use strict";

  var obj = Object.create({}, { bloop: { configurable: false } });

  delete obj.bloop; // throws TypeError in strict mode, silently fails in non-strict.

  console.log('bloop' in obj); // true

}());

Строгий режим должен выполнять проверку во время выполнения, поскольку при этом возникает ошибка TypeError. Есть также случаи, когда выcan успешно удалить неквалифицированные идентификаторы в нестрогом режиме ...

// "use strict";

window.bar = 6;

console.log(typeof bar); // number

delete bar; // works in non-strict, syntax error in strict!

console.log(typeof bar); // undefined

На самом деле, насколько я понимаю, вы можете удалить вещи (в нестрогом режиме), зависит от внутреннего[[Configurable]] свойство, и не имеет ничего общего с квалифицированными идентификаторами. Насколько я могу судить, в строгом режиме нет способа удалить неглобальные переменные, которые (как свойства локального VO)are настраивается:

(function() {

  // "use strict";

  eval('var foo = 5;');

  console.log(typeof foo); // number

  delete foo; // works in non-strict, SyntaxError in strict.

  console.log(typeof foo); // undefined

}());

Итак, мой вопрос в том, какой смысл выдавать SyntaxError при использованииdelete для неквалифицированного идентификатора, когда TypeError все равно будет выдавать, если свойство не настраивается? Это кажется ненужным ограничением, и в некоторых случаях кажется, что нет другого обходного пути, кроме как не использовать строгий режим (третий пример). Кто-нибудь может объяснить мотивы этого решения?

Обновление: я только что понял, что я упускаю из виду тот факт, что прямойeval вызовы имеют строгую область видимости в строгом режиме вместо области видимости вызывающей функции, поэтому в третьем примереfoo не будет определен в строгом режиме. В любом случае, проверка во время выполнения все равно поймает это, но это поднимает побочный вопрос: нет ли способа иметь настраиваемые локальные переменные в строгом режиме, как мы делаем сeval& d; объявления переменных в нестрогих? AFAIK, который был одним из немногих законных примененийeval.

 user12344455562119 авг. 2012 г., 08:30
Что именно вы подразумеваете под «(не) квалифицированным идентификатором»? Я не могу найти этот термин в спецификации.
 Dagg Nabbit19 авг. 2012 г., 08:31
@ Pumbaa80 идентификатор без точек. :)
 Dagg Nabbit19 авг. 2012 г., 08:38
@ Pumbaa80(function(){"use strict"; var foo; delete foo;}()) ... хром:SyntaxError: Delete of an unqualified identifier in strict mode.

Ответы на вопрос(2)

Решение Вопроса

Вы говорите оРаздел 11.4.1, пункт 5.а. из спецификаций:

Else, ref is a Reference to an Environment Record binding, so
a. If IsStrictReference(ref) is true, throw a SyntaxError exception.
b. Let bindings be GetBase(ref).
c. Return the result of calling the DeleteBinding concrete method of bindings, providing GetReferencedName(ref) as the argument.

То, что вы назвали «неквалифицированными идентификаторами» официально называется «привязка к записи среды».

Теперь к вашему вопросу. Зачем выдавать SyntaxError, когда 5.c. все равно потерпит неудачу? Я думаю, что вы ответили сами!

Strict mode must do a runtime check here, because a TypeError is thrown when this is encountered.

Это верно. Но всегда лучше быстро потерпеть неудачу. Таким образом, когда есть вероятность обнаружения ошибки синтаксиса (вparse time), эта возможность должна быть использована.

Зачем? Это избавит вас от необходимости исправления вашего приложения в случае возникновения ошибки. Подумайте об IDE, которые могут сразу показать вам ошибку, а не часы отладки.
Кроме того, такие ограничения могут быть полезны для оптимизированных JIT-компиляторов.

 Dagg Nabbit19 авг. 2012 г., 11:14
Спасибо, что выкопали эту спецификацию. Имеет смысл думать об этом как об отладчике или оптимизаторе JIT. Если он будет использован таким образом, я полагаю, что это стоит того, чтобы не иметь возможности удалять вещи, которые вы могли бы сделать иначе.

ть о доступе к собственности. Также обратите внимание на то, как важно вызывать функцию. Еслиnew оператор не используетсяthis не определено подuse strict, и вы не можете использовать метод ниже. Пример:

'use strict'
function func(){
  var self = this;
  self.obj = {};
  self.obj.x = 'y'

  console.log(self.obj);
  delete self.obj // works
  // delete obj // doesn't work
  console.log(self.obj);
}

var f = new func();

Для удаления объекта вне функции (замыкание), вам нужно будет вызвать как

// same code as above
delete f.obj
 21 авг. 2012 г., 23:55
ну, алиасинг это мой стиль, можно сказать. Я использую этоthis не будет доступен в анонимных функциях, где в качестве переменнойvar self будет доступно О, оdelete obj не работает подnew - Я не знаю (я относительно новичок в JS). О, я прочитал вопрос неправильно, не берите в голову.
 Dagg Nabbit21 авг. 2012 г., 23:45
Я не уверен, в чем смысл вашего примера. Почему мы делаем псевдоним дляthis? А такжеdelete obj не будет работать в нестрогом режиме, если только вы не используетеnew, но это не похоже на предназначение кода. Если я не читаю это неправильно, этот вид кажется перефразировкой моего вопроса. +1 в любом случае за усилия и потому, что я, вероятно, просто скучаю по вашей точке;)

Ваш ответ на вопрос