油猴脚本已加载但Array.prototype.findLast Polyfill不生效问题
Array.prototype.findLast Polyfill油猴脚本内部生效,但控制台访问返回undefined
我通过Blackbox生成了一个为Array.prototype.findLast提供polyfill的油猴脚本,用于兼容不支持该方法的旧浏览器。测试时能看到脚本的console.log输出,说明脚本已执行,且脚本内部的测试代码testArray.findLast能正确返回结果4,但页面加载后在控制台直接访问Array.prototype.findLast却返回undefined。
脚本代码
// ==UserScript== // @name Array.prototype.findLast Polyfill // @author ychaouche // @namespace ychaouche.scripts // @version 2024-11-04 // @description Add findLast method to Array.prototype if it doesn't exist // @match *://*/* // ==/UserScript== (function() { 'use strict'; if (!Array.prototype.findLast) { Array.prototype.findLast = function(callback, thisArg) { if (this == null) { throw new TypeError('Array.prototype.findLast called on null or undefined'); } if (typeof callback !== 'function') { throw new TypeError('callback must be a function'); } const list = Object(this); const length = list.length >>> 0; for (let i = length - 1; i >= 0; i--) { if (i in list) { const element = list[i]; if (callback.call(thisArg, element, i, list)) { return element; } } } return undefined; }; console.log('Array.prototype.findLast polyfill has been added.'); } else { console.log('Array.prototype.findLast already exists.'); } // Optional: Test the polyfill var testArray = [1, 2, 3, 4, 5]; var lastEven = testArray.findLast(num => num % 2 === 0); console.log('Last even number:', lastEven); })();
控制台输出
Array.prototype.findLast polyfill has been added. Array.prototype.findLast-Polyfill.user.js:37:17 Last even number: 4 >>> Array.prototype.findLast undefined
问题原因
这是因为油猴脚本运行在独立的沙箱环境中,脚本内部修改的Array.prototype属于沙箱内的全局对象,和浏览器控制台直接访问的页面主环境Array.prototype并非同一个引用。油猴的沙箱机制用于隔离脚本与页面代码、其他脚本的作用域,避免冲突,但也导致了polyfill无法作用到页面主环境。
解决方案
要让polyfill作用到页面主环境的Array.prototype,需要通过油猴提供的unsafeWindowAPI突破沙箱,直接操作页面的全局作用域。
修改后的脚本
// ==UserScript== // @name Array.prototype.findLast Polyfill // @author ychaouche // @namespace ychaouche.scripts // @version 2024-11-04 // @description Add findLast method to Array.prototype if it doesn't exist // @match *://*/* // @grant unsafeWindow // ==/UserScript== (function() { 'use strict'; // 获取页面主环境的Array构造函数 const PageArray = unsafeWindow.Array; if (!PageArray.prototype.findLast) { PageArray.prototype.findLast = function(callback, thisArg) { if (this == null) { throw new TypeError('Array.prototype.findLast called on null or undefined'); } if (typeof callback !== 'function') { throw new TypeError('callback must be a function'); } const list = Object(this); const length = list.length >>> 0; for (let i = length - 1; i >= 0; i--) { if (i in list) { const element = list[i]; if (callback.call(thisArg, element, i, list)) { return element; } } } return undefined; }; console.log('Array.prototype.findLast polyfill has been added to page global scope.'); } else { console.log('Array.prototype.findLast already exists in page global scope.'); } // 测试页面主环境的数组 var testArray = new unsafeWindow.Array(1, 2, 3, 4, 5); var lastEven = testArray.findLast(num => num % 2 === 0); console.log('Last even number in page scope:', lastEven); })();
关键修改点
- 在脚本元信息中添加
@grant unsafeWindow,启用油猴的unsafeWindow权限; - 用
unsafeWindow.Array获取页面主环境的Array构造函数,替代沙箱内的Array; - 修改
PageArray.prototype.findLast,让页面环境的所有数组实例都能访问该方法; - 测试时使用
unsafeWindow.Array创建数组,确保测试的是页面主环境的数组。
修改完成后,控制台访问Array.prototype.findLast即可看到polyfill方法,页面内的代码也能正常调用findLast。
内容的提问来源于stack exchange,提问作者ychaouche
相关产品推荐
相关产品推荐

