可能重复:
Use of ‘prototype’ vs. ‘this’ in Javascript?
Object Oriented questions in Javascript
您能否请您推荐以下哪一项最佳或者是利弊?
function User() {
this.name = "my name";
this.save = function() {
};
}
function User() {
this.name = "my name";
}
User.prototype.save = function() {
}
答案 0 :(得分:52)
来自Java和PHP的背景,我最初在JavaScript中使用整个“类”概念。以下是一些需要考虑的事项。
首先,因为您可能会将您的类定义为..
Customer = function () {}
Customer.prototype = new Person();
如果要在构造过程中定义属性和方法,最终会遇到各种代码的噩梦。原因是像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();
现在我们要更新Person以设置它们是否为'new':
Person = function (name, isNew) {
this.name = name;
this.isNew = isNew;
this.getName = function () {return (this.isNew ? "New " : "") + this.name; }
}
现在,在继承自Person的任何“类”上,必须更新构造函数以遵循表单。您可以通过执行以下操作来解决这个问题:
Customer = function () {
Person.apply(this, arguments);
}
这将在新“客户”的范围内调用“人员”,使您无需了解人员构造。
看看这些基准:http://jsperf.com/inherited-vs-assigned 基本上,我在这里要证明的是,如果你要创建这些对象 en masse ,那么最好的方法是在原型上创建它们。创建它们像:
Person = function (name) {
this.name = name;
this.getName = function () {return this.name}
}
非常慢,因为对于每个对象创建,它都会创建一个新函数 - 它不会简单地查找现有对象的原型链。相反,如果你只有几个对象被频繁调用,那么在本地定义它们有助于通过查找原型链来减少速度。
这总是让我感动。假设您有以下内容:
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);
猜猜是什么?简是一个看门人!可不是闹着玩的!这就是原因。由于您没有将this.jobs定义为实例化 Employee 的新对象,因此现在只需查找原型链,直到找到“作业”并按原样使用它。好玩,对吧?
所以,如果你想跟踪实例,这很有用,但是在大多数情况下你会发现它非常令人沮丧。您可以通过执行以下操作来解决这个问题:
Employee = function () { Person.apply(this); }
这迫使'人'创建一个新的'this.jobs'。
由于JavaScript中没有任何真正的“私有”,因此获取私有变量的唯一方法是在构造函数中创建它们,然后在构造函数中初始化依赖它们的任何内容。
Person = function () {
var jobs = {};
this.setJob = function (jobTitle, active) {jobs[jobTitle] = active; }
this.getJob = function (jobTitle) { return jobs[jobTitle]; }
}
但是,这也意味着必须在继承类的每个实例化上调用该构造函数。
http://ejohn.org/blog/simple-javascript-inheritance/
这是一个超级基础类设置。这很简单。有用。并且它可以做到你需要它做90%的时间而不必处理JavaScript提供的所有疯狂:)
</rant>
答案 1 :(得分:10)
最好是一个非常主观的术语。
方法1提供了真正私有变量的可能性。例如:
function User() {
var name = "fred";
this.getName = function () { return name;};
}
方法2将使用更少的内存,因为所有用户对象共享一个保存功能。
'最佳'将取决于您的具体要求。
答案 2 :(得分:7)
JavaScript是一种“基于对象”的语言,而不是“基于类”的语言。共享行为,即类概念,通过链接原型来实现。
方法1不创建类。每次调用它时,都会按照定义创建属性和函数,并且不与其他“实例”共享。如果替换this.save
,那么只有一个实例会改变行为。
方法2实现共享行为。因此,它是人们与类和实例相关联的。如果使用其他函数替换this.save
,则所有派生实例将立即具有新行为。
如果“最佳”意味着没有内存消耗功能的重新定义和共享常见行为(这是基于类的编程倾向于等同于),方法2就是可行的方法。
答案 3 :(得分:5)
正如其他人所说,有两个主要区别:
以下是一个展示这些内容的示例:
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()