创建JavaScript类的最佳方法是什么?

Aru*_*ala 36 javascript oop

可能重复:
在Javascript中使用'prototype'与'this'?
Javascript中面向对象的问题

您能否请您推荐以下哪项是最佳的或其优缺点?

方法1

function User() {

    this.name = "my name";
    this.save = function() {

    };
}
Run Code Online (Sandbox Code Playgroud)

方法2

function User() {

    this.name = "my name";
}

User.prototype.save = function() {

}
Run Code Online (Sandbox Code Playgroud)

Ste*_*hen 52

来自Java和PHP的背景,我最初在JavaScript中使用整个"类"概念.以下是一些需要考虑的事项.

施工

首先,因为您可能会将您的类定义为..

Customer = function () {}
Customer.prototype = new Person();
Run Code Online (Sandbox Code Playgroud)

如果在构造过程中定义属性和方法,最终会遇到各种各样的代码噩梦.原因在于,一段代码Customer.prototype = new Person();需要在Customer构造函数中调用Person以实现真正的继承.否则,您最终必须知道原始设置始终是什么.请看以下示例:

Person = function (name) {
    this.name = name;
    this.getName = function () {return this.name}
}
Customer = function (name) {
    this.name = name;
}
Customer.prototype = new Person();
Run Code Online (Sandbox Code Playgroud)

现在我们要更新Person以设置它们是否是"新的":

Person = function (name, isNew) {
    this.name = name;
    this.isNew = isNew;
    this.getName = function () {return (this.isNew ? "New " : "") + this.name; }
}
Run Code Online (Sandbox Code Playgroud)

现在,在继承自Person的任何"类"上,您必须更新构造函数以遵循表单.你可以通过以下方式解决这个问题:

Customer = function () {
    Person.apply(this, arguments);
}
Run Code Online (Sandbox Code Playgroud)

这将在新"客户"的范围内调用"人员",这样您就不必了解人员构造.

速度

看看这些基准:http: //jsperf.com/inherited-vs-assigned.
基本上,我试图在这里证明的是,如果你是集体创建这些对象,那么最好的方法是在原型上创建它们.创建它们像:

Person = function (name) {
    this.name = name;
    this.getName = function () {return this.name}
}
Run Code Online (Sandbox Code Playgroud)

非常慢,因为对于每个对象创建,它都会创建一个新函数 - 它不会简单地查找现有对象的原型链.相反,如果你只有几个对象被频繁调用,那么在本地定义它们有助于通过查找原型链来减少速度.

共享属性

这总是让我感动.假设您有以下内容:

Person = function () {
    this.jobs = {};
    this.setJob = function (jobTitle, active) {this.jobs[jobTitle] = active; }
}

Employee = function () {}
Employee.prototype = new Person();

var bob = new Employee();
bob.setJob('janitor', true);

var jane = new Employee();
console.log(jane.jobs);
Run Code Online (Sandbox Code Playgroud)

你猜怎么着?简是一个看门人!可不是闹着玩的!这就是原因.由于您没有将this.jobs定义为Employee实例化的新对象,因此现在只需查找原型链,直到找到"作业"并按原样使用它.好玩,对吗?

因此,如果您想跟踪实例,这很有用,但在大多数情况下,您会发现它非常令人沮丧.您可以通过执行以下操作来解决这个问题:

Employee = function () { Person.apply(this); }
Run Code Online (Sandbox Code Playgroud)

这迫使'Person'创建一个新的'this.jobs'.

私有变量

因为在JavaScript中没有什么是真正的"私有",所以你可以获得私有变量的唯一方法是在构造函数中创建它们,然后在构造函数中创建依赖它们的任何东西.

Person = function () {
    var jobs = {};
    this.setJob = function (jobTitle, active) {jobs[jobTitle] = active; }
    this.getJob = function (jobTitle) { return jobs[jobTitle]; }
}
Run Code Online (Sandbox Code Playgroud)

但是,这也意味着必须在继承类的每个实例化上调用该构造函数.


建议

http://ejohn.org/blog/simple-javascript-inheritance/

这是一个超级基类设置.这很简单.有用.它可以做你需要它做90%的时间,而不必处理JavaScript提供的所有疯狂:)

</rant>


Pet*_*son 10

最好是一个非常主观的术语.

方法1给出了真正私有变量的可能性.例如:

function User() {
   var name = "fred";
   this.getName = function () { return name;};
}
Run Code Online (Sandbox Code Playgroud)

方法2将使用更少的内存,因为所有User对象共享单个保存功能.

"最佳"将取决于您的具体要求.


Cyb*_*nic 7

JavaScript是一种"基于对象"的语言,而不是"基于类"的语言.共享行为是类概念,通过链接原型来实现.

方法1不创建类.每次调用它时,都会按照定义创建属性和函数,并且不与其他"实例"共享.如果替换,this.save那么只有一个实例会改变行为.

方法2实现共享行为.因此,它是人们与类和实例相关联的.如果this.save使用其他函数替换,则所有派生实例将立即具有新行为.

如果"最佳"意味着没有内存消耗功能的重新定义和共享共同行为(这是基于类的编程倾向于等同于),方法2就是要走的路.


grc*_*grc 5

正如其他人所提到的,有两个主要区别:

  • 方法1将为每个User实例创建一个新函数
  • 方法1将能够访问构造函数范围中的局部变量

这是一个展示这些的例子:

function User() {

    var name = "my name";

    this.foo = function() {
        // one function per User instance
        // can access 'name' variable
    };
}

User.prototype.bar = function() {
    // one function shared by all User instances
    // cannot access 'name' variable
};

var a = new User();
var b = new User();

console.log(a.foo === b.foo); // false; each instance has its own foo()
console.log(a.bar === b.bar); // true; both instances use the same bar()
Run Code Online (Sandbox Code Playgroud)