1

我正在使用 jQuery 库创建一个插件。

在这里,我将String.prototype存储在一个变量中,然后我使用这个变量来扩展我的 Sting 对象。这工作正常。

// String Prototyping store in a variable
// Save bytes in the minified version of js
var StrProto = String.prototype;
String.prototype.toProperCase = function () {
  return this.replace(/\w\S*/g, function (txt) {
    return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
  });
};
// working fine
alert("yogesh kumar".toProperCase());

在下一种情况下,我正在创建存储在 abc变量中的 m函数 xyz ,这也可以正常工作。

function xyz(x){
  alert(x)
}
var abc = xyz;
// working fine
abc("yogesh kumar");

在最后一种情况下,我将document.createElement存储在变量 标签中并使用标签创建按钮。但这不起作用。

var tag=document.createElement;
$(document.createElement("button")).html("document.Element").appendTo("#myDiv");

// not working
$(tag("button")).html("tag").appendTo("#myDiv");

请检查 jsFiddle 上的链接:

点击这里

错误:

在 Chrome 中

  • 未捕获的类型错误:非法调用

在火狐中

  • 错误:NS_ERROR_XPC_BAD_CONVERT_JS:无法转换 JavaScript 参数

为什么会出现这个错误?

解决办法是什么?

4

5 回答 5

7

您正在获得对作为文档成员的函数的引用。当您直接调用该引用时,它的上下文现在是窗口而不是文档。这是一个例子:

http://jsfiddle.net/DeCNx/

var foo = {
  createElement: function(tagname) {
    if (this._secretvarthatisneeded) {
      console.log(tagname + " Element Created!");
    }
  },
  _secretvarthatisneeded: true
}

foo.createElement("FOOBAR"); // works

var bar = foo.createElement;
bar("BARFOO"); // doesn't work
bar.call(foo,"BARBAR") // works

由于上下文丢失,bar()调用没有导致console.log();

显然这只是为了简化演示。

更新:对于您正在使用的用途,我建议您这样做:

$.createElement = function(tagName,attributes){
    return $(
        document.createElement(tagName),
        attributes ? attributes : {}
    )
}

现在您可以简单地执行$.createElement("button").html("tag").appendTo("#myDiv");它,它既快速又易于阅读。但是请注意,IE 的输入存在问题,如果您正在创建输入元素,我建议使用$("<input type='text' />")而不是 this。

于 2013-01-07T19:40:11.300 回答
5

使用bind()将本机 JS 方法“分配”给变量的方法:

var ce = document.createElement.bind(document);
var elem = ce('div');
alert(elem.nodeName);

适用于现代浏览器,包括 IE9+。对于较旧的浏览器,请使用包装函数。

于 2013-01-07T19:37:01.507 回答
4

jQuery 可以为您创建新元素,如下所示:

$("<button />").html("document.Element").appendTo("#myDiv");

要了解您的方法不起作用的原因,请阅读下面的@Kevin 评论

于 2013-01-07T19:29:58.633 回答
2

发生这种情况是因为在其内部document.createElement使用。this当你像document.createElement()then一样调用它时,它this被设置为document. 但是,当您将其保存为变量时,则this不再是document,而是window

您需要使用上下文调用它。

var tag = document.createElement;  // you are saving the function, not its context
var btn = tag.call(document, 'button'); // you need to set the context

如果您的浏览器支持它,您还可以使用.bind

var tag = document.createElement.bind(document);
var btn = tag('button');
于 2013-01-07T19:39:27.510 回答
2

此错误的原因是该方法丢失了其上下文。该方法createElement()必须在document对象的上下文中调用。

在控制台中试试这个:

var tag = document.createElement;
tag.call(document, "div");  // no error
tag("div");  // error

为什么createElement()必须在上下文中调用的具体细节是特定于document实现的,但很容易猜到。

因此,要维护上下文,请为以下内容创建一个函数包装器document.createElement()

function tag(tagName) {
    return document.createElement(tagName);
}

当然,jQuery 也会为你创建元素:

$("<div>");  // new div element
于 2013-01-07T19:39:38.457 回答