javascript 对象委托

javascript object delegation

我正在学习 javascript 中的 classes 并且我是 运行 以下代码
这是 main.js

var dog1 = new Dog("a",1);
var dog2 = new Dog("b",2);

dog1.howl();
dog1.howl = function(){
  console.log("test");
};
dog2.howl();

dog1.howl = null;
dog1.howl();

这是Dog.js子class

function Dog (name,legs) {
    Animal.call(this,name);
    this.legs = legs;
}
Dog.prototype = Object.create(Animal.prototype);
//Dog.prototype.constructor = Dog;
Dog.prototype.howl = function(){
    console.log("woef"+ this.name + " :" + this.legs);
};

最后是Animal.js,这是超级class

function Animal(name){
    this.name = name;
}
Animal.prototype.howl = function(){
    console.log("i can only howl"+ this.name);
};

我期望得到的结果是

woefa :1
test
i can only howla

但我得到了

woefa :1
woefb :2
Main.js:11 Uncaught TypeError: dog1.howl is not a function

我希望通过删除函数对象委托将调用 super 中的 howl 函数 class 但显然这不会发生。
我犯了哪个错误,我的问题的解决代码是什么?

因为在dog1.howl = null;中你只是将嚎叫设置为null,并没有删除它,所以当你在dog1.howl();中时javascript会尝试调用null 作为函数,因为 null 不是函数,它会抛出该错误。

逐行描述:

var dog1 = new Dog("a",1);
var dog2 = new Dog("b",2);

dog1.howl();  // It'll use its prototype's howl, which will howls woefa :1
dog1.howl = function(){
  console.log("test");
};
dog2.howl();  // new howl function defined for dog1 will only affect dog1, so dog2 still howls : woefb :2

dog1.howl = null; // Assign null to howl property.
dog1.howl();      // As null is not function, error is throw.

你应该做的是

// Remove dog1's howl property from itself, so now it'll use the prototypes'howl function.
delete dog1.howl;

如果你想让 dog1 嚎叫到 i can only howla,你必须让 Animal 的嚎叫功能可见,因为 Dog.prototype.howl 将首先被发现,你需要删除 Dog.prototype 的嚎叫(导致所有狗现在都像动物一样嚎叫)或创建一个新的嚎叫,遍历到可以嚎叫的原始对象:

function Animal(name){
    this.name = name;
}
Animal.prototype.howl = function(){
    console.log("i can only howl"+ this.name);
};

function Dog (name,legs) {
    Animal.call(this,name);
    this.legs = legs;
}
Dog.prototype = Object.create(Animal.prototype);
//Dog.prototype.constructor = Dog;
Dog.prototype.howl = function(){
    console.log("woef"+ this.name + " :" + this.legs);
};

var dog1 = new Dog("a",1);
var dog2 = new Dog("b",2);

dog1.howl();

console.log('howl before set:', dog1.howl === dog2.howl); // This would be true, as they both reference to their prototype.

dog1.howl = function(){
  console.log("test");
};

// This would always be true, as you have same prototype.
console.log(dog1.__proto__.howl === dog2.__proto__.howl);

// This would be false, as dog1 now use a new assigned one, while dog2 use the prototype one.
console.log('howl after set:', dog1.howl === dog2.howl); 
dog2.howl();
delete dog1.howl;

console.log("howl after delete:", dog1.howl === dog2.howl); // This would be true

// Make all the dogs able to howl like animal..
Dog.prototype.originHowl = function() {
    var current = this;
    var parent = Object.getPrototypeOf(current);
    // Traverse up prototype chain and break until the parents can't howl.
    while(parent.howl && parent.howl instanceof Function) {
        current = parent;
        parent = Object.getPrototypeOf(current);
    }
    current.howl.call(this);
};

dog1.originHowl();