Эксперимент: может ли экземпляр JavaScript сам быть конструктором и иметь свой собственный набор экземпляров?

#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.y return true? Is myFoo pointing to a new private data 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. Так что это не то, чего я хотел, поэтому суперинсталляция никогда не может сама быть конструктором, верно?