出身于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,使其也能设置他们是否为“新”:
Person = function (name, isNew) {
this.name = name;
this.isNew = isNew;
this.getName = function () {return (this.isNew ? "New " : "") + this.name; }
}
现在对于任何从Person继承的'class',您必须更新构造函数以遵循格式。您可以通过执行以下操作来解决此问题:
Customer = function () {
Person.apply(this, arguments);
}
这将在新的“Customer”作用域中调用“Person”,使您无需了解“Person”构造。
速度
看一下这些基准测试:http://jsperf.com/inherited-vs-assigned。
基本上,我想在这里证明的是,如果您正在批量创建这些对象,则最佳路线是在原型上创建它们。就像这样创建它们:
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);
猜猜怎么着?简(Jane)是个清洁工!真心话!原因是这样的,由于您在Employee的实例化时没有将this.jobs定义为新对象,它现在只是查找原型链直到找到'jobs'并像原样使用它。很有趣,对吧?
因此,如果您想跟踪实例,这很有用,但大多数情况下,您会发现这非常令人沮丧。您可以通过执行以下操作来解决该问题:
Employee = function () { Person.apply(this)
这迫使'Person'创建一个新的'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>
.save()
方法确实可以访问对象的属性。无论哪种方式,.save()
方法都可以访问this.name
。但是在方法2中,.save()
将无法访问构造函数中的局部变量 - 在您的示例中没有这样的变量,但更复杂的“类”可能需要或可能不需要这样做。 - nnnnnn