如何在 JavaScript 中为可调用对象创建构造函数?
我尝试了多种方式,例如以下。那里的例子只是实际对象的缩短例子。
function CallablePoint(x, y) {
function point() {
// Complex calculations at this point
return point
}
point.x = x
point.y = y
return point
}
这起初有效,但它创建的对象不是 CallablePoint
的实例,因此它不会从 CallablePoint.prototype
复制属性并说 在 instanceof CallablePoint
上为 false
。是否可以为可调用对象创建工作构造函数?
事实证明这实际上是可能的。通过使用 function
语法或 Function
构造函数创建函数时,它会获得内部 [[Call]]
属性。它不是函数本身的属性,而是任何函数在构造时获得的属性。
虽然这仅意味着任何具有 [[Call]]
的东西在构造时都只能是 Function
(好吧,有一个异常(exception)——Function.prototype
本身不从 Function
继承),这并不意味着它以后不能变成其他东西,同时保留 [[Call]]
属性。好吧,前提是您的浏览器不是 IE < 11。
允许改变魔法的是 ES6 中的 __proto__
,它已经在许多浏览器中实现。 __proto__
是一个包含当前原型(prototype)的神奇属性。通过更改它,我可以创建继承自不是 Function
的函数。
function CallablePoint(x, y) {
function point() {
// Complex calculations at this point
return point
}
point.__proto__ = CallablePoint.prototype
point.x = x
point.y = y
return point
}
// CallablePoint should inherit from Function, just so you could use
// various function methods. This is not a requirement, but it's
// useful.
CallablePoint.prototype = Object.create(Function.prototype)
首先,CallablePoint
的构造函数创建了一个Function
(只有Function
允许以[[Call]] 开头
属性。接下来,我改变它的原型(prototype),所以它会继承 CallablePoint
。此时我有一个不继承自 Function
的函数(有点像令人困惑)。
在为 CallablePoint
定义构造函数后,我将 CallablePoint
的原型(prototype)设置为 Function
,所以我有 CallablePoint
继承自 Function
。
这样,CallablePoint
实例就有了原型(prototype)链:CallablePoint -> Function -> Object
,同时仍然是可调用的。此外,由于该对象是可调用的,因此根据规范,它的 typeof
等于 'function'
。