Reputation: 1076
So I've been playing with prototypal inheritance in CoffeeScript, and in particular with how one can go about writing CoffeeScript classes that inherit from a particular object, rather than another class, similar to Crockford's object function. Essentially what I'd like to do is to write a class that can inherit from a particular object passed in to its constructor. Unfortunately, I believe this may be impossible without resort to setPrototypeOf
, which, given the rather alarming warnings about it, I'd rather not do. Instead I am probably going to settle for a function that can do something similar. Below are two possibilities:
a = {foo: 1}
class Example
constructor: (@bar) ->
extendObject = (parent, Class, args...) ->
F = (anon...) -> Class.apply(@, anon)
F:: = Object.create parent
F::constructor = Class
new F args...
extendObjectMaker = (parent, Class) ->
F = (anon...) -> Class.apply(@, anon)
F:: = Object.create parent
F::constructor = Class
F
maker = extendObjectMaker a, Example
test1 = extendObject a, Example, 2
test2 = new maker 2
Now, I greatly prefer the second approach, since essentially what it is returning is a new class, which you can then use regular constructor syntax with. There's just one problem: while objects created using extendObject
correctly identify as Example
s, objects created using the constructor returned by extendObjectMaker
identify as F
s, and are not instances of Example
.
console.log test1 instanceof Example # True
console.log test2 instanceof Example # False
Given that these functions use almost exactly the same code, I'm having difficulty figuring out just why they're exhibiting different behavior. So, does anyone know why test2
is not showing up as an Example
, and what I need to change to make it do so?
Upvotes: 1
Views: 119
Reputation: 5395
Take a look at the CoffeeScript source code: http://coffeescript.org/v1/annotated-source/nodes.html#section-60.
CoffeeScript treats constructor calls differently depending on whether they are called with a splat (args...
) or without one.
Your code will give the desired result if you either invoke the extendObjectMaker with new maker [2]...
or re-write your function as follows:
extendObjectMaker = (parent, Class) ->
F = (anon...) -> Class.apply(@, anon)
F:: = Object.create parent
F::constructor = Class
(args...) -> new F args...
Upvotes: 2