What is the correct way to create a Javascript cla

2019-03-26 07:31发布

问题:

I'm trying to figure out how to construct my Javascript classes (or singleton objects) correctly.

var obj = new Object();
obj.foo = 'bar';
obj.method = function() { ...}

var obj = {
    foo : 'bar',
    method : function() { ...}
}

var obj = function(){}
obj.prototype = {
    foo : 'bar',
    method: function() { ... }
}

I want to be able to set a couple of properties and assign the methods available. I would also like to be able to use things like mixins on the objects so I can extend these objects with things like events.

回答1:

I'm trying to figure out how to construct my Javascript classes (or singleton objects) correctly.

There's a big difference between those ("classes" and singleton objects). Your first couple of examples are one-off objects (singletons). Your third (last) example creates a constructor function that will allow you to create multiple objects sharing the same prototype. I would recommend augmenting the prototype property on the constructor function rather than replacing it as you're doing, e.g.:

var Thingy = function() {   // Or use a function declaration rather than expression
    // Optional initialization code here
};
Thingy.prototype.foo = 'bar';
Thingy.prototype.method = function() {
    // Method code here
};

(Constructor functions, by convention, start with an upper case letter.)

Which you use (singleton or constructor function) depends on what you need.

As of ES2015 (aka "ES6"), it's simpler, although there's no new syntax for defining a non-method prototype property (your foo); there probably will be in ES2017 or ES2018, once this proposal moves forward, but until then:

class Thingy {
    constructor() {
        // Optional initialization code here
    }
    method() {
    // Method code here
    }
}
Thingy.prototype.foo = 'bar';

If you need to get into inheritance hierarchies, in the old ES5 syntax there's a fair bit of plumbing involved:

var Base = function() {
};
Base.prototype.method = function(arg1) {
    // ...
};

var Derived = function() {
    Base.call(this);
};
Derived.prototype = Object.create(Base.prototype);
Derived.prototype.constructor = Derived;
Derived.prototype.method = function(arg1) {
    // Using Base's `method`, if desired, is a bit ugly:
    Base.prototype.method.call(this, arg1);
};

...which is why you used to see libraries stepping in, like Prototype's Class stuff, or my own Lineage; those are outdated by ES2015 syntax, though, whcih makes it downright easy:

class Base {
    method(arg1) {
        // ...
    }
}
class Derived extends Base {
    method(arg1) {
        // Use's the superclass's `method`, if desired, is easy:
        super.method(arg1);
    }
}

Re the title of your question:

What is the correct way to create a Javascript class?

There are several equally-correct ways to create "classes" of objects in JavaScript, because JavaScript is a very flexible language. There are standard constructor functions, "builder" functions, Object.create (on ES5-enabled environments) which lets you do more direct prototypical inheritance, and several others. One of the great things about JavaScript is that you get to choose your style of "class".



回答2:

you can also use something like:

function O(x,y) {
   this.x=x;
   this.y=y;
   this.method=function() {...}
   return this;
}

var o=new O(0,0);


回答3:

If you're looking for a practical solution rather than a theoretical one, you better use a framework.

  • Backbone.js has all you need, including mixins and an event system.

If you need some widgets too, consider

  • qooxdoo
  • ExtJS

Both of them provide a clean architecture and may be used without widgets, but they require a bit more learning than Backbone.

The inheritance structure that these frameworks provide feels very much like the common class-based one (think Java). That's because they create special objects internally that merely serve as prototypes for others, and thus take the role of classes.

For example, when you call Ext.define('MyClass', {extend: 'ParentClass', mixins: foo, ... }), then Ext creates a function "MyClass", and an anonymous object (MyClass.prototype) which holds the methods you provided.



回答4:

If you're targeting a browser or environment that supports ES5, then you can do this:

var Person = {
  foo: ...,
  bar: ...
};

var Mike = Object.create(Person, { baz: ... });