我们都知道JavaScript中构造函数是用来创建对象实例的。我想知道自定义的构造函数是否可以创建函数实例?或者其他数据类型的实例?
-----------------------2017年1月8日更新-----------------------
根据回答的朋友提示,以闭包的形式创建函数实例,我做了一个演示例子:
function Foo () {
return function() {
console.log('Foo');
}
}
Foo.prototype.outStr = function() {
console.log('abc');
}
var f = new Foo();
f();
f.outStr();
如果f是Foo构造函数创建的实例,那么实例应该会继承构造函数的prototype原型对象上的属性和方法。
但是上面这段代码中,f.outStr()执行后,会提示f.outStr不是一个函数。也就是说f并没有集成到outStr这个方法。
首先来说,你是希望构造一个函数对象,而它同时又具有你自定义的类方法……这在 ES6 里其实是很容易通过继承实现的
不过在 ES5 里也有不是很完美的实现方法,比如改变
f
的__proto__
为Foo.prototype
。不过这样改过之后你会发现f
不再具有函数对象的一些方法,比如call()
、apply()
、bind()
等。同时__proto__
不在标准中,所以不能保证每一个 JS 引擎都实现了。回过头来说 ES6 的办法——因为 ES6 可以通过很多工具,比如
babel
翻译成ES5
的,所以 ES6 实现了,ES5 也就能实现 (现在我对这句话表示怀疑——具体请看后面) 。ES6 中,
Foo
从Function
继承,所以可以通过Foo
构造一个函数对象,同时它可以用Foo
中定义的方法。但问题在于构造这个对象的时候不能使用 function 定义语法,也不能使用函数表达式等,必须直接使用Function
构造函数。构造函数需要函数体文本为作参数,比如当然函数体很短的时候不是问题,比较长的时候才是麻烦的事情。当然可以用 es6 引入的 模板字符串 来解决,它允许多行字符。这会损失编辑器对其语法的检查。所以我的办法是定义一个临时函数,再通过
toString()
和正则表达式把函数体找出来。最终完成的代码是这样的:
不过很遗憾,使用 TypeScript 和 Babel 转出来的 es5 代码都不能运行……