JavaScript中的Ruby样式块

Ruby style blocks in JavaScript?

本文关键字:样式 Ruby 中的 JavaScript      更新时间:2023-09-26

但是我想做的是有能力在JavaScript中传递任意代码,这些代码将在特定范围内执行,类似于如何在Ruby中生成块。

举个例子:

function injectHook() {
    return function(block) {
        block();
    }
}
(function() {
    var a = 1;
    self.inject = injectHook();
})();
inject(function() {
    a++;
});
inject(function() {
    console.log(a);
});

上面的尝试将不起作用,因为injectHook在不同的作用域定义,并且无法访问a

这里的主要用例是用于实时调试复杂的代码。

编辑:我围绕这个问题开始了一个GitHub项目

首先,好问题!我花了至少一个小时试图想出一个相对简单的方法来实现它!我是这样处理这个问题的:

Object.prototype.yield = function() {
    return "try { (" + this + ")() } catch (e) { console.log('**Context error** ' + e) }";
}
// first yielding block
var y1 = (Object(function() { 
    console.log('in y1, but still in the right context...');
    a++;
})).yield();
// second yielding block
var y2 = (Object(function() { 
    console.log('in y2, but still in the right context...');
    a = a + 5;
})).yield();
// voila
(function() {
    var a = 1;
    eval(y1);
    eval(y2);
    a--;
    eval(y2);
    console.log(a); // a == 11 now as expected
})();
// another block without an `a`
(function() {
    var b = 1;
    eval(y1); // gracefully fails
})();

从它可以在多个位置产生的意义上来说,这倾向于更像红宝石。不仅如此,它还更进一步,能够产生特定的代码块(y1, y2, y3等)

我希望这个答案是有用的,你的问题是伟大的!

对不起,这在JavaScript中是不可能的。代码只能访问定义它的作用域,不能访问作用域外的局部变量。

做类似事情的唯一方法是在对象上:

function injectHook( obj ){
    return function( block ){
        block.apply( obj );
    }
}
function someClass(){
    this.a = 1;
    this.inject = injectHook( this );
}
var instance = new someClass;
instance.inject(function(){
    this.a++;
});

(注意:旧版本的Firefox在eval中有一个"bug",使您尝试做的事情成为可能,但这不是普遍可能的。)

应该可以:

function Inject(scope) {
    return 'Inject.' + scope + ' = ' + function(block) {
        return eval('(' + block + ')()');
    };
}
(function(){
    var a = 1;
    eval(Inject('ref'));
})();
Inject.ref(function(){ a++ });
Inject.ref(function(){ console.log('hello world', a) });