javascript对象委派

时间:2015-07-14 17:40:20

标签: javascript object inheritance delegates

我正在学习javascript中的课程,并且我正在运行以下代码 这是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子类

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,这是超类

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

我希望通过删除函数对象委托将调用超类中的howl函数,但显然不会发生这种情况。
我犯的错误是什么?问题的解决方案代码是什么?

1 个答案:

答案 0 :(得分:0)

因为在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,你必须让动物的嚎叫功能可见,因为首先会找到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();