Создание другого экземпляра одного и того же прототипа в Javascript

Я хотел бы создать 2 разных "экземпляра" одного и того же прототипа в Javascript. Обратите внимание, что слово "экземпляры" здесь относится не к "экземплярам классов", а к двум отдельным экземплярам классов (например, один конкретный класс, который был загружен из 2 разных загрузчиков классов в терминах Java).

Предполагая, что у меня есть этот объект:

var protoObj = {
  prop: "",
  method: function () {
    // do stuffz
  }
}

protoObj.method.staticProperty = 0;

function childObj (prop)  {
  this.prop = prop;
}
childObj.prototype = protoObj;

var child1 = new childObj("First Child");
var child2 = new childObj("Second Child");

console.log("Prop:", child1.prop); //prints "Prop: First Child"
console.log("Prop:", child2.prop); //prints "Prop1: Second Child"

child1.method.staticProperty = 1;
child2.method.staticProperty = 2;

console.log("Child1 Static:", child1.method.staticProperty); //prints "Child1 Static: 2" <-- I wanted this to be 1. I want each instance to have its own "parent"
console.log("Child2 Static:", child2.method.staticProperty); //prints "Child2 Static: 2"

Моя цель для child1.method.staticProperty иметь другое значение от child2.method.staticProperty

Вы можете спросить, зачем это нужно? Сохранение состояния в свойствах функции действительно неверно, но приведенный выше код взят из компилятора Typescript, который компилирует "Статику класса" как свойства функций конструктора JavaScript. Мне нужно иметь разные статические значения для одного и того же имени класса.

Обратите внимание, что в моем случае protoObj по сути является javascript applicationApi (20-строчный файл), и наша цель состоит в том, чтобы иметь возможность создавать 2 отдельных экземпляра приложения при загрузке библиотеки только один раз.

4 ответа

Решение

Моя цель для child1.method.staticProperty иметь другое значение от child2.method.staticProperty

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

Обратите внимание, что в моем случае protoObj по сути является javascript applicationApi (20-строчный файл), и наша цель - создать 2 разных экземпляра приложения.

Включите файл сценария дважды, чтобы выполнить его дважды и создать два отдельных объекта:

<script type="text/javascript" src="applicationApi.js"></script>
<script type="text/javascript">
    console.assert(childObj.prototype == protoObj);
    var firstInstance = childObj;
    protoObj.method.staticProperty = 1;
</script>
<script type="text/javascript" src="applicationApi.js"></script>
<script type="text/javascript">
    console.assert(childObj.prototype == protoObj);
    var secondInstance = childObj;
    protoObj.method.staticProperty = 2;
</script>
<script type="text/javascript">
    console.log(new firstInstance);
    console.log(new secondInstance);
    console.log(firstInstance !== secondInstance);
</script>

Однако обратите внимание, что необходимость сделать это предполагает ошибку в дизайне библиотеки API.

… При загрузке библиотеки только один раз.

Просто отправьте соответствующие заголовки кэширования, и это будет сделано неявно.

Вам нужно создать экземпляр статического свойства для каждого "статического экземпляра".

Это использует преимущества динамического характера javascripts и фактически перезаписывает.method экземпляром самого себя.

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

var protoObj = {
  prop: "",
  method: function () {
    // do stuffz
  }
}

protoObj.method.staticProperty = 0;

function childObj (prop)  {
  this.prop = prop;
}
childObj.prototype = protoObj;

var child1 = new childObj("First Child");
var child2 = new childObj("Second Child");
var child3 = new childObj("Third Child");

console.log("Prop:", child1.prop); //prints "Prop: First Child"
console.log("Prop:", child2.prop); //prints "Prop: Second Child"
console.log("Prop:", child3.prop); //prints "Prop: Second Child"

child1.method = new child1.method();
child1.method.staticProperty = 1;
child2.method = new child2.method();
child2.method.staticProperty = 2;

console.log("Child1 Static:", child1.method.staticProperty); //prints "Child1 Static: 2" <-- I wanted this to be 1. I want each instance to have its own "parent"
console.log("Child2 Static:", child2.method.staticProperty);
console.log("Child3 Static:", child3.method.staticProperty);

Единственный способ сделать это - создать новый экземпляр method каждый раз в конструкторе. В основном двигаться method из прототипа и в конструктор:

var protoObj = {
  // some share stuff
}

function childObj (prop)  {
  // non-shared stuff:
  this.prop = prop;
  this.method = function () {
    // do stuffz
  }
  this.method.staticProperty = 0;
}

childObj.prototype = protoObj;

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

function Foo () {}
Foo.prototype = {
  a: "no problem",
  b: {
    x: "problem"
  }
}

var i = new Foo();
var j = new Foo();
var k = new Foo();

i.a += " 1";
j.a += " 2";
k.a += " 3";

console.log(i.a , j.a , k.a); // no problem 1, 2, 3

i.b.x += " 1";
j.b.x += " 2";
k.b = { x: "problem 3" };

console.log(i.b.x , j.b.x , k.b.x); // problem 2, 2, 3

Если вы будете следовать правилу, чтобы использовать прототипы только для свойств строк, чисел и логических значений, у вас не будет проблем:

function Foo () {
  this.b = {
    x: "no problem"
  };
}
Foo.prototype = {
  a: "no problem"
}

i.b.x += " 1";
j.b.x += " 2";
k.b = { x: "no problem 3" };

console.log(i.b.x , j.b.x , k.b.x); // no problem 1, 2, 3

Статическое свойство - это свойство уровня класса, и изменение статического свойства будет отражено для каждого дочернего элемента одинаково. Как вы можете видеть в вашем случае, когда вы печатаете нестатическую переменную, ответ правильный, но когда вы печатаете статическую переменную, вывод имеет то же значение. **child1, child2 - разные экземпляры, но имеющие одинаковые статические

   protoObj.prototype.childObj = function() {
      console.log("Downloading protoObj ...");
   }

Попробуйте это.... Когда создается новый объект protoObj, этот новый объект "наследует" метод childObj от прототипа функции конструктора и становится доступным для использования.

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