【问题标题】:If JavaScript has first-class functions, why doesn’t calling this function in a variable work?如果 JavaScript 有一流的函数,为什么在变量中调用这个函数不起作用?
【发布时间】:2012-01-07 22:20:29
【问题描述】:

据称 JavaScript 具有一流的功能,所以这似乎应该起作用:

var f = document.getElementById;
var x = f('x');

但它在所有浏览器上都失败了,每个浏览器都有不同的神秘错误消息。 Safari 显示“类型错误”。 Chrome 显示“非法调用”。 Firefox 提示“无法转换 JavaScript 参数”。

为什么?

【问题讨论】:

    标签: javascript


    【解决方案1】:

    当您在 Javascript 中调用 obj.method() 时,该方法将 obj 作为 this 传递。调用document.getElementById('x'),因此将this 设置为document

    但是,如果您只写 f = document.getElementById,您现在有了一个新的引用函数,但该引用不再“绑定”到 document

    因此,您的代码不起作用,因为当您将 f 作为裸函数名调用时,它最终会绑定到全局对象 (window)。一旦函数的内部部分尝试使用this,它就会发现它现在有一个window 而不是document,并且毫不奇怪它不喜欢它。

    可以f工作,如果你这样称呼它:

    var x = f.call(document, 'x');
    

    调用f,但将上下文显式设置为document

    解决此问题的其他方法是使用Function.bind(),它在 ES5 及更高版本中可用:

    var f = document.getElementById.bind(document);
    

    实际上只是一个通用的捷径,用于创建您自己的正确设置上下文的包装器:

    function f(id) {
        return document.getElementById(id);
    }
    

    【讨论】:

      【解决方案2】:

      因为在 JavaScript 函数中没有绑定到上下文 (this)。你可以使用bind():

      var f = document.getElementById.bind(document);
      

      【讨论】:

      • 为了澄清这个答案,document.getElementById() 中的thisdocument,而您执行作用域的this 是全局作用域,也就是thiswindow对象。
      【解决方案3】:

      使用 ES6 的扩展运算符,你也可以试试:

      function f(){
          return document.getElementById(...arguments);
      };
      

      Babel 给出了这个:

      function f() {
          var _document;
          return (_document = document).getElementById.apply(_document, arguments);
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多