У меня есть следующий код:
function Complex(real, imaginary) {
let c = Object.create(Complex.methods);
[c.real, c.imaginary] = [real, imaginary];
return c;
}
Complex.methods = {
toString() {return `${this.real}+${this.imaginary}i`},
add(other) {
if (!(other instanceof Complex)) throw new Error("Only supports complex-only addition");
return Complex(this.real+other.real, this.imaginary+other.imaginary);
}
}
let c1 = Complex(2,0);
let c2 = Complex(3,4);
console.info(c1.add(c2) + "");
// "Uncaught Error: Only supports complex-only addition",
Это происходит потому, что c1 instanceof Complex
возвращается false
. Почему он возвращает ложь?
Сравните это с использованием ключевого слова class
:
class CX {
toString() {return "xxx"}
}
let c1 = new CX();
console.info(c1 + "", c1 instanceof CX);
// xxx true
Но все же любопытно, почему первый не распознает оператор instanceof
.
@PeterSeliger хорошо, если бы я вызывал его как let c1 = new Complex(2,0)
; пусть c2 = Complex(3,4);` позволит ли это мне использовать instanceof
? Или как я увижу, что c2
был создан с помощью фабрики Complex()
?
other.constructor.name
возвращает Объект, а c1.constructor.name
возвращает клиентский опыт. Попробуйте отладить его таким образом.
@RezaSaadati Понятно, хотя я не очень понимаю, не могли бы вы опубликовать ответ с некоторыми подробностями?
Вы понимаете как instanceof
работает? Непонятно, почему вы ожидаете, что объект, который наследуется от Complex.methods
, а не Complex.prototype
, будет instanceof Complex
.
OP либо выбирает классический (старый добрый) подход к функции конструктора...
function Complex(real, imaginary) {
Object.assign(this, { real, imaginary });
}
Complex.prototype.toString = function toString () {
return `${this.real} + ${this.imaginary}i`
};
Complex.prototype.add = function add (other) {
if (!(other instanceof Complex)) {
throw new Error("Only supports complex-only addition");
}
return new Complex(
this.real + other.real,
this.imaginary + other.imaginary
);
};
let c1 = new Complex(2,0);
let c2 = new Complex(3,4);
console.info(c1.add(c2) + "");
.as-console-wrapper { min-height: 100%!important; top: 0; }
... или подход, основанный на классах...
class Complex {
constructor(real, imaginary) {
Object.assign(this, { real, imaginary });
}
toString () {
return `${this.real} + ${this.imaginary}i`
}
add (other) {
if (!(other instanceof Complex)) {
throw new Error("Only supports complex-only addition");
}
return new Complex(
this.real + other.real,
this.imaginary + other.imaginary
);
}
}
let c1 = new Complex(2,0);
let c2 = new Complex(3,4);
console.info(c1.add(c2) + "");
.as-console-wrapper { min-height: 100%!important; top: 0; }
Спасибо за это. Только один вопрос: почему вы используете Object.assign(...)
, а не Object.create(...)
выше?
Object.assign(this, { real, imaginary });
то же самое, что и this.real=real; this.imaginary=imaginary
, и это просто ярлык?
Object.create
сам по себе бесполезен, если речь идет об экземплярах и операторе instanceof
. И выбор Object.assign
просто короче, если речь идет о назначении множества параметров конструктора в качестве свойств экземпляра... constructor(foo, bar, baz, biz, buz) { Object.assign(this, { foo, bar, baz, biz, buz }); }
... проще написать, чем... constructor(foo, bar, baz, biz, buz) { this.foo = foo; this.bar = bar; this.baz = baz; this.biz = biz; this.buz = buz; }
Complex
— это фабричная функция, которая создает объект черезObject.create
. Прототип этого недавно созданного объекта — это объект, который был прибит непосредственно кComplex
в качестве свойстваmethods
этой функции. Таким образом, посколькуComplex
не является функцией-конструктором (вызывается черезnew
), экземпляровComplex
также нет.