21

可能重复:
如果 Javascript 具有一流的功能,为什么这不起作用?

当我尝试为document.getElementById如下创建别名函数时:

f = document.getElementById;

但是,当我尝试打电话时:

var e_fullname = f(“fullname”);

出现错误: Could not convert JavaScript argument

以下是可以的:

var e_fullname = f.call(document, “funname”);

你能告诉我为什么吗?

4

3 回答 3

31

调用函数有四种方式:

  1. 函数调用:f(p1, p2)
  2. 方法调用:obj.f(p1, p2)
  3. 应用或调用调用:f.apply(obj, [p1, p2]),f.call(obj, p1, p2)
  4. 构造函数调用:new f(p1, p2)

在所有这些情况下,f它只是对函数对象(具有[[Call]]内部属性的对象)的引用(指针)。在所有这些情况下,它的行为不同的是函数的调用方式,这很重要。

所以,f只是对对象的引用,和getElementById之间没有区别;该函数不会保留对引用它的对象的引用。document.getElementByIdsomeOtherHTMLElement.getElementById

如果要绑定某个“所有者”对象,请使用以下bind方法:

var f = document.getElementById.bind(document);
于 2012-10-21T17:10:16.110 回答
7

getElementById是文档上的一种方法。要调用它,解释器需要具有函数体本身、调用它的对象(在您的情况下为文档)和参数。

当你这样做时f = document.getElementById,你正在复制函数体,而不是要调用它的对象。

当你这样做时:

f.call(document, “funname”);

您提供了调用它的对象和参数。

如果您希望能够直接调用 f,则需要以某种方式获取存储在其中的“文档”对象。最简单的是:

var f = function(name){return document.getElementById(name)}

这将创建一个闭包,它为您保留文档的价值。

你也可以使用 bind() 来做同样的事情。

于 2012-10-21T17:04:29.300 回答
2

你可以使用bind

创建一个新函数,在调用该函数时,将其 this 关键字设置为提供的值,并在调用新函数时提供的任何参数之前具有给定的参数序列。

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

它是在 ES5 中引入的,因此请注意尚不支持此版本 ECMAScript 的浏览器!

作为替代方案,您可以使用proxyjQuery 的方法,在版本中添加1.4

var f = ​$.proxy(document.getElementById, document);

或者您可以将 delcaref作为其自身的功能(这是一个更详细的解决方案)。

var f = function() { return document.getElementById(arguments); }
于 2012-10-21T17:02:04.150 回答