1

My prototypical example is the following pseudo-code:

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

But the problem here is that type is not a function so new type() won't work. Is there an specific property that you can add to an object to make it acceptable to new?

What most matters to me is the prototype chain, that is what matters for me, that is person.[[Prototype]] should be type, etc, in case that is not possible with new.

Creating a subtyping chain is not an option. Here type is the meta-type of person, not its supertype. Likewise kind is a meta-meta-type. The following tests may clarify the requirements: When all done, I want these positive tests:

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

and these negative tests:

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

I hear that by assigning to the __proto__ property one can do some magic of this sort, but don't know how. Obviously a portable solution (by using Object.create for example) is much preferred, if there is one.

Tom van der Woerdt
  • 29,532
  • 7
  • 72
  • 105
Saintali
  • 4,482
  • 2
  • 29
  • 49
  • So are you simply trying to create a `person`, which is-a `type`, which is-a `kind`? So every time you're making a new `person`, you're implicitly making a new `kind`, and automatically getting all the features of that type? – Merlyn Morgan-Graham Aug 26 '11 at 22:31
  • No I don't want a subtyping chain, I want `person` to be instance of `type` in the same way that `john` is instance of `person`. – Saintali Aug 26 '11 at 23:01
  • This is confusing, especially with your comment on FunkyFresh's answer. 1) You want an is-a relationship between the types? 2) You don't want to inherit any structure or functionality from the base type? – Merlyn Morgan-Graham Aug 26 '11 at 23:10
  • 1
    I updated the question to clarify this issue. Does this make sense now? – Saintali Aug 26 '11 at 23:13

3 Answers3

2

Is there an specific property that you can add to an object to make it acceptable to new?

No. The property that controls this ability according to ECMAScript section 11.2.2 is called [[Construct]], and as you can tell from the square brackets, it's an internal property. It can't be influenced from ECMAScript code. The only time [[Construct]] gets assigned is, according to section 13.2, when a Function object is created.

The only access you have to prototypal inheritance in ECMAScript Third Edition is through creating constructor functions with a prototype property. You have to create the function even if you don't intend to do anything with it. This question covers common patterns of class/instance systems.

In ECMA 5 you indeed get Object.create(). For compatibility with current browsers that don't support it yet, you can implement that part of Object.create() yourself using a temporary constructor function that does nothing, eg:

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() {};
}

(Of course Object.defineProperties is another ES5 method that you'd have to shim in if you wanted support for that, and that's not possible to implement in plain ES3, only using other browser extensions.)

I hear that by assigning to the __proto__ property one can do some magic of this sort, but don't know how.

This was always non-standard, and is going away even in Firefox. Don't bother with it.

Community
  • 1
  • 1
bobince
  • 528,062
  • 107
  • 651
  • 834
  • I hope something like `Function.create(proto, f)` exists as well, returning a function equal to `f`, but with the given prototype. Then I could say `type = Function.create(kind, function() {})` – Saintali Aug 26 '11 at 22:51
  • @saintali: Not natively. You can certainly implement one yourself in very little code, though, eg `var type= kind.makeSubclass()` in the linked question. – bobince Aug 26 '11 at 22:59
  • `__proto__` is going away everywhere, not just in Firefox. Still will be around for a bit until all the use-cases addressed by it are possible with other stuff, though. (The intention is for the [[Prototype]] of an object to become immutable at object creation time.) – gsnedders Aug 26 '11 at 23:25
  • @bobince I don't see how `kind.makeSubclass()` solves that problem. I want `type instaceof kind` but not `new type() instaceof kind`. As I said in the updated question, I want `type` to be the (meta-)type of `person` and `kind` to be the (meta-meta-)type of `type`. – Saintali Aug 26 '11 at 23:48
0

try new type.constructor(), which will create a new object of the same type as type, that may be what you want.

erikvold
  • 15,988
  • 11
  • 54
  • 98
0

As I understand it, you want type to inherit kind? yes?

if so...

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
Duncan Gravill
  • 4,552
  • 7
  • 34
  • 51