开发者

Does prototype really matter in JavaScript if the class will never be subclassed?

So, in answering anot开发者_如何转开发her question on this site, I wrote a class for someone to create a BitArray instance in JavaScript. The code I posted looked like this:

var foo = function(param1) {
    this._member = param1;
    this.getMember = function() { return this._member; };
    this.setMember = function(val) { this._member = val; };
    this.alertMember = function() { alert(this._member); };
    foo.STATIC_CONSTANT = "some value";
}

One of the comments I received was a rather stern "You should absolutely add the methods to foo.prototype instead of this". If I take that criticism and apply it to the above, it turns the code into:

var foo = function(param1) {
    this._member = param1;
}
foo.prototype.getMember = function(){ return this._member; };
foo.prototype.setMember = function(val) { this._member = val; };
foo.prototype.alertMember = function() { alert(this._member); };
foo.STATIC_CONSTANT = "some value";

My question is, what's the difference here between the two approaches assuming foo will never be subclassed?

To be clear, I'm not advocating writing sloppy code - I credit the commentor with catching me being sloppy - but as I was conceeding to his correctness, it really did make me think - why should I prototype if I'm creating an effectively sealed class?

Is there some performance or functional consequence I'm missing here? Or when a class won't be subclassed is using the prototype irrelevent?


There are various reasons. Firstly though I guess speaking of classes in JavaScript is misleading. There are no classes in JavaScript, but only prototypes.

Let us analyze what actually happens in your first approach and what happens in the second approach. When the code of the first approach is run it defines a function, which, when it is called as a constructor, will create a bunch of other functions and assign them to members of the newly created object. You should be aware that this is done every time you call the function. So if you call the function once, you will have one object with a total of 4 functions. If you call the function twice, you will have two objects with a total of 8 functions, and so on. Each time, you create a new object using this constructor you will create a complete set of functions for it. Each of those function will require memory. Also, modern JIT compilers trying to spot hotspots in your code might fail to identify those functions as hot spots, since instead of having one function that is called multiple times you have several functions where each is only called once. Additionally even if the JIT is able to spot those functions as hotspots, it will have to compile each of those functions separately which will require additional work.

That being said I believe the assumption "foo will never be subclassed" shouldn't be valid. You cannot assume that others won't want to inherit from your object or would like to augment the prototype of your object. This is currently not possible. Imagine I would like to change foo.STATIC_CONSTANT. I couldn't, because each time I construct a new foo, it will override my changed foo.STATIC_CONSTANT again. Same is true for any other augmentation I might like to do.

All these problems do not arise in the second, correct object oriented javascript pattern.


Yes, there is a difference.

In the first example, every single time you create a new instance of the class, its methods are redefined. This makes it very much less efficient in terms of speed and memory.

To illustrate:

function C1 () {
    this.foo = function () { };
}

function C2 () {}
C2.prototype.foo = function () {};

c1a = new C1();
c1b = new C1();

c2a = new C2();
c2b = new C2();

c1a.foo === c1b.foo;  // false
c2a.foo === c2b.foo;  // true


Here, you are creating three functions from scratch for each instance of the array. This has some memory cost; it can be discussed whether this cost is big or not, but if you'll try to create thousands of instances of this array, you will notice the difference.

The object creation will be a little slower, too, but not much on recent optimized runtimes (like V8).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜