最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

oop - Prototypes in JavaScript - Stack Overflow

programmeradmin6浏览0评论

In the JavaScript the same thing you can do in many different ways.

Consider the examples:

1:

function Circle(radius) {
 return {
  "r" : radius,
  "area" : function(){
   return Circle.pi * this.r * this.r; 
  }
 }
}
Circle.pi = 3.14159;

var a = Circle(10);
alert(a.area());

2:

function Circle(radius) {
    this.r = radius;
}

Circle.pi = 3.14159;
Circle.prototype.area = function(){
 return Circle.pi * this.r * this.r; 
}

var a = new Circle(10);
alert(a.area());

The second is better than first because we dont define the same function area for any instance of the Circle.

But lets consider 3:

function Circle(radius) {
 return {
  "r" : radius,
  "area" : Circle.area
 }
}
Circle.pi = 3.14159;
Circle.area = function(){
 return Circle.pi * this.r * this.r; 
}

var a = Circle(10);
alert(a.area());

Is there any reason to prefer second style instead of third? Or I misunderstood something at all?

In the JavaScript the same thing you can do in many different ways.

Consider the examples:

1:

function Circle(radius) {
 return {
  "r" : radius,
  "area" : function(){
   return Circle.pi * this.r * this.r; 
  }
 }
}
Circle.pi = 3.14159;

var a = Circle(10);
alert(a.area());

2:

function Circle(radius) {
    this.r = radius;
}

Circle.pi = 3.14159;
Circle.prototype.area = function(){
 return Circle.pi * this.r * this.r; 
}

var a = new Circle(10);
alert(a.area());

The second is better than first because we dont define the same function area for any instance of the Circle.

But lets consider 3:

function Circle(radius) {
 return {
  "r" : radius,
  "area" : Circle.area
 }
}
Circle.pi = 3.14159;
Circle.area = function(){
 return Circle.pi * this.r * this.r; 
}

var a = Circle(10);
alert(a.area());

Is there any reason to prefer second style instead of third? Or I misunderstood something at all?

Share Improve this question asked Aug 28, 2010 at 20:31 DanDan 3071 gold badge3 silver badges6 bronze badges 3
  • You know about the availability of Math.PI, don't you? – Marcel Korpel Commented Aug 28, 2010 at 21:08
  • 1 possible duplicate of Object oriented javascript with prototypes vs closures – Marcel Korpel Commented Aug 28, 2010 at 21:13
  • I've made some benchmarks like here blogs.msdn./b/kristoffer/archive/2007/02/13/…. The result - the 3rd style just between 1st and 2nd :) Thx for all answers and ments, I've learnt a lot. – Dan Commented Aug 28, 2010 at 22:38
Add a ment  | 

5 Answers 5

Reset to default 4

I would definitely go with example 2. Neither example 1 or 3 make good use of JavaScript's object-oriented features because:

  1. You duplicate method definitions in each instance.
  2. By returning a new object instead of using this, you lose the identity of the class, i.e. you can no longer do checks like a instanceof Circle.
  3. You give up the possibility of inheritance since you do not use prototypes.

Is there any reason to prefer second style instead of third?

The third style is still wasting a small amount of space in order to store the association between the name area and the area function.

Also because you are returning a new Object from the {...} literal, instanceof Circle won't work.

The second is better than first because we dont define the same function area for any instance of the Circle.

Indeed, but it can sometimes be useful to define a new copy of each method—a copy that, thanks to closures, can know what object it is bound to. With traditional prototyping you only get the this context which is set from the object the caller retrieved it from, rather than bound to a particular object. The first way avoids the problems of this-retention in things like event handlers, at the price of some loss of efficiency.

The difference between Circle.prototype.area and Circle.area is that one is only accessible with a instance of the class.

Circle.prototype.area = function(){};
Circle.area // wrong
(new Circle()).area // ok (you need a Circle object)

and

Circle.area = function(){};
Circle.area // ok (you don't need the object, its static)
(new Circle()).area // wrong

The problem with example 2 is, that when you accidentally forget to use the new operator when creating the object, and just call var a = Circle(10); (which is fine for the 3rd example, but not for the 2nd), then your constructor creates big trouble:

this.r = radius;

Since you didn't use new, this will be assigned the global object, so the constructor really sets the global variable r!

So I would strongly prefer example 3.

I'd like to ment on "The second is better than first because we dont define the same function area for any instance of the Circle." In practice, this may be such a negligable advantage as to be totally insignificant. I tend to favor syntax and human-friendly code over efficiency, unless performance is noticably affected. I've been pletely ignoring the Prototype feature of javascript and also avoiding the use of "this", basically using technique #1. It's working just fine for me. I find avoiding "this" prevents a lot of confusion about just what "this" refers to. It's perfectly possible to create inheritance-type structures without "prototype". You simple create a superclass object, and override whichever methods you want. Douglas Crockford has written pretty extensively on numerous different ways to do inheritance in javascript.

I will agree with casablanca above that being able to test for type using "instanceof" is a nice advantage of returning "this". Perhaps I'll take another look at "protype" and "this" on a future project. For now, though, I'm getting along just fine without them.

发布评论

评论列表(0)

  1. 暂无评论