#javascript #inheritance #constructor #prototype
#javascript #наследование #конструктор #прототип
Вопрос:
let bar;
function foo(){
this.x=x;
this.y=y;
}
bar=new foo(1,2);
/*Since all functions in javascript are objects.
Why can't an instance an object be a constructor itself?*/
!function bar(a,b){
this.a=a;
this.b=b;
}(); // (1)
let bar1=new bar(3,4);
console.log(bar1.a);
(1): Используя именованный IIFE, может ли bar быть экземпляром и конструктором одновременно?
Это просто забавный трюк, позволяющий использовать свободу языка, чтобы увидеть, возможно ли это, какие-либо другие способы сделать это?
Комментарии:
1. ваш код выдаст ошибку (
let bar
повторное объявление) — итак, очевидно, что вы не можете этого сделать2. Тогда как насчет использования именованного функционального выражения, такого как
(function bar(a,b){this.a=a, this b=b}());
Ответ №1:
Похоже, вы ищете функцию, возвращающую функцию-конструктор:
function makeBar(x, y) {
function Bar(a, b) {
this.a = a;
this.b = y b;
}
Bar.x = x;
return Bar;
}
var Bar1 = makeBar("bar1", 2);
console.log(Bar1.x); // "bar1"
var myBar1 = new Bar1(1, 2); // Bar { a: 1, b: 4 }
console.log(myBar1 instanceof Bar1); // true
var Bar2 = makeBar("bar2", 0);
var myBar2 = new Bar2(3, 3); // Bar { a: 3, b: 3 }
console.log(myBar2 instanceof Bar1); // false
Чтобы создать makeBar
не фабричную функцию, а конструктор с работающим прототипом, вам нужно будет использовать
function Foo(x, y) {
function Bar(a, b) {
this.a = a;
this.b = y b;
}
Object.setPrototypeOf(Bar, Foo.prototype);
Bar.x = x;
return Bar;
}
Foo.prototype.log = function() {
console.log("I'm " this.name);
};
var Bar = new Foo("bar", 2);
Bar.log();
console.log(Bar instanceof Foo); // true
var myBar = new Bar(1, 2);
console.log(myBar instanceof Bar); // true
Комментарии:
1. Это частично точно, здесь все экземпляры Foo будут возвращать Bar ,
var myFoo=new Foo(1,2);
выполняет « myFoo.y===Bar.yreturn true? Is myFoo pointing to a new private data
y«Bar
конструктора или это свойство экземпляраFoo
2. @PranavRaykar Каждый
Foo
вызов будет возвращать новыйBar
. Вы можете это видетьBar1 !== Bar2
.x
является свойством экземпляра для всехFoo
«instaces», напримерa
, иb
являются свойствамиBar
экземпляров.y
является частной переменной закрытия (чтобы продемонстрировать, что разныеBar
s выполняют разные вещи — иначе упражнение было бы бессмысленным).
Ответ №2:
Может ли экземпляр JavaScript сам быть конструктором и иметь свой собственный набор экземпляров?
Конечно, функция — это экземпляр Function
, а конструктор — это функция.
Таким образом, вы можете просто иметь
const instance1 = new Function("a", "this.a = a;");
const instance2 = new instance1("foo");
console.log(instance2.a); // "foo"
Если вам нужно instance1
быть чем-то большим, чем необработанная функция, вы даже можете расширить этот конструктор:
class MyFunc extends Function {
doSomethingMore(){ console.log("I'm doing more"); }
}
const instance1 = new MyFunc("a", "this.a = a;");
instance1.doSomethingMore();
const instance2 = new instance1("foo");
console.log(instance2.a); // "foo"
Но я не вижу четкой причины, по которой вы когда-либо хотели бы это сделать…
(Обратите внимание, что динамическое создание функции с помощью Function
конструктора обычно менее «производительно», чем во время синтаксического анализа с помощью выражения функции или оператора.)
Ответ №3:
В вашем коде, поскольку bar
объявляется с let
помощью, он не может быть повторно объявлен как объявление функции в той же области.
Если вы хотите это сделать, вы могли бы foo
явно вернуть функцию, которую затем можно было бы вызвать с помощью new
:
function foo(x, y) {
this.x = x;
this.y = y;
return function bar(a, b) {
this.a = a;
this.b = b;
};
}
const bar = new foo(1, 2);
const bar1 = new bar(3, 4);
console.log(bar1.a);
Комментарии:
1. Но здесь bar является свойством экземпляра foo , это не экземпляр foo
2.
bar
не является свойством экземпляраfoo
—foo
возвращаетbar
конструктор.3. Так что это не то, чего я хотел, поэтому суперинсталляция никогда не может сама быть конструктором, верно?