如何构建一个“类”(带有属性和方法),将在其上创建大量实例?
答案 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年原始示例等效的界面。
在“现代”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)就这一主题进行了撰写和发言,并为每一主题提看看这些文章:
答案 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();
从评论here和this article了解到这一点。