在 JavaScript 中,函数是可调用的。
我可以从函数中删除这个属性,只留下一个普通对象吗?
var foo = function () {};
foo.[[callable]] = false; // pseudocode
foo(); // "foo is not a function"
我可以从函数中删除这个属性,只留下一个普通对象吗?
不。函数(评估行为,而不是它们的对象属性)几乎是不可变的。
对象的可调用性取决于它们是否有
[[call]]
槽。 规范说明了这些:
内部槽是作为创建对象过程的一部分进行分配的,并且可能不会动态添加到对象中。
(这意味着它们也不能动态删除)。此外,“这些内部方法不是 ECMAScript 语言的一部分”和“不是对象属性”,这意味着它们不能通过语言以任何可以想象的方式访问、设置、删除或操作。
[[call]]
槽是各种对象的一部分,它们始终包含内部方法,但除了初始化(一次)之外,它们永远不会发生变化。它们有多种类型:
[[call]]
用户定义的函数对象,在FunctionAllocate
[[call]]
内置函数对象,由环境隐式初始化[[call]]
,在BoundFunctionCreate
[[call]]
某些代理对象,在 ProxyCreate
的步骤 7a 中进行有条件初始化,前提是代理目标也可调用如您所见,无法更改甚至删除对象的
[[call]]
插槽,即使在代理上也是如此。你最好的选择是
throw
通过
从函数创建一个新的、不可调用的对象var obj = Object.assign(Object.create(Object.getPrototypeOf(fn)), fn);
据我所知你不能。
这些函数有一个名为
call()
的属性,它调用函数的主体(抱歉有些冗余)。
您可以将此属性设置为任何表达式,例如
foo.call = console.log('foo not a function');
但这不会阻止函数体被调用。
并且由于您无法将其设置为函数,因此您无法使用
event.preventDefault()
函数。
我喜欢对Bergi已经提到过的内容提供额外的观点,也受到OP问题中这个答案的鼓励。
目的是什么? – user3749178 4 月 16 日 16:18.
@user3749178 好奇心。 – 本·阿斯顿 4 月 16 日 16:19
除了依赖于
var obj = Object.assign(Object.create(Object.getPrototypeOf(fn)), fn);
的
ES6
之外,还有一种 ES3
兼容方法可以将函数对象包装到 callable对象中。因此,这些对象不再可以由调用运算符
()
调用,但此类对象仍然公开两个调用方法 call
和 apply
。
由于这种方法一方面可以防止函数对象被 ()
(方法/函数)或 new
运算符(实例化)调用,但另一方面它仍然支持委托(基于函数的混合/特征)。的要点托管代码
var foo = function () {
if(!arguments.callee.enabled){
throw "function disabled";
}
console.log("Hello");
}
foo.enabled = true;
foo();
foo.enabled = false;
foo();