JavaScript中可调用对象的构造函数[duplicate]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript中可调用对象的构造函数[duplicate]相关的知识,希望对你有一定的参考价值。
这个问题在这里已有答案:
如何在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
的属性,并且在false
上说instanceof CallablePoint
。是否可以为可调用对象创建工作构造函数?
原来它实际上是可能的。通过使用function
语法或Function
构造函数创建函数时,它获取内部[[Call]]
属性。它不是函数本身的属性,而是任何函数在构造时获得的属性。
虽然这只意味着任何有[[Call]]
的东西在构造时可能只有Function
(好吧,有一个例外 - Function.prototype
本身并不从Function
继承),这并不意味着它不能在以后成为别的东西,同时保留[[Call]]
属性。好吧,如果您的浏览器不是IE <11。
允许改变魔法的是来自ES6的__proto__
,已在许多浏览器中实现。 __proto__
是一个神奇的属性,包含当前的原型。通过改变它,我可以创造继承自非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
s以[[Call]]
属性开头。接下来,我更改其原型,因此它将继承CallablePoint
。此时我有一个不继承Function
的函数(有点混乱)。
在我为CallablePoint
s定义了构造函数之后,我将CallablePoint
的原型设置为Function
,所以我拥有继承自CallablePoint
的Function
。
这样,CallablePoint
实例具有原型链:CallablePoint -> Function -> Object
,同时仍然可以调用。此外,因为对象是可调用的,所以根据规范,typeof
等于'function'
。
假设您使用Python中的__call__
功能并且通常称为“可调用对象”,我将写下我的答案。 “可调用对象”在JavaScript上下文中听起来很陌生。
我已经尝试了几个JavaScript引擎,但是我尝试的那些都没有允许你调用对象,即使你从Function
继承。例如:
function Callable(x) {
... "use strict";
... this.__proto__ = Function.prototype;
... this.toString = function() { return x; };
... }
undefined
> var c = new Callable(42);
var c = new Callable(42);
undefined
> c;
c;
{ toString: [function] }
> c(42);
c(42);
TypeError: Property 'c' of object #<Object> is not a function
at repl:1:1
at REPLServer.eval (repl.js:80:21)
at repl.js:190:20
at REPLServer.eval (repl.js:87:5)
at Interface.<anonymous> (repl.js:182:12)
at Interface.emit (events.js:67:17)
at Interface._onLine (readline.js:162:10)
at Interface._line (readline.js:426:8)
at Interface._ttyWrite (readline.js:603:14)
at ReadStream.<anonymous> (readline.js:82:12)
> c instanceof Function;
c instanceof Function;
true
c.apply(null, [43]);
TypeError: Function.prototype.apply was called on 43, which is a object and not a function
at Function.APPLY_PREPARE (native)
at repl:1:3
at REPLServer.eval (repl.js:80:21)
at repl.js:190:20
at REPLServer.eval (repl.js:87:5)
at Interface.<anonymous> (repl.js:182:12)
at Interface.emit (events.js:67:17)
at Interface._onLine (readline.js:162:10)
at Interface._line (readline.js:426:8)
at Interface._ttyWrite (readline.js:603:14)
>
这是V8(Node.js)。即你可能有一个对象,它正式继承自函数,但它不可调用,我找不到一种方法来说服运行时它可能被调用。我在Mozilla的JavaScrip实现中有类似的结果,所以我认为它必须是通用的。
但是,自定义类型在JavaScript中的作用非常小,所以我认为你无论如何都不会错过它。但是,正如您已经发现的那样,您可以在函数上创建属性,就像在对象上一样。所以,你可以用一种不太方便的方式来做到这一点。
如果你使用CallablePoint
关键字,我不确定你是否知道你的对象只是new
的一个实例。通过命名它“可调用”,你让我觉得你不想使用new
。无论如何,有一种方法可以强制返回一个实例(感谢提示,Resig):
function CallablePoint(x, y) {
if (this instanceof CallablePoint) {
// Your "constructor" code goes here.
// And don't return from here.
} else {
return new CallablePoint(x, y);
}
}
这将返回CallablePoint
的一个实例,无论它是如何被调用的:
var obj1 = CallablePoint(1,2);
console.log(obj1 instanceof CallablePoint); // true
var obj2 = new CallablePoint(1,2);
console.log(obj2 instanceof CallablePoint); // true
如果您希望CallablePoint()
构造函数返回CallablePoint类型的对象,那么您可以执行类似这样的操作,其中CallablePoint对象包含一个点作为对象的属性,但仍然是CallablePoint对象:
function CallablePoint(x, y) {
this.point = {};
this.point.x = x
this.point.y = y
}
或者,如果您真正想要做的是创建一个返回CallablePoint对象的函数,那么您可以创建一个因子函数:
function CallablePoint(x, y) {
this.point = {};
this.point.x = x
this.point.y = y
}
function makeCallablePoint(x, y) {
return new CallablePoint(x,y);
}
以上是关于JavaScript中可调用对象的构造函数[duplicate]的主要内容,如果未能解决你的问题,请参考以下文章