带剔除的对象继承 属性

Object inheritance with a knockout property

我有如下js继承示例:

function Fruit(){
  this.who = function(){ console.dir(this.fruitName); }
}
Fruit.prototype.fruitName = "I am a fruit";

function Orange(){
  Fruit.call();
  this.fruitName = "I am an orange";
}
Orange.prototype = new Fruit();
Orange.prototype.constructor = Orange;

function Apple(){
  Fruit.call();
  this.fruitName = "I am an apple";
}
Apple.prototype = new Fruit();
Apple.prototype.constructor = Orange;

var orange = new Orange();
var apple = new Apple();
orange.who();
apple.who();

上面的代码输出:

I am an orange
I am an apple

哪个是正确的。

现在,将 fruitName 更改为可观察到的淘汰赛会产生意想不到的结果:

function Fruit(){
  this.who = function(){ console.dir(this.fruitName()); }
}
Fruit.prototype.fruitName = ko.observable("I am a fruit");

function Orange(){
  Fruit.call();
  this.fruitName("I am an orange");
}
Orange.prototype = new Fruit();
Orange.prototype.constructor = Orange;

function Apple(){
  Fruit.call();
  this.fruitName("I am an apple");
}
Apple.prototype = new Fruit();
Apple.prototype.constructor = Orange;

var orange = new Orange();
var apple = new Apple();
orange.who();
apple.who();

输出:

I am an apple
I am an apple

除非我做错了什么,否则这看起来像是 Knockout 中的错误。 有办法解决这个问题吗?

此处提供完整的 jsfiddle:https://jsfiddle.net/h1go9se2/

怎么回事

原型的想法是它在实例之间共享。函数使用 this 来确保 运行 方法实际影响单个实例。

Knockout observables 是函数,但最好将它们视为值的包装器。

如果你在原型上定义你的可观察对象,这意味着你包装了一个由所有实例共享的值。

在扩展它的任何 class 的构造函数中写入该值将覆盖所有实例的值。

修复

不是在 Fruit 原型上声明 fruitName,而是在 Fruit 构造函数中定义 属性:

function Fruit(){
  this.who = function(){ console.dir(this.fruitName()); }
  this.fruitName = ko.observable("I am a fruit");
}

可运行代码段:

function Fruit(){
  this.who = function(){ console.dir(this.fruitName()); }
  this.fruitName = ko.observable("I am a fruit");
}

function Orange(){
  Fruit.call();
  this.fruitName("I am an orange");
}
Orange.prototype = new Fruit();
Orange.prototype.constructor = Orange;

function Apple(){
  Fruit.call();
  this.fruitName("I am an apple");
}
Apple.prototype = new Fruit();
Apple.prototype.constructor = Orange;

var orange = new Orange();
var apple = new Apple();
orange.who();
apple.who();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>