【问题标题】:Is there a way in JavaScript to instantiate an object which is not necessarily a function?JavaScript中有没有办法实例化不一定是函数的对象?
【发布时间】:2011-08-26 22:07:36
【问题描述】:

我的原型示例是以下伪代码:

var kind = ...;
...
var type = new kind();
...
var person = new type();
...
var john = new person();

但这里的问题是type 不是一个函数,所以new type() 不起作用。 是否可以向对象添加特定属性以使其为new 所接受?

对我来说最重要的是原型链,这对我来说很重要,即 person.[[Prototype]] 应该是 type 等,以防 new 无法实现。

创建子类型链不是一种选择。这里typeperson 的元类型,而不是它的超类型。同样kind 是一个元元类型。以下测试可以阐明要求: 完成后,我想要这些阳性测试:

console.log(john instanceof person);   // should be true
console.log(person instanceof type);   // should be true
console.log(type instanceof kind);     // should be true

这些负面测试:

console.log(john instanceof type);     // should be false
console.log(john instanceof kind);     // should be false
console.log(person instanceof kind);   // should be false

我听说通过分配给__proto__ 属性可以做一些这种魔术,但不知道如何。显然,如果有便携式解决方案(例如使用 Object.create),则更可取。

【问题讨论】:

  • 那么您是否只是想创建一个person,即-a type,即-a kind?所以每次你创建一个新的person,你就在隐式地创建一个新的kind,并自动获得该类型的所有功能?
  • 不,我不想要子类型链,我希望 person 成为 type 的实例,就像 johnperson 的实例一样。
  • 这令人困惑,尤其是您对 FunkyFresh 的回答的评论。 1)您想要类型之间的is-a关系吗? 2)您不想从基类型继承任何结构或功能?
  • 我更新了问题以澄清这个问题。这现在有意义吗?

标签: javascript metaprogramming prototype-programming


【解决方案1】:

您是否可以向对象添加特定属性以使其为new 所接受?

没有。根据 ECMAScript 第 11.2.2 节控制此功能的属性称为[[Construct]],从方括号中可以看出,它是一个内部属性。它不受 ECMAScript 代码的影响。根据第 13.2 节,分配 [[Construct]] 的唯一时间是创建 Function 对象时。

在 ECMAScript 第三版中,您对原型继承的唯一访问是通过创建具有 prototype 属性的构造函数。即使您不打算对它做任何事情,您也必须创建该函数。 This question 涵盖了类/实例系统的常见模式。

在 ECMA 5 中,您确实会得到 Object.create()。为了与当前尚不支持的浏览器兼容,您可以使用不执行任何操作的临时构造函数自己实现Object.create() 的那部分,例如:

if (!('create' in Object)) {
    Object.create= function(proto, props /* optional */) {
        var obj;
        if (proto===null) {
            obj= {};
        } else {
            Object.create._construct.prototype= proto;
            obj= new Object.create._construct();
            Object.create._construct.prototype= null;
        }
        if (props!==undefined)
            Object.defineProperties(obj, props);
        return obj;
    };
    Object.create._construct= function() {};
}

(当然,Object.defineProperties 是另一种 ES5 方法,如果你想支持它,你必须使用它,而这在普通 ES3 中是不可能实现的,只能使用其他浏览器扩展。)

我听说通过分配给__proto__ 属性可以做一些这种魔术,但不知道如何。

这一直是非标准的,即使在 Firefox 中也会消失。不用管它。

【讨论】:

  • 我希望像 Function.create(proto, f) 这样的东西也存在,返回一个等于 f 的函数,但具有给定的原型。那我可以说type = Function.create(kind, function() {})
  • @saintali:不是本地的。不过,您当然可以用很少的代码自己实现一个,例如链接问题中的var type= kind.makeSubclass()
  • __proto__ 无处不在,不仅仅是在 Firefox 中。不过,在它解决的所有用例都可以与其他东西一起使用之前,它仍然会存在一段时间。 (目的是让对象的 [[Prototype]] 在对象创建时变得不可变。)
  • @bobince 我看不出kind.makeSubclass() 是如何解决这个问题的。我想要type instaceof kind,但不想要new type() instaceof kind。正如我在更新后的问题中所说,我希望type 成为person 的(元)类型,kind 成为type 的(元元)类型。
【解决方案2】:

尝试new type.constructor(),它将创建一个与type 相同类型的新对象,这可能是您想要的。

【讨论】:

  • type.constructorkind,所以这将创建一个新的kind,而不是一个新的type
【解决方案3】:

据我了解,您希望type 继承kind?是吗?

如果是这样……

function kind() {};
kind.prototype.name = "fred";
function type() {};
type.prototype = new kind();

var person = new type();
colsole.log(person.name);  //fred

console.log(person instanceof type);  // true
console.log(person instanceof kind);  // true

console.log(type.prototype instanceof kind);   //true

【讨论】:

  • 我希望这条instanceof 链是真的:john instanceof person && person instance of type && type instance of kind
  • 查看更新。如您所见, person 是它所继承的所有类型的一个实例。
  • 谢谢,但person instanceof kind 有问题,请查看更新后的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多