我想知道是否有人可以在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*/)
调用,所以,我想我的问题是,以第二种方式定义函数的优点是什么?以及他们如何或为何与众不同?
希望我有道理......
编辑:谢谢你们所有的启发性答案,很难在这里判断答案是“正确的”,所以我要标记我认为最有贡献的那个......
你们当然给了我更多的思考......
答案 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。