在Javascript中创建相同原型的不同实例

时间:2017-04-07 14:50:47

标签: javascript classloader prototypal-inheritance static-variables

我想在Javascript中创建相同原型的2个不同“实例”。请注意,这里的“实例”一词并不是指“实例化的类”,而是指两个不同的类实例(例如,一个特定的类以Java术语从2个不同的类加载器加载)。

假设我有这个对象:

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.staticPropertychild2.method.staticProperty

具有不同的

您可能会问为什么需要这样做?在函数属性中存储状态确实是错误的,但上面的代码来自Typescript编译器,它编译“类静态”作为JavaScript构造函数的属性。我需要的是为同一个类名设置不同的静态值。

请注意,在我的情况下,protoObj本质上是一个javascript applicationApi(一个20K行文件),我们的目标是能够在只加载一次库时创建应用程序的2个不同实例。

4 个答案:

答案 0 :(得分:0)

静态属性是类级属性,静态属性的更改将反映给每个子级相同。 正如您在打印非静态变量时所看到的那样,答案是正确的,但是当您打印静态变量时,输出具有相同的值。 ** child1,child2是不同的实例,但具有相同的静态

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

试试这个....当创建一个新的protoObj对象时,这个新对象将从构造函数的原型中“继承”childObj方法,并可以使用。

答案 1 :(得分:0)

您需要为每个静态实例&#39;实例化静态属性。

这利用了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);

答案 2 :(得分:0)

执行此操作的唯一方法是每次在构造函数中创建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

答案 3 :(得分:0)

  

我的目标是child1.method.staticPropertychild2.method.staticProperty

的值不同

只有在两种方法不同的情况下才有可能,所以你的对象继承了两个原型对象 - 如果没有创建两个protoObj或者克隆它就不可能实现,你说你不会这样做。 ; t想要。

  

请注意,在我的情况下,protoObj本质上是一个javascript applicationApi(一个20K行文件),我们的目标是能够创建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库的设计存在错误。

  

...只加载一次库。

只需发送相应的缓存标头即可隐式完成。