【问题标题】:Chrome sometimes calls incorrect constructorChrome 有时会调用不正确的构造函数
【发布时间】:2012-04-25 11:50:17
【问题描述】:

我们有一个广泛使用 jQuery 的网站,它在 Firefox 和 IE 中运行良好。但是在 Chrome 中,我们经常(和半随机地)获得Uncaught TypeError: Cannot call method 'apply' of undefined(也有其他 jQuery 方法出现在 apply 的位置)。

我们设法将问题追溯到 jQuery 方法pushStack()

原始源代码(jQuery 1.7.1):

// Take an array of elements and push it onto the stack
// (returning the new matched element set)
pushStack: function( elems, name, selector ) {
   // Build a new jQuery matched element set
   var ret = this.constructor();

   // (etc.)
}

仪表代码:

pushStack: function( elems, name, selector ) {
   if (!(this instanceof jQuery.fn.init)) throw this;

   // Build a new jQuery matched element set
   var ret = this.constructor();

   if (!(ret instanceof jQuery.fn.init)) {
          console.log("pushStack>this: " + this.constructor);
          console.log("pushStack>ret: " + ret.constructor);
          throw ret;
   }

   // (etc.)
}

在大多数情况下pushStack() 运行正确。然而,有时 Chrome 会构造一个 Object 类型的对象,而不是 jQuery.fn.init。控制台输出:

pushStack>this: function ( selector, context ) {
    // The jQuery object is actually just the init constructor 'enhanced'
    return new jQuery.fn.init( selector, context, rootjQuery );
    }
pushStack>ret: function Object() { [native code] }
Uncaught #<Object>

有人遇到过类似的问题吗?它是 Chrome 的(已知)错误吗?

更新

我设法简化了我们的页面,以便它可以自行加载。我填写了bug in Chromium project 项目,复制问题的页面附在此处。

【问题讨论】:

  • 你能缩小用例的范围吗?这听起来像是常见的console.log.apply 上下文问题。
  • @David 感谢您的评论。 console.log.apply 上下文问题是什么意思?使用没有检测的原始 jQuery 时也会出现此问题。
  • @MiroslavBajtoš 您是否应用了 Chromium 项目中建议的解决方法?
  • @davidzarlengo 是的,我是该解决方法的作者。
  • 哦,好吧,在那种情况下,谢谢!到目前为止,它也对我们有用。

标签: javascript jquery google-chrome


【解决方案1】:

Chromium 错误跟踪器中的响应似乎确认这是 Chrome 浏览器的错误。

解决方法是在 jQuery 中“修复”pushStack() 函数:

// Take an array of elements and push it onto the stack
// (returning the new matched element set)
pushStack: function( elems, name, selector ) {
   // Build a new jQuery matched element set
   var ret = this.constructor();

   // Workaround for Chrome bug
   if ((this instanceof jQuery.fn.init) && !(ret instanceof jQuery.fn.init)) {
       // console.log("applying pushStack fix");
       ret = new jQuery.fn.init();
   }

   // etc.
}

【讨论】:

  • 感谢您的解决方法!是否有任何可以想象的方式可以应用此解决方法而无需修改 jquery 源文件(例如,在包含来自 Google CDN 的 jquery 缩小文件之后的代码中)?这意味着在我们的构建中包含我们目前没有做的 jquery 源代码。
  • @centralscru 看看下面的回复:stackoverflow.com/a/10727909/69868
  • 太棒了,不知道我怎么错过了!
【解决方案2】:

这是一个“不显眼”的解决方案(例如,如果您从 CDN 中提取 jQuery)。将其保存在 .js 文件中,并在拉入 jQuery 后包含它。

(function ($) {
    var pushStackOrig, pushStackChrome;

    pushStackOrig = $.fn.pushStack;

    pushStackChrome = function ( elems, name, selector ) {
        // Build a new jQuery matched element set

        // Invoke the correct constructor directly when the bug manifests in Chrome.
        //var ret = this.constructor();
        var ret = new jQuery.fn.init(); 

        if ( jQuery.isArray( elems ) ) {
            push.apply( ret, elems );

        } else {
            jQuery.merge( ret, elems );
        }

        // Add the old object onto the stack (as a reference)
        ret.prevObject = this;

        ret.context = this.context;

        if ( name === "find" ) {
            ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
        } else if ( name ) {
            ret.selector = this.selector + "." + name + "(" + selector + ")";
        }

        // Return the newly-formed element set
        return ret;
    };

    $.fn.pushStack = function (elems, name, selector) {
        var ret;

        try {
            ret = pushStackOrig.call(this, elems, name, selector);
            return ret;
        } 
        catch (e) {
            if (e instanceof TypeError) {
                if (!(ret instanceof jQuery.fn.init)) {
                    ret = pushStackChrome.call(this, elems, name, selector);
                    return ret;
                }
            }

            throw e;
        }
    };

}).call(this, jQuery);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    • 2017-07-27
    • 1970-01-01
    • 2021-11-12
    相关资源
    最近更新 更多