在原型上声明属性根本不是反模式。当我看到一个对象时,我认为“这就是这种类型的原型对象对数据和方法的作用。”
其他人已经警告不要在原型中给属性一个参考值,例如:Foo.prototype.bar = [];
---因为数组和对象是引用类型。引用类型是不可变的,因此“类”的每个实例都指向相同的数组或对象。只需在原型中将它们设置为null
,然后在构造函数中给它们一个值。
我总是在原型中包含所有属性,其中一个非常明确的原因是:向其他程序员传达哪些属性可公开提供,以及它们的默认值是什么,而不需要通过构造函数筛选出来。
如果您要创建需要文档的共享库,这将变得特别有用。
考虑这个例子:
/**
* class Point
*
* A simple X-Y coordinate class
*
* new Point(x, y)
* - x (Number): X coordinate
* - y (Number): Y coordinate
*
* Creates a new Point object
**/
function Point(x, y) {
/**
* Point#x -> Number
*
* The X or horizontal coordinate
**/
this.x = x;
/**
* Point#y -> Number
*
* The Y or vertical coordinate
**/
this.y = y;
}
Point.prototype = {
constructor: Point,
/**
* Point#isAbove(other) -> bool
* - other (Point): The point to compare this to
*
* Checks to see if this point is above another
**/
isAbove: function(other) {
return this.y > other.y;
}
};
(文档格式:PDoc)
只是阅读文档这里是一个有点尴尬,因为有关x
和y
性质的信息嵌入在构造函数中。对比,与包括原型这些特性的“反模式”:
/**
* class Point
*
* A simple X-Y coordinate class
*
* new Point(x, y)
* - x (Number): X coordinate
* - y (Number): Y coordinate
*
* Creates a new Point object
**/
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype = {
/**
* Point#x -> Number
*
* The X or horizontal coordinate
**/
x: 0,
/**
* Point#y -> Number
*
* The Y or vertical coordinate
**/
y: 0,
constructor: Point,
/**
* Point#isAbove(other) -> bool
* - other (Point): The point to compare this to
*
* Checks to see if this point is above another
**/
isAbove: function(other) {
return this.y > other.y;
}
};
现在看看样机给你的实际对象的快照,这是很容易在你的头上来可视化,也更容易供作者撰写文档。构造函数也不会与文档混杂在一起,并且坚持将对象带入生活的业务。
该原型具有一切,并且是关于“原型”Point
对象对于方法和数据具有什么样的信息的标准来源。
我会争辩说不是包括原型中的数据属性是反模式。
它说“数据属性”,我相信它是指变量。我不认为它提到了向原型添加功能的任何事情。 – 2012-08-10 14:54:54
arxanas说什么。确切的引用是:“一个类的主体只能包含方法,没有数据属性,具有数据属性的原型通常被认为是反模式,所以这只是一个最佳实践。”换句话说,通过“数据属性”,作者的意思是“不属于方法/功能的属性”。 – ruakh 2012-08-10 14:57:44
你的问题是基于一个误解,不知道该怎么做。我永远不会记得看到数据被放置在原型上。我不能真正编辑你的问题在原型中有数据,因为这不是我经常看到的*模式。 – Esailija 2012-08-10 14:58:22