【问题标题】:Making an object non-callable使对象不可调用
【发布时间】:2023-03-15 21:55:01
【问题描述】:

在 JavaScript 中,函数是可调用的。

我可以从函数中删除这个属性,只留下一个普通对象吗?

var foo = function () {};
foo.[[callable]] = false; // pseudocode
foo(); // "foo is not a function"

【问题讨论】:

  • 出于好奇,您想要做什么,而普通的旧对象无法做到?
  • @user3749178 好奇心。
  • 您可能需要深入研究 V8 之类的实现,以了解它如何确定它是函数对象还是常规对象。我从未见过这种区别记录在案。如果typeof(foo) 返回'function',则假定它是可调用的,我很确定您不能更改现有对象的类型。
  • 能够subclass Function 是 ES6 的一部分,但我认为这不会让你让它不可调用。
  • 为了回答您的问题,我需要更好地了解预期用途

标签: javascript


【解决方案1】:

我可以从函数中删除这个属性,只留下一个普通对象吗?

没有。函数(评估行为,而不是它们的对象属性)几乎是不可变的。

对象的callability 取决于它们是否具有[[call]] 槽。 spec says about those

内部插槽是在创建对象的过程中分配的,不能动态添加到对象中。

(暗示它们也不能被动态删除)。此外,“这些内部方法不是 ECMAScript 语言的一部分”和“不是对象属性”,这意味着它们不能以任何方式访问、设置、删除或操作通过语言可以想象的方式。

[[call]] 插槽是各种对象的一部分,它们总是包含一个内部方法,但除了初始化(一次)之外,它们永远不会发生变异。它们有多种:

如您所见,无法更改甚至删除对象的[[call]] 插槽,即使在代理上也是如此。你最好的选择是

  • 在不合时宜的状态下调用函数throw
  • 从函数中创建一个新的、不可调用的对象

    var obj = Object.assign(Object.create(Object.getPrototypeOf(fn)), fn);
    

【讨论】:

  • 哇,那 125 个代表来得很快 :-)
  • 你回答了这个问题!不像其他 100 人看过它,还有三个反对者。
【解决方案2】:

据我所知你不能。

这些函数有一个名为call() 的属性,它调用函数的主体(抱歉冗余)。

您可以将此属性设置为任何表达式,例如

foo.call = console.log('foo not a function');

但这不会阻止调用函数的主体。

而且由于不能将其设置为函数,所以不能使用event.preventDefault() 函数。

【讨论】:

    【解决方案3】:

    我喜欢为Bergi 已经did mention 提供一个额外的观点,OP 的问题中的这个答案也鼓励了我。

    出于什么目的? – 用户 3749178 4 月 16 日 16:18

    .

    @user3749178 好奇。 – 本阿斯顿 4 月 16 日 16:19

    除了依赖于ES6var obj = Object.assign(Object.create(Object.getPrototypeOf(fn)), fn); 之外,还有一种ES3 兼容方法可以将函数对象包装到可调用 对象中。因此,调用运算符() 不能再调用这些对象,但这些对象仍然公开两个调用方法callapply。 由于这种方法一方面防止函数对象被()(方法/函数)或new 运算符(实例化)调用,另一方面它仍然支持委托(基于函数的混合/特征)。

    Function.toApplicator的要点托管代码

    【讨论】:

      【解决方案4】:

      这不是一个优雅的解决方案,其想法是创建“已启用”属性作为标志以了解该功能是否已启用:

      var foo = function () { 
        if(!arguments.callee.enabled){
          throw "function disabled";
        }
        console.log("Hello");
      }
      
      foo.enabled = true;
      foo();
      foo.enabled = false;
      foo();
      

      【讨论】:

      • 这个解决方案不是我喜欢的,因此我提供奖励
      猜你喜欢
      • 2021-08-21
      • 2018-09-30
      • 2021-02-18
      • 1970-01-01
      • 2018-03-01
      • 2021-07-15
      • 2016-04-20
      • 2017-09-20
      • 2016-10-01
      相关资源
      最近更新 更多