繁体   English   中英

JavaScript原型仅限于功能吗?

[英]JavaScript prototype limited to functions?

o.prototype = {...}仅在o是Function时有效。 假设我有以下代码

 conf = {
  a: 2,
  b: 4
 };
 conf.prototype = {
  d: 16
 }

conf.aconf.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将具有其三个成员,但是物理上仅存在ab

conf.hasOwnProperty('a'); // true 
conf.hasOwnProperty('b'); // true
conf.hasOwnProperty('d'); // false

因为d存在于conf [[Prototype]]confProto )上。

属性存取器 . []负责解析在原型链中必要时查找的属性(通过[[Get]]内部方法)。

实际上,JavaScript中有两种不同的“原型”:

  1. 一个是每个对象都具有的“隐藏”链接(让我们使用[[Prototype]]表示此隐藏链接)。 默认情况下,对象文字的隐藏链接指向Object.prototype ,功能对象的隐藏链接指向Function.prototype ,而数组的隐藏链接指向Array.prototype 这些隐藏的原型链接与名称为“ prototype”的属性无关。 您不能通过添加或修改o.prototype来更改这些隐藏的链接。
  2. 另一个是所有功能对象都会自动具有一个名为“ 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM