2011-07-15 21 views
2

但是我想要做的是能夠傳遞JavaScript中的任意代碼,這些代碼將在特定的範圍內執行,類似於您如何在Ruby中生成塊。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將無法​​正常工作。

這裏的主要用例是對複雜代碼進行實時調試。

編輯:I started a GitHub project around this question

+0

這個問題並不十分清楚。你當然可以「說」這些陳述。當你「說」他們時,你期望**會發生什麼?在那段代碼中,「自我」是什麼意思?這真的不是一個JavaScript概念。你是不是指「這個」? – Pointy

+0

我試圖在那裏更清楚些。希望它更容易理解。 – kristopolous

+0

+1是一個很好的問題:) –

回答

1

這應該工作:

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) }); 
+0

我喜歡你的解決方案,我也提供了一個稍微比較ruby-ish的答案。好的問題無論哪種方式 –

+0

並非所有的瀏覽器反編譯功能,主要是移動瀏覽器,但也有一些簡約的桌面功能 –

+0

任何具體的例子? – kristopolous

0

抱歉,這是不可能的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,讓你正在嘗試做的可能,但它不是廣泛可能的)

+0

你是說'函數f(){ var a = 1; eval('alert(a)'); } f();'不會工作在說,FF 5? – kristopolous

+0

不,FF的舊版本的代碼允許您從函數f以外獲取'a'變量。 –

+0

@cvolves什麼?你怎麼可能得到一個閉包中的局部變量,而不是從詞法範圍到閉包的代碼? – Pointy

0

首先,大問題!我花了至少一個小時試圖想出一個相對簡單的實現方法!這是我如何解決這個問題:

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,等等),它更進一步。

我希望這個答案很有用,你的問題很好!

+0

還不錯。我想你可以用這樣的解決方案來真正接近knuths的功能。 – kristopolous

+0

稍作編輯使得代碼更具可讀性(也不需要反射功能) –