【问题标题】:Override this.method = function() inside of a var x = function()在 var x = function() 中覆盖 this.method = function()
【发布时间】:2023-03-21 17:07:01
【问题描述】:

我有一个 Javascript 对象:

var Dog = function() {
    this.speak = function() {
        return 'woof'
    }
    this.trick = function() {
        return 'sitting' 
    }
}

我想创建一个新对象 Cat,它基于 Dog 但具有不同的speak 方法:

var Cat = ???
    ...
    this.speak = function() {
        return 'meow'
    }
    ...

所以我最终可以做到这一点:

var tabby = new Cat();

tabby.speak() //returns 'meow'
tabby.trick() //returns 'sitting'

我对“面向对象的 Javascript”几乎没有经验,似乎无法在网上找到反映我想要做什么的示例,也不知道要搜索哪些关键字。

我认为这与我在 Backbone 中覆盖函数的方式类似,但这似乎不同:

var Cat = Dog.extend({
    //the speak function below would override the one that returns 'woof'
    speak: function() {
        return 'meow'
    }
});

感谢任何帮助!

(以上是我最终目标的简化版本 - 我想覆盖 Rickshaw.Graph.Axis.X 内部的 render 方法)

【问题讨论】:

标签: javascript oop prototype


【解决方案1】:

通常在 JavaScript 中,我们会在原型上定义方法,而不是在实例上:

function Dog() {}
Dog.prototype.speak = function () {
    return 'woof';
};
Dog.prototype.trick = function () {
    return 'sitting';
};

在原型和实例上定义方法的区别在于,原型允许您在所有将其原型设置为同一对象的对象之间共享属性。这个对象是你定义共享哪些属性的地方,一个原型对象也可以有自己的原型,创建一个原型链。

为了创建一个简单的例子,我们来看一个简单的例子:

var foo = { bar: 1 };

// create a new object with its prototype set to `foo`
var baz = Object.create(foo);

console.log(foo.bar); // 1
console.log(baz.bar); // 1

// prototype properties and values are shared
foo.bar = 2;

console.log(foo.bar); // 2
console.log(baz.bar); // 2

// this is an instance property, so the property is no longer shared
baz.bar = 3; 

console.log(foo.bar); // 2
console.log(baz.bar); // 3

如果你有一个原型继承系统,你会这样做:

function Dog() {}
Dog.prototype.speak = function () {
    return 'woof';
};
Dog.prototype.trick = function () {
    return 'sitting';
};

function Cat() {}
Cat.prototype = Object.create(Dog.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.speak = function () {
    return 'meow';
};

请记住,如果您在实例上定义属性,它将覆盖原型上设置的属性、原型的原型等等。


如果您正在寻找针对您在实例上定义方法的特定情况的答案(并且它不是内置构造函数 - 有些具有特殊行为),您需要做一些事情不同:

function Cat() {
    Dog.call(this);
    this.speak = function () {
        return 'meow';
    };
}

它的作用是为Dog 函数提供Cat 实例的当前对象,它可以在其上设置属性。这是通过将Dog 中的this 的值设置为Cat 的实例来完成的,仅用于使用func.call(/* value of this */); 的调用。

【讨论】:

    【解决方案2】:

    鉴于您目前的方法,您可以这样做:

    var Dog = function() {
        this.speak = function() {
            return 'woof'
        }
        this.trick = function() {
            return 'sitting' 
        }
    }
    
    var Cat = function() {
        Dog.call(this)
    
        this.speak = function() {
            return 'meow'
        }
    }
    

    虽然我们在这里没有使用原型继承。我们只是将自己的属性直接分配给对象。这比使用共享的继承方法效率低。更何况CatDog上创建了speak方法,然后立即覆盖。

    var tabby = new Cat();
    
    tabby.speak() //returns 'meow'
    tabby.trick() //returns 'sitting'
    

    【讨论】:

      【解决方案3】:
      function Dog() {}
      
      Dog.prototype.speak = function() {
        return 'woof';
      };
      
      Dog.prototype.trick = function() {
        return 'sitting';
      };
      
      function Cat(){}
      
      Cat.prototype = Object.create(Dog.prototype);
      
      Cat.prototype.speak = function() {
        return 'meow';
      };
      
      var fluffy = new Cat();
      
      fluffy.speak(); // 'meow'
      fluffy.trick(); // 'sitting'
      

      基本上,您想在谷歌上搜索“原型继承”。

      【讨论】:

        【解决方案4】:

        与其他答案的概念相同,但这里是 javascript 秘密从 google 闭包继承函数 略微简化 - https://code.google.com/p/closure-library/source/browse/closure/goog/base.js#1578

         var inherits = function(child, parent) {
            function tmp () {};
            tmp.prototype = parent.prototype;
            child.superClass_ = parent.prototype;
            child.prototype = new tmp;
            child.prototype.constructor = child;
          };
        

        现在可以

        var Dog = function() {};
        Dog.prototype.speak = function(){
            return 'woof';
        }
        Dog.prototype.trick = function(){
          return 'sitting';   
        }
        
        var Cat = function(){};
        inherits(Cat, Dog); //weird
        Cat.prototype.speak = function(){
                return "meow";
        };
        
        
        var HouseCat = function(){};
        inherits(HouseCat, Cat);
        HouseCat.prototype.speak = function(){
           return "purr";
        };
        
        
        var dog = new Dog();
        var cat = new Cat();
        var houseCat = new HouseCat();
        
        
        console.log(dog.speak());  //woof
        console.log(cat.speak());  //meow
        console.log(houseCat.speak());  //purr
        console.log(houseCat.trick());  //sitting
        console.log(cat instanceof Dog);  //true
        console.log(houseCat instanceof Cat);  //true
        console.log(houseCat instanceof Dog);  //true
        console.log(dog instanceof Cat);  //false
        console.log(cat instanceof HouseCat);  //false    
        

        【讨论】:

          猜你喜欢
          • 2011-10-18
          • 2014-04-12
          • 2014-11-16
          相关资源
          最近更新 更多