Как bind работает с new и instanceof?

Вчера у меня было собеседование, и была задача написать класс JavaScript, который может быть создан с несколькими новыми и созданными объектами, которые должны быть экземпляром всех его родителей. Я пытался сделать это с помощью Function.bind (), но это не сработало.

function JSObject() {
  return JSObject.bind(null);
}

var obj1 = new JSObject();
var obj2 = new obj1();
var obj3 = new obj2();

console.info(obj2 instanceof obj1); // prints false, expected true
console.info(obj3 instanceof obj2); // prints false, expected true
console.info(obj3 instanceof obj1); // prints false, expected true

console.info(obj1 instanceof obj2); // prints false, expected false 
console.info(obj1 instanceof obj3); // prints false, expected false

let objects = [JSObject, new JSObject()];

for (let i = 0; i < 10; i++) {
  objects.push(new objects[objects.length - 1]());
}

for (let obj of objects) {
  const objProt = Object.getPrototypeOf(obj);
  const objProtProt = Object.getPrototypeOf(obj.prototype);
  const funcProt = Object.getPrototypeOf(Function);
  const funcProtProt = Object.getPrototypeOf(Function.prototype);
  console.info(objProt === funcProt); // expected true
  console.info(objProtProt === funcProtProt); // expected true
}

Кроме того, я не могу напрямую изменить прототип, тесты проверяют, что прототип объекта должен быть функцией.

Не уверен, какая именно цель здесь. Ваш конструктор всегда просто возвращает новую функцию, которая сама по себе не является конструктором (это промежуточная функция, которую возвращает bind, а не JSObject), хотя при вызове он возвращает новый экземпляр, поэтому он никогда не будет экземпляром чего-либо.

deceze 12.10.2018 17:05

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

dandavis 12.10.2018 17:45

@dandavis, если вы вернете this, как бы вы использовали его в качестве конструктора при попытке вызвать new obj1();?

Mark 12.10.2018 18:02

@MarkMeyer: поскольку формально из конструкторов могут поступать только объекты, вы не можете вернуть конструктор из конструктора, вам придется использовать фабричный шаблон.

dandavis 12.10.2018 18:04

@dandavis Верно, поэтому возврат this не решит проблему OP.

Mark 12.10.2018 18:06

да, я просто привожу некоторую предысторию, так как неясно, что OP должен здесь делать; он говорит, что console.info(obj2 instanceof obj1); должен быть ложным и истинным, что невозможно ...

dandavis 12.10.2018 18:06

Да, похоже, опечатка. Второй, вероятно, должен быть obj2 instanceof obj3

Mark 12.10.2018 18:09

@dandavis исправлено

gzaripov 12.10.2018 19:18

Что вы имеете в виду под "можно создать с несколькими новыми"? Также неясно, что должно означать «экземпляр всех его родителей» в этом контексте. Вы должны были создать простую иерархию классов?

Bergi 12.10.2018 19:29

@Bergi первый означает: var obj = new new new new new JSObject (); Я думаю, мне нужно создавать новые объекты таким образом, чтобы они унаследовали от предыдущего объекта или корня.

gzaripov 12.10.2018 19:32

@GrigoryZaripov Да, похоже (см. Мой ответ). Но это также означает, что каждый созданный объект является функцией («конструктором»), противоречит ли это требованию «Я не могу изменить прототип напрямую, тесты проверяют, что прототип объекта должен быть функцией»?

Bergi 12.10.2018 19:47

@Bergi да, это так. console.info выводит ожидаемые значения, но прототип изменен.

gzaripov 12.10.2018 20:11

@gzaripov Не могли бы вы добавить этот чек к вопросу? Но я сомневаюсь, что возможно иметь obj2, который можно использовать как с new (для которого требуется функция), так и может быть экземпляром obj1 (для которого требуется наследование от obj1.prototype) без изменения прототипа функции.

Bergi 12.10.2018 23:05

@Bergi добавил проверку.

gzaripov 13.10.2018 15:48
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
14
159
1

Ответы 1

На самом деле это не «класс», поскольку вы не можете отличить конструктор от экземпляра. Каждая функция «конструктор» просто создает новые объекты, которые сами являются «подклассами».

function inherit(parent) {
    function object() {
        return Object.setPrototypeOf(inherit(object), object.prototype);
    }
    object.prototype = Object.create(parent.prototype);
    return object;
}
var JSObject = inherit(Function);

Или используя ES6:

function inherit(parent) {
    return class object extends parent {
        constructor() {
            return Object.setPrototypeOf(inherit(object), new.target.prototype);
        }
    }
}
const JsObject = inherit(Function);

Они даже достигают obj instanceof Function и obj.prototype instanceof Function (и, конечно же, instanceof Object). Ваши дополнительные требования к Object.getPrototypeOf(obj) == Function.prototype и Object.getPrototypeOf(obj.prototype) == Object.prototype не достижимы. (Предполагается, что мы не используем прокси с отслеживанием состояния, которые обманывают ваши тесты).

Другие вопросы по теме