Создание другого экземпляра одного и того же прототипа в 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 от прототипа функции конструктора и становится доступным для использования.