有人可以解释javascript原型继承

时间:2009-11-09 20:44:43

标签: javascript oop

我想知道是否有人可以在OO javascript中解释function.prototype thingie(thingie !! ??)。

我来自服务器端编程背景,可能是我没有抓住原型的整个概念,

给出以下代码片段:

var animate=function(){};
animate.angular=function(){/*does something here*/};
animate.circular=function(){/*does something here*/};

var animate=function(){};
animate.prototype.angular=function(){/*does something here*/};
animate.prototype.circular=function(){/*does something here*/};

据我所知,后两个函数都可以通过animate.angular(/*args*/)animate.circular(/*args*/)调用,所以,我想我的问题是,以第二种方式定义函数的优点是什么?以及他们如何或为何与众不同?

希望我有道理......

编辑:谢谢你们所有的启发性答案,很难在这里判断答案是“正确的”,所以我要标记我认为最有贡献的那个......

你们当然给了我更多的思考......

6 个答案:

答案 0 :(得分:6)

我认为您的意思是在示例中的某处设置与 new animate()相同的内容。如果不使用 new ,我会详细说明会发生什么:

var animate = function(){ console.log(0, 'animate'); };
animate.angular = function(){ console.log(1, 'animate.angular'); };
animate.circular = function(){ console.log(2, 'animate.circular'); };

animate.prototype.angular = function(){ console.log(3, 'animate.prototype.angular'); };
animate.prototype.circular = function(){ console.log(4, 'animate.prototype.circular'); };

只有前两个功能,#1& #2,可以从动画变量中调用。

animate.angular();
animate.circular();

如果您创建新动画(),则可以拨打下一个,#3& #4,(但不是#1或#2)。

var ani2 = new animate();

ani2.angular();
ani2.circular();

此外,animate()是一个函数,但ani2不是。

console.log(5, typeof animate);
console.log(6, typeof ani2);
console.log(7, animate());

虽然已经创建了ani2,但您可以通过animate.prototype向其中添加新成员。

animate.prototype.bark = function(){ console.log(8, 'bark'); };
ani2.bark();

然而,animate变量不会继承它的原型。

console.log(9, typeof ani2.bark);
console.log(10, typeof animate.bark);

请注意,ani2不会继承直接应用于animate变量的成员。它只继承自animate.prototype。

animate.paperclip = function(){ console.log(11, "paperclip"); };

animate.paperclip();
console.log(12, typeof ani2.paperclip);
console.log(13, typeof animate.paperclip);

您还可以在构造函数(如animate)中使用 this 关键字将实例成员添加到 new 子项。

var Anime = function(a,b){ this.a=a; this.b=b; this.c=console; };
var anime1 = new Anime(14, 'anime1');
var anime2 = new Anime(15, 'anime2');
anime1.c.log(anime1.a, anime1.b);
anime2.c.log(anime2.a, anime2.b);

Anime.prototype.a = 16;
Anime.prototype.z = 'z';

var anime3 = new Anime(17, 'anime3');
anime3.c.log(18, anime3.a, anime3.b, anime3.z, " ", anime2.a, anime2.b, anime2.z, " ", anime1.a, anime1.b, anime1.z);
anime2.z='N';
anime3.c.log(19, anime3.a, anime3.b, anime3.z, " ", anime2.a, anime2.b, anime2.z, " ", anime1.a, anime1.b, anime1.z);

内存是为anime2.z的单独实例自动分配的,因为它已被修改,anime1& anime3仍然“分享”一个节俭的未经修改的z。

a,b和c成员不是以同样的方式“共同”。它们是在构造函数中使用 this 立即分配的, new Anime(),(不是从Anime.prototype继承)。此外,原型上的成员将始终由构造函数“个性化”。

永远不要忘记关键字,否则它不会像它应该的那样工作。例如, this 指向不带 new 的构造函数中的全局对象。

console.log(20, typeof window.a, typeof window.b, typeof window.c);
var opps = Anime(21, 'zapp');
console.log(22, typeof window.a, typeof window.b, typeof window.c);
console.log(23, typeof opps);

这是输出。汤姆的第二个建议是道格拉斯·克罗克福德的视频!


/*
1 animate.angular
2 animate.circular
0 animate
3 animate.prototype.angular
4 animate.prototype.circular
5 function
6 object
0 animate
7 undefined
8 bark
9 function
10 undefined
11 paperclip
12 undefined
13 function
14 anime1
15 anime2
18 17 anime3 z 15 anime2 z 14 anime1 z
19 17 anime3 z 15 anime2 N 14 anime1 z
20 undefined undefined undefined
22 number string object
23 undefined
*/

答案 1 :(得分:3)

即使有时感觉这样,javascript也没有类,但是可以使用原型。您定义原型,然后您可以创建原型的副本。

从:

开始
var animate=function(){};
animate.angular=function(){/*does something here*/};
你可以:

var a = new animate();
animate.angular();       // OK
a.circular();            // error: a.circular is not a function

但是,如果你从:

开始
function animate(i){};
animate.prototype.angular = function() {};

现在你可以

var a = new animate();
a.angular();

当然,如果您有实例变量,这会更有趣。

function animate(i) {
    this.x = i;
}
animate.prototype.angular = function() {
    this.x *= 2;
}

var a = new animate(5);
a.angular();
console.log(a.x);    // 10

答案 2 :(得分:2)

Javascript是一种奇怪的语言......非常强大但与其他语言相比并不是所有强大的结构...

原型是如果你要创建一个类的多个实例,JavaScript可以让你节省内存......所以如果你以OOP方式使用JS,你应该将你的函数定义为原型的一部分。此外,还有一些方法可以使用原型来模拟继承。

我强烈推荐这本书"Javascript, the Good Parts",对此有很多很好的解释。

答案 3 :(得分:2)

如果您可以节省3个小时的时间,我建议您查看YUI Theatre的“The JavaScript Programming Language”视频。演讲者/老师是道格拉斯·克罗克福德,他将为你提供一个坚实的JS基础,你可以在其上建立。

此致

汤姆

答案 4 :(得分:2)

基于原型的OOP为您提供自由优等OOP不会。

如果你真的想要了解它,就像很多人说的那样,阅读Crockford的解释,你将得不到比这更好的资源。

如果您想快速获益:

var Building = function() {
    this.openDoor = function() {};
};

var House = function() {
    this.closeDoor = function() {};
};
House.prototype = new Building();

var a = new House();
a.openDoor();
a.closeDoor();

定义对象(将代表其他语言中的类)这样的方式太糟糕了,所以我会在答案中加入一点提示:

构建系统的最佳方法是在您选择的全局命名空间下,例如:

if (typeof MYAPP === 'undefined' || !MYAPP) {
    var MYAPP = {};
}

function New(className, classBody) {
    // This adds your "classes" to this MYAPP namespace so they can be instantiated
    // You need some magic here, so have fun with this function
}

New('Building', function() {
    this.openDoor = function() {};
});

New('House', function() {
    this.prototype = new MYAPP.Building();
    this.closeDoor = function() {};
});

// Now you can do the same as before but your application is cleaner :)
var a = new MYAPP.House();
a.openDoor();
a.closeDoor();

干杯。

答案 5 :(得分:1)

其他人已经提到Douglas Crockford,请在他的网站上查看Prototypal Inheritance以获取更多信息。有关对比,请参阅Classical Inheritance

像枪手一样,我也推荐Crockford的(苗条)书JavaScript: The Good Parts