What is the modern way to structure a “class” in J

2020-05-16 04:40发布

How to build a "class" (with properties and methods) upon which will be created a lot of instances?

标签: javascript
6条回答
forever°为你锁心
2楼-- · 2020-05-16 05:10
// I like this pattern..

// class
function Person(name, birthdate) {
  this._name = name;
  this._birthdate = birthdate;
  /* should not do this
  * this.getAge = function() {
  * }
  * as the method will be constructed
  * for each instance, better to let it
  * be inherited from prototype, see below
  */
}

// class methods
Person.prototype.getBirthdate = function() {
  return this._birthdate;
}

// same as above, function as a method
Person.prototype.getAge = function() {
  var currentDate = new Date();
  // age in millis
  return currentDate - this._birthdate;
}

// the get age method can be a "static"
// method on the constructor function if you pass the
// person object
Person.getAge = function(person) {
  var currentDate = new Date();
  // age in millis
  //no reference to this
  return currentDate - person.getBirthdate();
}

// you could use it like this

myPerson = new Person("Steve", new Date("1980-01-01"));
// returns age in millis
myPerson.getAge();
// returns age in millis
Person.getAge(myPerson);

You could also use a anonymous function to simulate private and public

var PersonFactory = (function() {
  // private area, no one can alter
  // the person cache
  var _cache = {}

  // public area
  return {
    // returns a person born now
    getPerson: function(name) {
      if(_cache[name]) {
        return _cache[name];
      }
      else {
        _cache[name] = new Person(name, new Date());
        return _cache[name];
      }
    }
  }
})();

var p = PersonFactory.getPerson("Leif");
p.getAge();
p = PersonFactory.getPerson("Leif");
// should be the same age / obj
p.getAge();

I don't like this pattern though. The underscore warning _myVariable should be enough to keep users of your lib from using those variables / methods. I used it allot when I first discovered it because of my Java background.. It makes it difficult to work with prototype inheritance and can cause memory leaks.

查看更多
神经病院院长
3楼-- · 2020-05-16 05:12

The approach to object orientation most native to JavaScript is to use prototypal inheritance, but many other patterns exist, including pseudoclassical inheritance, which mimics the class-based inheritance pattern in languages like C and Java. Douglas Crockford has written and spoken on the subject and provides some very good explanations of each. Take a look at these articles:

Prototypal Inheritance in JavaScript

Classical Inheritance in JavaScript

查看更多
闹够了就滚
4楼-- · 2020-05-16 05:14

By using an anonymous self-executing function, you can allow for public and private attributes/methods.

This is the pattern I like the most:

(function ($, MyObject, undefined) {

    MyObject.publicFunction = function () {
        console.log("Public function");
    };

    var privateFunction = function () {
        console.log("Private function");
    };    

    var privateNumber = 0;
    MyObject.sayStuff = function () {
        this.publicFunction();
        privateFunction();
        privateNumber++;
        console.log(privateNumber);
    };  


    // You can even nest the namespaces
    MyObject.nestedNamespace = MyObject.nestedNamespace || {};
    MyObject.nestedNamespace.logNestedMessage = function () {
        console.log("Nested namespace function");
    };

}(jQuery, window.MyObject = window.MyObject || {}));

MyObject.sayStuff();
MyObject.sayStuff();
MyObject.nestedNamespace.logNestedMessage();
MyObject.publicFunction();

Learned about it from the comments here and this article.

查看更多
对你真心纯属浪费
5楼-- · 2020-05-16 05:19

The modern way is to use class, as introduced in ES6.

class Movie {
    constructor(name) {
        this.name = name;
        // The "_" prefix is commonly used to denote "private" members.
        this._id = +new Date();
    }

    getName() {
        return `${this.name} ${this._id}`;
    }

    setName(name) {
        this.name = name;
    }
}

const movie = new Movie('Beerfest');

console.log(movie.getName());

The above example provides an equivalent interface to the original examples from 2010.


Original answer from 2010:

In "modern" JavaScript, there are three popular methods for defining objects.

The first method is the classic method and is still popular because of its simplicity; however, it is discouraged by MDC in favor of the second method because of the inefficiency of having to redefine each function every time an instance of the object is created.

// Constructor, methods and members all rolled up into one definition
var Movie = function(name) {
    this.name = name;
    // Note that private members can be created using the closure property
    var _id = +(new Date());

    this.getName = function() {
        return this.name + " " + _id;
    };

    this.setName = function(name) {
        this.name = name;
    };
};

var m = new Movie("Beerfest");

The second method is a variation of and can be used interchangeably with the first. It is also useful for adding new methods to existing objects via the prototype property. Private members and methods are not possible in this form.

// Constructor is separate from its methods
var Movie = function(name) {
    this.name = name;
}

Movie.prototype.getName = function() {
    return name;
};

Movie.prototype.setName = function(name) {
    this.name = name;
};

var m = new Movie("Kill Bill");

The third method is to use the module pattern, which makes it possible to instantiate objects without having to use the new operator.

var Movie = function (name) {
    var _id = +(new Date());
    var privateMethod = function() { alert(_id); };

    // All methods and members defined here are public
    return {
        name: name,
        getName: function() {
            return this.name + " " + _id;
        },
        setName: function(name) {
            this.name = name;
        }
    };
};

var m = Movie("Stackoverflow: the movie");

Note that in the first and third methods, you can use private access members and methods. But be aware that to use this within private methods some must happen.

查看更多
家丑人穷心不美
6楼-- · 2020-05-16 05:28

JavaScript does not use classes in the same way as Java, C++ or the like.

One way to achieve your effect is to define a function in which the this keyword is used--accessing members roughly as you would in Java. Then, use the new keyword in calling this function to create an object.

function Foo(){ //vaguely like a Java constructor
    this.aField = 1; //define members simply by using 'this'
    this.aMethod = methodFunction; //assign a function as a member using 'this'
}

function methodFunction(){
}

var foo = new Foo(); //construct an object
查看更多
登录 后发表回答