实用程序函数用于实例化扩展预先存在的对象的CoffeeScript类的实例

时间:2016-03-26 20:03:14

标签: inheritance coffeescript prototype javascript-objects

所以我一直在使用CoffeeScript中的原型继承,特别是如何编写继承自特定对象而不是另一个类的CoffeeScript类,类似于Crockford的对象函数。基本上我想做的是编写一个可以从传入其构造函数的特定对象继承的类。不幸的是,我相信如果不诉诸setPrototypeOf,这可能是不可能的,因为有关它的相当惊人的警告,我宁愿不这样做。相反,我可能会解决一个可以做类似事情的功能。以下是两种可能性:

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

现在,我非常喜欢第二种方法,因为它本质上返回的是一个新类,然后您可以使用常规构造函数语法。只有一个问题:使用extendObject创建的对象正确识别为Example时,使用extendObjectMaker返回的构造函数创建的对象标识为F,并且不是Example

console.log test1 instanceof Example # True
console.log test2 instanceof Example # False

鉴于这些函数使用几乎完全相同的代码,我很难弄清楚它们为何表现出不同的行为。那么,有没有人知道为什么test2没有显示为Example,我需要改变什么才能让它这样做?

1 个答案:

答案 0 :(得分:2)

查看CoffeeScript源代码:http://coffeescript.org/v1/annotated-source/nodes.html#section-60

CoffeeScript以不同方式处理构造函数调用,具体取决于是使用splat(args...)调用还是使用splat调用它们。

如果 调用带有new maker [2]... 或重新编写函数的extendObjectMaker,您的代码将提供所需的结果:

extendObjectMaker = (parent, Class) ->
  F = (anon...) -> Class.apply(@, anon)
  F:: = Object.create parent
  F::constructor = Class
  (args...) -> new F args...