JS: почему удаление неопределенного возвращает false, а удаление других базовых типов данных возвращает true

#javascript #node.js

#javascript #node.js

Вопрос:

Итак, я просто играл в Node.js командная строка и вспомнил, что undefined это не зарезервированное ключевое слово в JS, и вполне допустимо объявлять переменную с именем undefined , подобным

 let undefined = 7;
  

Я объявил эту переменную, но, увидев, что Node.js не переопределяет undefined значение по умолчанию (иначе говоря, переменная существует, но к ней нельзя получить доступ, поскольку она использует undefined по умолчанию), я попытался удалить ее, используя delete инструкцию. Мой вывод выглядел так:

 > delete undefined
false
  

Это вызвало у меня любопытство, поскольку я никогда не видел, чтобы удаление возвращало false в Node.js CL (он даже возвращает true, если вы пытаетесь удалить необъявленные переменные или что-то подобное delete asdasddsa ).

Теперь я попробовал, что произойдет, если я использую это как

 > delete null
true
  

Это также работает для всех других примитивных значений, таких как true , 1 или "string" .

Итак, почему это возвращает false, но возвращает true для null? Мне просто любопытно и я пытаюсь глубже понять, как работает язык

Комментарии:

1. 12.5.3 delete Оператор -> 12.5.3.2 Семантика среды выполнения: оценка -> Шаги 3, 4b, 5e

2. Если вы посмотрите на результат Object.getOwnPropertyDescriptor(self, 'undefined') , вы увидите, что configurable это false означает, что свойство не может быть изменено или удалено.

3. Эти строки кода на самом деле ничего не делают, delete удаляют свойства объекта, а не объекты или примитивы. Семантика среды выполнения, на которую ссылается Андреас, объясняет возвращаемые значения.

4. Ах, я понимаю, спасибо за объяснение. Я знаю, что вы можете сделать свойства не конфигурируемыми с помощью Object.freeze или Object.defineProperty , но есть ли какие-либо более естественные случаи этого? До сих пор я не сталкивался ни с одним

5. Вы можете использовать это Object.keys(self).filter(k => !Object.getOwnPropertyDescriptor(self, k).configurable) , чтобы получить массив всех свойств, которые не настраиваются.

Ответ №1:

Поведение определено в 12.5.3.2 Семантика среды выполнения: оценка delete оператора, а точнее, на шагах 3, 4b и 5e

  1. Пусть ref будет результатом вычисления UnaryExpression .
  2. ReturnIfAbrupt(ref) .
  3. Если Type(ref) это не ссылка, верните true .
  4. Если IsUnresolvableReference(ref) равно true , то
    a. Утверждение: IsStrictReference(ref) есть false .
    b. Return true .
  5. Если IsPropertyReference(ref) равно true , то
    a. Если IsSuperReference(ref) есть true , создайте ReferenceError исключение.
    b. Пусть baseObj будет ! ToObject(GetBase(ref)) .
    c. Пусть deleteStatus будет ? baseObj.[[Delete]](GetReferencedName(ref)) .
    d. Если deleteStatus есть false и IsStrictReference(ref) есть true , создайте TypeError исключение.
    e. Return deleteStatus .
  6. Else,
    a. Assert: ref является ссылкой на привязку записи среды.
    b. Пусть bindings будет GetBase(ref) .
    c. Return ? bindings.DeleteBinding(GetReferencedName(ref)) .

Примечание
Когда delete оператор возникает в коде строгого режима, выдается SyntaxError исключение, если оно UnaryExpression является прямой ссылкой на переменную, аргумент функции или имя функции. Кроме того, если delete оператор встречается в коде строгого режима и свойство, подлежащее удалению, имеет атрибут { [[Configurable]]: false } , TypeError генерируется исключение.