在JavaScript中构建“类”的现代方法是什么?

时间:2010-02-05 07:48:44

标签: javascript

如何构建一个“类”(带有属性和方法),将在其上创建大量实例?

6 个答案:

答案 0 :(得分:23)

现代方式是使用class,如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());

以上示例提供了与2010年原始示例等效的界面。


2010年的原始答案:

在“现代”JavaScript中,有三种常用的方法来定义对象。

第一种方法是经典方法,因其简单而仍然很受欢迎;但是,discouraged by MDC支持第二种方法,因为每次创建对象的实例时都必须重新定义每个函数的效率低。

// 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");

第二种方法是第一种方法的变体,可与第一种方法互换使用。通过prototype属性向现有对象添加新方法也很有用。这种形式无法使用私人成员和方法。

// 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");

第三种方法是使用module pattern,这样就可以在不必使用new运算符的情况下实例化对象。

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");

请注意,在第一种和第三种方法中,您可以使用私有访问成员和方法。但请注意to use this within private methods some must happen

答案 1 :(得分: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);

您还可以使用匿名函数来模拟私人和公共

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();

我不喜欢这种模式。下划线警告_myVariable应该足以让lib的用户不使用这些变量/方法。由于我的Java背景,我在第一次发现它时使用了它。它使得使用原型继承很困难并且可能导致内存泄漏。

答案 2 :(得分:4)

JavaScript最原生的面向对象的方法是使用原型继承,但存在许多其他模式,包括伪古典继承,它模仿C和Java等语言中基于类的继承模式。道格拉斯·克罗克福德(Douglas Crockford)就这一主题进行了撰写和发言,并为每一主题提看看这些文章:

Prototypal Inheritance in JavaScript

Classical Inheritance in JavaScript

答案 3 :(得分:2)

JavaScript不像Java,C ++等那样使用类。

实现效果的一种方法是定义一个使用 this 关键字的函数 - 像在Java中一样粗略地访问成员。然后,在调用此函数时使用 new 关键字来创建对象。

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

答案 4 :(得分:1)

答案 5 :(得分:0)

通过使用匿名自执行功能,您可以允许公共和私有属性/方法。

这是我最喜欢的模式:

(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();

从评论herethis article了解到这一点。