Bug 重现步骤
在http服务器放置以下网页bug1.htm
,打开网址时报错,网页代码如下:
比如 http://www.example.com/bug1.htm
<div id="ctn_login"></div>
<button id="btn_login">Login</button>
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<script>
(function ($) {
$.fn.verify = function () {
alert(1);
return true;
};
})(jQuery);
$('#btn_login').click(function () {
var ctn_login = $('#ctn_login');
if (!ctn_login.verify()) {
return false;
}
});
</script>
错误提示如下:
bug1:16 Uncaught TypeError: ctn_login.verify is not a function
at HTMLButtonElement.<anonymous> (bug1:16:24)
at HTMLButtonElement.dispatch (jquery-3.6.4.min.js:2:43184)
at y.handle (jquery-3.6.4.min.js:2:41168)
(匿名) @ bug1:16
dispatch @ jquery-3.6.4.min.js:2
y.handle @ jquery-3.6.4.min.js:2
基本排查
错误提示 ctn_login.verify is not a function;
,让人难以理解,难道我的浏览器 Js 引擎被智子锁定了。网页代码源自真实网页,经过排除法我排除了其他影响因素,上面是精简后剩下的骨干代码。离奇的是,如果将 var ctn_login = $('#ctn_login');
这句移动到全局似乎不报错。
<div id="ctn_login"></div>
<button id="btn_login">Login</button>
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<script>
// 位置1:移到这里不报错
// var ctn_login = $('#ctn_login');
(function ($) {
$.fn.verify = function () {
alert(1);
return true;
};
})(jQuery);
// 位置2:移到这里偶尔报错
var ctn_login = $('#ctn_login');
$('#btn_login').click(function () {
if (!ctn_login.verify()) {
return false;
}
});
</script>
然后,我发现,关闭浏览器安装的扩展 PageXray 1.31 版本,不再报错。
继续检查 ctn_login 点击事件中的 ctn_login 是一个jQuery 对象,但未被扩展出包含 verify 方法。
<div id="ctn_login"></div>
<button id="btn_login">Login</button>
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<script>
(function ($) {
$.fn.verify = function () {
alert(1);
return true;
};
})(jQuery);
var ctn_login1 = $('#ctn_login');
alert(ctn_login1 instanceof jQuery); // true
alert(typeof ctn_login1.verify); // function
$('#btn_login').click(function () {
var ctn_login = $('#ctn_login');
alert(ctn_login instanceof jQuery); // true
alert(typeof ctn_login.verify); // undefined
if (!ctn_login.verify()) {
return false;
}
});
</script>
另外补充一下,我在本地 apache httpd server(未开启SSL) 上,关闭 PageXray 不报错,打开 PageXray 报错,上传到服务器,https 证书下有时报错,有时不报错。
根因分析
说实话,我开始准备去 stackoverflow 提问,但发现 PageXray 已从 Chrome App Store 下架了,可能不方便其它人分析。我猜想可能原因是 PageXray 源码中某代码比如低版本 jQuery 影响了 JavaScript 执行。
总之,这种调整代码顺序重现的 Bug 让我以为我的 Js 引擎被智子锁定了。
寻求解答
由于已通过关闭 PageXray 解决这个报错问题,但问题产生的原因我依然未弄明白,尤其是这种偶然重现的缺陷,按照经验一般是和 Js 的异步机制有关。希望有哪位老师看到,可以拿代码分析一下,指定指定迷津。
附上从%userprofile%\AppData\Local\Microsoft\Edge\User Data\Default\Extensions\aedmpdookgbneegaeajpoldpnpfbpmlb
拿出的PageXray 源码