【问题标题】:Overriding methods in JavascriptJavascript中的重写方法
【发布时间】:2013-03-07 23:53:49
【问题描述】:

我想知道使用原型和不使用原型的重写方法有什么区别。考虑:

示例 1:

function Animal() {
    this.sleep = function () {
        alert("animal sleeping");
    };

    this.eat = function () {
        alert("animal eating");
    };
}

function Dog() {
    this.eat = function () {
        alert("Dog eating");
    };
}

Dog.prototype = new Animal;

var dog = new Dog;

dog.eat();

示例 2:

function Animal() { }

function Dog() { }

Animal.prototype.sleep = function () {
    alert("animal sleeping");
};

Animal.prototype.eat = function () {
    alert("animal eating");
};

Dog.prototype = new Animal;

Dog.prototype.eat = function () {
    alert("Dog eating");
};

var dog = new Dog;

dog.eat();

我觉得这两个例子产生了相同的效果,Dog 类覆盖了Animal 类的 eat 方法。或者发生了什么不同的事情?

【问题讨论】:

  • 在构造函数中定义对象的属性时,应该使用this关键字。
  • @Sann 抱歉错过了 this 关键字。现在编辑问题。
  • 将方法放在原型上几乎总是一个好主意,因为它们会在所有实例之间共享。将它们放在您的构造函数中会将它们复制到所有实例中,这会消耗更多内存。
  • 那么除了内存问题,还有其他问题吗?
  • @DeepakMahalingam - 在构造函数中声明为 this 属性的函数可防止构造函数的私有变量被垃圾收集,即使它们本身可能不会关闭任何私有变量。但是,由于这可以归类为 内存问题,我会说:不,没有其他问题。将方法放在prototype 上只是一种流行的编码实践。

标签: javascript prototype overriding


【解决方案1】:

第一个例子中的方法是在对象实例中定义的。

您正在将Dog 原型设置为新的Animal 实例,因此Dog 将从Animal 继承sleepeat 函数。然后你DEFINING(不是OVERRIDINGDog构造函数中的eat方法作为实例方法,这将HIDE继承Dog 实例中的 eat 方法。

考虑以下示例:

function LittleDog() { }
LittleDog.prototype = Object.create(Dog.prototype);
(new LittleDog()).eat();

上面的代码将在第一个示例中向animal eating 发送您的代码。

并且会在第二个代码中提醒Dog eating

【讨论】:

    【解决方案2】:

    正如 Arun 在第一个示例中提到的,您正在为每个新实例创建 sleepeat 函数。在第二个示例中,只有一个 sleepeat 函数在所有实例之间共享。

    在这种情况下,第二种方法更好,但最好知道何时使用第一种方法以及何时使用第二种方法。先说一点理论:

    注意:JavaScript中有四种变量——privatepublicsharedstatic

    私有变量在定义它们的函数之外是不可访问的。例如:

    function f() {
        var x; // this is a private variable
    }
    

    公共变量在函数内的this 对象上定义。例如:

    function f() {
        this.x; // this is a public variable
    }
    

    共享变量在函数的prototype 上共享。例如:

    function f() {}
    
    f.prototype.x; // this is a shared variable
    

    静态变量是函数本身的属性。例如:

    function f() {}
    
    f.x; // this is a static variable
    

    通常最好将构造函数的方法声明为共享方法,因为构造函数的所有实例共享它们。但是,如果您的方法需要访问私有变量,则必须将它本身声明为公共方法。

    注意:这是我自己的命名法。没有多少 JavaScript 程序员坚持它。其他人似乎遵循 Douglas Crockford 的命名法:http://javascript.crockford.com/private.html

    要了解有关 JavaScript 中原型继承的更多信息,请阅读以下答案:https://stackoverflow.com/a/8096017/783743

    【讨论】:

      【解决方案3】:

      在您的第一个示例中,每个新的 Dog 实例都有自己的 eat 方法,而在第二个示例中,Dog.prototype 上只有一个 eat 方法,它将在所有未来的 @ 实例之间共享987654325@ 就像 Arun 提到的那样。

      这是两者之间唯一的“棘手”区别。但最好在prototype 上定义方法以避免高内存消耗和泄漏。

      【讨论】:

        【解决方案4】:

        在第一个方法中,每个Animal 实例都将获得自己的sleepeat 方法实现。

        在第二个模型中,所有实例将共享sleepeat 方法的同一个实例。

        第二个模型更好,因为我们可以共享方法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-04-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-23
          • 2016-11-27
          • 1970-01-01
          相关资源
          最近更新 更多