JavaScript 基于原型的继承的好例子

IT技术 javascript prototypal-inheritance
2021-02-15 22:44:48

我已经使用 OOP 语言编程超过 10 年,但我现在正在学习 JavaScript,这是我第一次遇到基于原型的继承。我倾向于通过学习好的代码来学得最快。正确使用原型继承的 JavaScript 应用程序(或库)编写良好的示例是什么?你能否(简要地)描述一下原型继承是如何/在哪里使用的,所以我知道从哪里开始阅读?

6个回答

如前所述,道格拉斯·克罗克福德 (Douglas Crockford) 的电影很好地解释了原因和方法。但是把它放在几行 JavaScript 中:

// Declaring our Animal object
var Animal = function () {

    this.name = 'unknown';

    this.getName = function () {
        return this.name;
    }

    return this;
};

// Declaring our Dog object
var Dog = function () {

    // A private variable here        
    var private = 42;

    // overriding the name
    this.name = "Bello";

    // Implementing ".bark()"
    this.bark = function () {
        return 'MEOW';
    }  

    return this;
};


// Dog extends animal
Dog.prototype = new Animal();

// -- Done declaring --

// Creating an instance of Dog.
var dog = new Dog();

// Proving our case
console.log(
    "Is dog an instance of Dog? ", dog instanceof Dog, "\n",
    "Is dog an instance of Animal? ", dog instanceof Animal, "\n",
    dog.bark() +"\n", // Should be: "MEOW"
    dog.getName() +"\n", // Should be: "Bello"
    dog.private +"\n" // Should be: 'undefined'
);

然而,这种方法的问题在于,每次创建对象时它都会重新创建对象。另一种方法是在原型堆栈上声明您的对象,如下所示:

// Defining test one, prototypal
var testOne = function () {};
testOne.prototype = (function () {
    var me = {}, privateVariable = 42;
    me.someMethod = function () {
        return privateVariable;
    };

    me.publicVariable = "foo bar";
    me.anotherMethod = function () {
        return this.publicVariable;
    };

    return me;

}());


// Defining test two, function
var testTwo = ​function() {
    var me = {}, privateVariable = 42;
    me.someMethod = function () {
        return privateVariable;
    };

    me.publicVariable = "foo bar";
    me.anotherMethod = function () {
        return this.publicVariable;
    };

    return me;
};


// Proving that both techniques are functionally identical
var resultTestOne = new testOne(),
    resultTestTwo = new testTwo();

console.log(
    resultTestOne.someMethod(), // Should print 42
    resultTestOne.publicVariable // Should print "foo bar"
);

console.log(
    resultTestTwo.someMethod(), // Should print 42
    resultTestTwo.publicVariable // Should print "foo bar"
);



// Performance benchmark start
var stop, start, loopCount = 1000000;

// Running testOne
start = (new Date()).getTime(); 
for (var i = loopCount; i>0; i--) {
    new testOne();
}
stop = (new Date()).getTime();

console.log('Test one took: '+ Math.round(((stop/1000) - (start/1000))*1000) +' milliseconds');



// Running testTwo
start = (new Date()).getTime(); 
for (var i = loopCount; i>0; i--) {
    new testTwo();
}
stop = (new Date()).getTime();

console.log('Test two took: '+ Math.round(((stop/1000) - (start/1000))*1000) +' milliseconds');

内省时有一个轻微的缺点。转储 testOne,将导致不太有用的信息。此外,“testOne”中的私有属性“privateVariable”在所有情况下都是共享的,shesek 的答复中也提到了这一点。

每次都重新创建对象的问题主要是由于为每个新对象重新创建了方法。但是,我们可以通过在 上定义方法来缓解这个问题Dog.prototype因此this.bark = function () {...},我们可以Dot.prototype.bark = function () {...}Dog函数之外执行而不是使用(在此答案中查看更多详细信息
2021-04-18 22:44:48
请注意,在 testOneprivateVariable中只是IIFE范围内的变量,并且它在所有实例之间共享,因此您不应在其上存储特定于实例的数据。(在 testTwo 上它是特定于实例的,因为每次调用 testTwo() 都会创建一个新的、每个实例的范围)
2021-04-20 22:44:48
我投票是因为你展示了另一种方法,为什么不使用它,因为它会复制
2021-04-20 22:44:48

Douglas Crockford 在JavaScript Prototypal Inheritance上有一个不错的页面

五年前,我用 JavaScript编写了Classical Inheritance它表明 JavaScript 是一种无类的原型语言,并且它具有足够的表达能力来模拟经典系统。从那时起,我的编程风格发生了变化,任何优秀的程序员都应该如此。我学会了完全接受原型,并将自己从经典模型的限制中解放出来。

Dean Edward 的Base.jsMootools 的 ClassJohn Resig 的 Simple Inheritance作品是在 JavaScript 中进行经典继承的方法

为什么不简单地newObj = Object.create(oldObj);如果你想要它无类?否则,用oldObj构造函数的原型对象替换 with应该可以吗?
2021-04-26 22:44:48
function Shape(x, y) {
    this.x = x;
    this.y = y;
}

// 1. Explicitly call base (Shape) constructor from subclass (Circle) constructor passing this as the explicit receiver
function Circle(x, y, r) {
    Shape.call(this, x, y);
    this.r = r;
}

// 2. Use Object.create to construct the subclass prototype object to avoid calling the base constructor
Circle.prototype = Object.create(Shape.prototype);
也许在您的答案中添加此链接可能会使图片更加完整:developer.mozilla.org/en/docs/Web/JavaScript/Reference/...
2021-04-24 22:44:48

我会看看YUI和 Dean Edward 的Base图书馆:http : //dean.edwards.name/weblog/2006/03/base/

对于 YUI,您可以快速查看lang module,尤其是。YAHOO.lang.extend方法。然后,您可以浏览一些小部件或实用程序的来源,并查看它们如何使用该方法。

yui 3 中的 lang 似乎没有扩展方法。但由于答案打算使用实现作为示例,因此版本无关紧要。
2021-04-24 22:44:48
自 2011 年起,YUI 2 已被弃用,因此指向的链接lang已半断开。有人愿意为 YUI 3 修复它吗?
2021-05-11 22:44:48

还有 Microsoft 的ASP.NET Ajax 库,http://www.asp.net/ajax/

还有很多很好的 MSDN 文章,包括使用面向对象技术创建高级 Web 应用程序