You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

油猴脚本已加载但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);
})();

关键修改点

  1. 在脚本元信息中添加@grant unsafeWindow,启用油猴的unsafeWindow权限;
  2. 用unsafeWindow.Array获取页面主环境的Array构造函数,替代沙箱内的Array;
  3. 修改PageArray.prototype.findLast,让页面环境的所有数组实例都能访问该方法;
  4. 测试时使用unsafeWindow.Array创建数组,确保测试的是页面主环境的数组。

修改完成后,控制台访问Array.prototype.findLast即可看到polyfill方法,页面内的代码也能正常调用findLast。

内容的提问来源于stack exchange,提问作者ychaouche

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 15:18:18