Фокусы с JavaScript


Ответ будет объяснятся сразу после вопроса, так что если хотите сами подумать, не листайте. Мой ответ базируется на моем опыте и моем понимании как работает JS. Если я ошибся — поправьте, пожалуйста.

Недавно меня попросили помочь объяснить как отработает такой код. Будет ли ошибка или нет? Если ошибка, то какая ошибка и почему? А если не ошибка, то как отработает и почему?

class Foo extends null {}
const foo = new Foo;

Что получим? Как отработает? Что из себя представляет класс Foo и экземпляр класса — объект foo?


Объяснение

Во 1х будет ошибка, но не синтаксическая, а TypeError:

TypeError: Super constructor null of Foo is not a constructor

В данном классе нет конструктора. Поэтому конструктор будет искаться в родителе. Родитель у нас кто?

console.dir( Object.getPrototypeOf(Foo.prototype) ); // null

Ну надо же, родитель у класса null. А у null нет конструктора и он не может быть вызван. Но тогда другой вопрос: а почему мы можем вообще наследоваться от null ?

А потому, что:

typeof null === 'object'

Да да, в JS null это объект. А следовательно к нему применимы некоторые операции как и к Object (но не все!). Возможно это баг, но выглядит как фича. Если вы модифицируете код, добавив конструктор:

class Foo extends null {
constructor() {
console.log('call Foo.constructor')
}
}

то получите следующий результат:

0 |
1 | call Foo.constructor
2 |
3 | ReferenceError: Must call super constructor in derived class
| before accessing 'this' or returning from derived constructor
4 |

Как видим, конструктор получилось вызвать, но требуется вызов родительского. Добавляем super:

class Foo extends null {
constructor() {
console.log('call Foo.constructor')
super()
}
}

И получаем такой вот результат:

0 |
1 | call Foo.constructor
2 |
3 | TypeError: Super constructor null of Foo is not a constructor
4 |

Ну что и требовалось доказать. Такая вот небольшая вэтээфка джээска.

UPD

В принципе, если вернуть из конструктора объект, то:

class Foo extends null {
constructor() {
return Object.create(null);
}
}

то это будет даже работать и не будет ошибок. Семантичность? Ну не знаю…

Для чего знать и где применять?

Ну чисто меряться друг с другом, делать сложные quiz’ы (например такие как ReturnTrue). Возможно у вас появятся идеи как и зачем это использовать 🙂

Грязные фишки JS применяются для писькомерства