Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/470.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 该代码是否可以改进以避免内存泄漏或更稳定?_Javascript_Memory Leaks_Greasemonkey_Tampermonkey - Fatal编程技术网

Javascript 该代码是否可以改进以避免内存泄漏或更稳定?

Javascript 该代码是否可以改进以避免内存泄漏或更稳定?,javascript,memory-leaks,greasemonkey,tampermonkey,Javascript,Memory Leaks,Greasemonkey,Tampermonkey,我已经编译了代码(发布在下面): var-keys=[]; var key1=“17”//控制键 var key2=“16”//转移 var key3=“83”//s window.addGlobalHotkey=函数(回调,keyValues){ 如果(keyValues的类型==“数字”) keyValues=[keyValues]; var fnc=功能(cb,val){ 返回函数(e){ 键[e.keyCode]=真; 执行快捷键测试(cb、val); }; }(回调,键

我已经编译了代码(发布在下面):

var-keys=[];
var key1=“17”//控制键
var key2=“16”//转移
var key3=“83”//s
window.addGlobalHotkey=函数(回调,keyValues){
如果(keyValues的类型==“数字”)
keyValues=[keyValues];
var fnc=功能(cb,val){
返回函数(e){
键[e.keyCode]=真;
执行快捷键测试(cb、val);
};        
}(回调,键值);
window.addEventListener('keydown',fnc);
返回fnc;
};
window.executeHotkeyTest=函数(回调,keyValues){
var allKeysValid=true;
对于(变量i=0;i
  • 允许创建热键(在我的例子中是Ctrl+Shift+S)
  • 设计用于显示输入框(又名
    提示符
  • 并执行命令(一些预定义的
    开关
    或选项)
  • addGlobalHotkey(function(){/PLAY HERE/}[key1,key2,key3])一节中定义
现在你有了整个背景。它在Firefox、Chrome和GreaseMonkey两种浏览器中都能很好地工作,并且完全符合我的需要

然而,我注意到,在任何给定的选项卡上执行它之后,特定的选项卡开始逐渐变慢、挂起、延迟绘制,唯一的解决方法是关闭它。其他选项卡不受影响,仅在执行时处于打开状态的选项卡。所以我担心可能会有内存泄漏,是不是我在代码中遗漏了什么?是否可以通过某种方式加以改进以确保情况并非如此


此外,我还注意到,虽然99%以上的时候,它会很好地释放按键,但有时当你按下键盘上的任何键时,命令就会执行,这表明钩子在某种程度上没有正确地清理自己,导致任何键被卡住,并处理触发器,即使不是指定的键,我错过了什么?稳定性可以提高吗?

您可以做一些事情,但我看不出内存泄漏的原因

我已经评论了我的编辑

var keys = [];

// Integers takes less space than strings, and we might as well put it in an array already
var shortcut = [
    17, // ctrl
    16, // shift
    83  // s
];

window.addGlobalHotkey = function(callback, keyValues){
    if(typeof keyValues === "number")
        keyValues = [keyValues];

    // Unfortunately, because you need the cb argument we can't define it outside the addGlobalHotkey method.
    var fnc = function(cb, val){
        return function(e){
            keys[e.keyCode] = true;
            executeHotkeyTest(cb, val);
        };        
    }(callback, keyValues);

    window.addEventListener('keydown', fnc);
    return fnc;
};

window.executeHotkeyTest = function(callback, keyValues) {
    var i = keyValues.length;

    while(i--) {
        // If key is not pressed, we might as well abort
        if(!keys[keyValues[i]]) return;
    }

    callback();
};

window.addEventListener('keyup',function(e) {
    // Remove key instead of setting it to false
    keys.splice(e.keyCode, 1);
});

addGlobalHotkey(function() {
    var x = getIn("What Task?");

    // If x is empty there's no point in resuming
    if(!x) return;

    // If-statements are faster than switches, just saying.
    switch(x)
    {
        case "a":
            //...
        break;
        case "t":
            //...
            break;
        default:
            //...;
    }
}, shortcut);

function getIn(text){
    var x = prompt(text);

    // Altered if statement
    if(typeof x === 'string' && x.length > 0) return x;
}
最可能的泄漏是,数组键只会随着按更多不同的键而增长。因此使用了
.splice()
方法


编辑 我再次检查了你的代码。我忍不住注意到,每当您注册一个新的热键时,都会创建一个新的
onkeydown
侦听器。我已经改变了。试试下面的代码,看看它是否仍然运行缓慢

/* VARIABLES */

var keysPressed = [];
var hotkeys = [];

/* EVENT LISTENERS */

// Listen for keydown once instead for every hotkey
window.addEventListener('keydown', function(e) {
    // A button was pressed
    keysPressed[e.keyCode] = true;
    checkHotkeys();
}, false);

window.addEventListener('keyup', function(e) {
    // Remove key
    keysPressed.splice(e.keyCode, 1);
}, false);

/* FUNCTIONS */

function checkHotkeys() {
    var i = hotkeys.length;

    while(i--) {
        executeHotkeyTest(
            hotkeys[i].callback,
            hotkeys[i].keys
        );
    }
};

function addGlobalHotkey(callback, keys) {
    if(typeof keys === "number")
        keys = [keys];

    hotkeys.push({
        callback: callback,
        keys: keys
    });
};

function executeHotkeyTest(callback, keys) {
    var i = keys.length;

    while(i--) {
        // If key is not pressed, we might as well abort
        if(!keysPressed[keys[i]]) return;
    }

    callback();
};

function getIn(text){
    var x = prompt(text);

    // Altered if statement
    if(typeof x === 'string' && x.length > 0) return x;
}

/* OTHER */

// Integers takes less space than strings
var shortcut = [
    17, // ctrl
    16, // shift
    83  // s
];

addGlobalHotkey(function() {
    var x = getIn("What Task?");

    // If-statements are faster than switches, just saying.
    switch(x)
    {
        case "a":
            //...
        break;
        case "t":
            //...
            break;
        default:
            //...;
    }
}, shortcut);
编辑#2 我发现了问题

所以我们一直在使用keycode作为数组的索引-一个数字索引。它们是非关联的。请看下面的示例

0: 'abc',
1: 'def',
2: 'ghi'
删除1

0: 'abc',
1: 'ghi'
删除2

0: 'abc',
1: 'ghi'
通过将它们转换为字符串,数组将成为关联数组,并且将删除正确的键

// Listen for keydown once instead for every hotkey
window.addEventListener('keydown', function(e) {
    // A button was pressed
    keysPressed[e.keyCode.toString()] = true;
    checkHotkeys();
}, false);

window.addEventListener('keyup', function(e) {
    // Remove key
    delete keysPressed[e.keyCode.toString()];
}, false);

查看工作演示:

您在keys对象中将按下的任何键标记为true,因此当您停留在页面上的时间越长,keys对象将越大。请查看我编辑的答案。非常感谢,您为此付出了很多努力,我非常感谢。我将实现这一点,并运行一些基准测试,然后返回给您关于它的进展情况。但是看着它,我不得不说我知道你在哪里修剪了很多我应该在第二次看时遗漏的东西。好的,我测试了它,它在某种意义上起到了预期的作用。然而,我告诉你的关于钥匙不释放的小问题现在一直在发生。也就是说,在你按下Ctrl+Shift+S键后,它会出现,你输入命令,它会出现,然后消失,但只要你按下任何键,它就会弹出,不会松懈。好的,我的朋友,非常感谢您坚持这一点,我很感激我们可以共享的平台,虽然调试测试在我添加代码时显示其清除,但事实并非如此,因此可能我做错了什么,或者忘记发布清理,所以请看一下()它只插入了一个case语句(稍后我将修改为IF)正如您可以看到的,在启用调试之后,在所有操作完成之后,它们仍然是正确的,并且不会像没有添加代码时那样进行清理,那么我缺少了什么呢?谢谢,顺便说一句,凌晨2:30,我很快就要去上班了,所以太晚了。@GårÐåñ没问题,这就是我来这里的目的,对吗?我假设对话框会阻止keyup处理程序的运行。因此,您必须清理阵列。在第92行,我确实发布了一个清理。它现在可以正常工作了!非常感谢您,非常感谢您在调试过程中花费的时间和善意。所以我们有了正确的想法,有些东西没有释放,将数组设置回空是最简单的方法。我已经对它进行了测试,到目前为止,它似乎在所有意图和目的下都运行得非常完美。再次感谢你。
// Listen for keydown once instead for every hotkey
window.addEventListener('keydown', function(e) {
    // A button was pressed
    keysPressed[e.keyCode.toString()] = true;
    checkHotkeys();
}, false);

window.addEventListener('keyup', function(e) {
    // Remove key
    delete keysPressed[e.keyCode.toString()];
}, false);