[英]JavaScript prototype limited to functions?
o.prototype = {...}仅在o是Function时有效。 假设我有以下代码
conf = {
a: 2,
b: 4
};
conf.prototype = {
d: 16
}
conf.a和conf.b可以,并返回正确的值。 但是conf.d不会返回16而是返回undefined。 是否有解决方案可将基于原型的泛化也应用于这些类型的对象。
您会混淆可用于构造函数的prototype
属性和内部 [[Prototype]]
属性。
所有对象都具有此内部[[Prototype]]
属性,并且只有在使用构造函数调用它时,才允许new
运算符对其进行设置(通过[[Construct]]
内部操作)。
如果要使用对象实例进行原型继承(不使用构造函数),则可以使用Crockford的Object.create
技术(该方法现在是最近批准的ECMAScript 5th Edition的一部分):
// Check if native implementation available
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {} // empty constructor
F.prototype = o; // set base object as prototype
return new F(); // return empty object with right [[Prototype]]
};
}
var confProto = {
d: 16
};
var conf = Object.create(confProto);
conf.a = 2;
conf.b = 4;
在上面的代码中, conf
将具有其三个成员,但是物理上仅存在a
和b
:
conf.hasOwnProperty('a'); // true
conf.hasOwnProperty('b'); // true
conf.hasOwnProperty('d'); // false
因为d
存在于conf [[Prototype]]
( confProto
)上。
实际上,JavaScript中有两种不同的“原型”:
[[Prototype]]
表示此隐藏链接)。 默认情况下,对象文字的隐藏链接指向Object.prototype
,功能对象的隐藏链接指向Function.prototype
,而数组的隐藏链接指向Array.prototype
。 这些隐藏的原型链接与名称为“ prototype”的属性无关。 您不能通过添加或修改o.prototype
来更改这些隐藏的链接。 prototype
”的特殊属性。 这主要用于构造函数调用模式。 [[Prototype]]
用于搜索属性(如经典层次结构中的父级),每当无法在对象中找到属性时,都将搜索其[[Prototype]]
。 一种使用场景:假设您想向所有对象添加属性,您可以将其简单地添加到Object.prototype
,由于所有对象都以Object.prototype
作为其[[Prototype]]
链根,因此可以自动应用于所有对象。
让我们回到函数对象的“ prototype
”属性。 仅在与运算符new
使用时才有用。 以以下代码段为例:
function F() {} // function declaration
// F now has a property named "prototype"
var f = new F(); // use "new" operator to create a new function object based on F
上面的new F()
要做的是首先创建一个新的功能对象,将此新创建的功能对象的[[Prototype]]
(隐藏链接)设置为F.prototype
,然后返回新的功能对象。 这可能是您已经了解的适用于函数对象的内容。
还记得我说过我们不能更改对象的[[Prototype]]
吗? 好吧,至少不是直接的。 克罗克福德的Object.create
函数通过利用new
运算符可以帮助我们设置[[Prototype]]
的事实来做到这一点。 因此,通过使用Object.create
,您可以故意指示新对象的隐藏链接应指向的位置。 (有点像表明谁是您的父母班)
在您的示例中, conf
是对象文字,而conf.prototype
并不是真正有用。 这是另一个利用古典风格的版本:
function ConfBase() {}
ConfBase.prototype.d = 16;
var conf = new ConfBase();
conf.a = 2;
conf.b = 4;
document.writeln(conf.a);
document.writeln(conf.b);
document.writeln(conf.d);
与@CMS的答案相比,我更喜欢使用Object.create
。 但是本质上,这两种样式使用的是相同的基础机制,只是Object.create
可以帮助整理它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.