JavaScript原型仅限于函数?

Nee*_*asu 7 javascript prototype function object

o.prototype = {...}仅在o是函数时才起作用.假设我有以下代码

 conf = {
  a: 2,
  b: 4
 };
 conf.prototype = {
  d: 16
 }
Run Code Online (Sandbox Code Playgroud)

conf.aconf.b没问题并返回正确的值.但是conf.d没有返回16而是未定义.是否有任何解决方案,基于原型的泛化也可以应用于这些类型的对象.

CMS*_*CMS 21

您可能会混淆prototype可以在构造函数内部 [[Prototype]]属性上使用的属性.

所有对象都具有此内部[[Prototype]]属性,并且只有new使用构造函数调用它时的操作符才允许设置它(通过[[Construct]]内部操作).

如果你想拥有对象实例的原型继承(不使用构造函数),那么Crockford的Object.create技术就是你想要的(该方法现在是最近批准的ECMAScript第5版的一部分):

// 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;
Run Code Online (Sandbox Code Playgroud)

在上面的代码conf中将有三个成员,但只有a并且b将在物理上存在:

conf.hasOwnProperty('a'); // true 
conf.hasOwnProperty('b'); // true
conf.hasOwnProperty('d'); // false
Run Code Online (Sandbox Code Playgroud)

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

属性访问,.[]负责解决属性查找如果必要的话在原型链(通过[[Get]]内部方法).

  • 请问downvoter请发表评论?我总是希望改善我的答案:) (3认同)

bry*_*sai 6

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
Run Code Online (Sandbox Code Playgroud)

什么new F()上面确实是先创建一个新的函数对象,设置[[Prototype]]这个新创建的函数对象的(隐藏链接)是F.prototype,然后返回新的函数对象.这可能是您已经了解的适用于函数对象的内容.

请记住,我说我们不能改变对象的[[Prototype]]?好吧,至少不是直接的.Crockford的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);
Run Code Online (Sandbox Code Playgroud)

与@CMS的答案相比,我更喜欢使用Object.create.但基本上这两种风格使用相同的底层机制,这Object.create有助于整理它.