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

class - Confusion about how to create classes in JavaScript - Stack Overflow

programmeradmin5浏览0评论

In the past when creating "classes" in JavaScript, I have done it like this:

function Dog(name){
    this.name=name;
    this.sound = function(){
        return "Wuf";
    };
}

However, I just saw someone do it like this instead:

var Dog = (function () {
    function Dog(name) {
        this.name = name;
    }
    Dog.prototype.sound = function () {
        return "Wuf";
    };
    return Dog;
})();

Can you do it both ways, or is the way I've done it wrong? In that case, why? And what exactly is the difference between the two in terms of what we end up with? In both cases we can create an object by saying:

var fido = new Dog("Fido");
fido.sound();

I hope someone will enlighten me.

In the past when creating "classes" in JavaScript, I have done it like this:

function Dog(name){
    this.name=name;
    this.sound = function(){
        return "Wuf";
    };
}

However, I just saw someone do it like this instead:

var Dog = (function () {
    function Dog(name) {
        this.name = name;
    }
    Dog.prototype.sound = function () {
        return "Wuf";
    };
    return Dog;
})();

Can you do it both ways, or is the way I've done it wrong? In that case, why? And what exactly is the difference between the two in terms of what we end up with? In both cases we can create an object by saying:

var fido = new Dog("Fido");
fido.sound();

I hope someone will enlighten me.

Share Improve this question asked Mar 24, 2015 at 13:49 MBrownMBrown 5931 gold badge4 silver badges14 bronze badges 1
  • More on how to use constructor functions and prototype can be found here: stackoverflow./a/16063711/1641941 hope it helps – HMR Commented Mar 24, 2015 at 23:38
Add a ment  | 

4 Answers 4

Reset to default 15

There are two important differences between your way and theirs.

  1. Wrapping in a self invoking function ((function() { ... })();)
  2. Using the .prototype property over this. for methods.

Wrapping things in a self invoking function, then assigning the result (as defined in the return statement to a variable is called the module pattern. It's a mon pattern to ensure scope is more controlled.

Using Dog.prototype.sound = function() {} is preferable to this.sound = function(). The difference is that Dog.prototype.sound is defined once for all objects with the Dog constructor, and the this.sound = function() {} is defined again for each Dog object created.

The rule of thumb is: Things that are individual to an object (usually its properties) are to be defined on this, while things that are shared to all objects of the same type (usually functions) are to be defined on the prototype.

With your code, you're creating a new function sound for every new Dog instance that's being created. Javascript's prototype avoids this by creating only a single function which all object instances share; basically classical inheritance.

In the second code you're showing that's just additionally wrapped in an IIFE, which doesn't do much in this case.

The first is the traditional method of creating a constructor. The second an immediately invoked function expression that returns a constructor. This method allows you to keep variables within the module without leaking out into the global scope which could be an issue.

And what exactly is the difference between the two in terms of what we end up with?

They both, as you've seen, have the same result. The others have talked about prototype so I won't mention it here.

The second is preferable because it takes advantage of Javascript's prototypal inheritance mechanism.

Prototypes

Javascript inheritance is a cause of confusion, but it's actually fairly simple: every object has a prototype, which is an object that we will check when we try to access a property not on the original object. The prototype will, itself, have a prototype; in a simple case, like Dog, this will probably be Object.prototype.

In both of your examples, because of how the new operator works, we will end up with a prototype chain that looks like this: fido->Dog.prototype->Object.prototype. So, if we try to look for the name property on Fido, we'll find it right there on the object. If, on the other hand, we look for the hasOwnProperty property, we'll fail to find it on Fido, fail to find it on Dog.prototype, and then reach Object.prototype, where we'll find it.

In the case of sound, your examples define it in two different places: in the first case, fido and every other dog we create will have their own copy of the function. In the second case, Dog.prototype will have a single copy of the function, which will be accessed by individual dogs when the method is called. This avoids wasting resources on storing duplicates of the sound function.

It also means that we can extend the prototype chain; maybe we want a Corgi class that inherits the sound function from Dog. In the second case, we can simply ensure that Dog.prototype is in Corgi.prototype's prototype chain; in the first, we would need to create an actual Dog and put it in the prototype chain.

发布评论

评论列表(0)

  1. 暂无评论