Tengo el siguiente ejemplo de herencia 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();El código anterior genera:
I am an orange I am an appleCual es correcta.
Ahora, cambiar fruitName a un observable knockout da un resultado inesperado:
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();Producción:
I am an apple I am an appleA menos que esté haciendo algo mal, esto parece un error en Knockout. ¿Hay alguna forma de solucionar este problema?
Jsfiddle completo disponible aquí: https://jsfiddle.net/h1go9se2/
La idea del prototipo es que se comparte entre instancias. Las funciones usan this para asegurarse de que la ejecución de los métodos realmente impacte en una sola instancia.
Los observables knockout son funciones, pero es mejor pensar en ellos como envoltorios alrededor de un valor.
Si define su observable en el prototipo, significa que está envolviendo un valor para ser compartido por todas las instancias.
Escribir en ese valor en el constructor de cualquier clase que lo amplíe sobrescribirá el valor para todas las instancias.
En lugar de declarar fruitName en el prototipo de Fruit , define la propiedad dentro del constructor de Fruit :
function Fruit(){ this.who = function(){ console.dir(this.fruitName()); } this.fruitName = ko.observable("I am a fruit"); }Fragmento ejecutable:
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>