[英]Changing the behavior of JavaScript's with statement to prevent assignment from modifying the global object
JavaScript中的with
語句首先檢查對象的請求屬性是否存在,然后再決定是設置給定對象的屬性還是設置全局對象的屬性。
例:
var x = {a:5};
with(x){
a = 6; //x.a is now 6
b = 7; //window.b is now 7, x.b still does not exist
}
我想更改with
的行為,以便在檢查我正在使用的對象上是否存在屬性時,始終將其視為存在,以防止塊內的分配意外修改全局對象。
是否可以通過重載檢查對象屬性是否存在的函數來實現? 例如這樣的事情:
Object.prototype.__hasOwnProperty__ = function(p){
return true;
}
var x = {a:5};
with(x){
a = 6; //x.a is now 6
b = 7; //x.b should now be 7
}
我的代碼在node.js和V8上運行,因此,解決方案是否僅與此兼容。
希望有人對我如何實現這一想法有所了解。
謝謝你的幫助!
您正在嘗試從根本上改變with
語句在JavaScript中的工作方式。 這是不可能的,因為您無法保證解釋器正在使用hasOwnProperty
(或您有權訪問的任何其他構造)來檢查正在使用的對象上是否存在屬性。
您正在加入一個很好的傳統,希望它能with
不同的方式工作,但事實並非如此。 它可以正常工作,最好避免。
兩件事情:
不要修改Object.prototype
。 這被認為是不好的做法,並且會在任何地方導致意外的結果,而且如果對其進行修改,其他JS框架甚至都無法運行。
請不要with
使用。 它已從javascript中棄用,因為當存在與屬性同名的局部變量時,無法確定如何最好地發揮作用。
如果您需要遍歷對象的屬性,請執行以下操作:
for (var i in myObject) {
if (myObject.hasOwnProperty(i)) {
// processing logic here
}
}
您提到的代碼將幫助您實現覆蓋該設置邏輯。 https://developer.mozilla.org/zh-CN/JavaScript/Guide/Working_with_Objects提供了有關使用defineSetter覆蓋設置部分的信息,但強烈建議這樣做,即使在JavaScript 1.8.1及更高版本中也是如此。 我建議另一種方法。
為了使變量不在全局范圍之內,可以使用匿名函數。 由於JavaScript具有功能范圍,因此在函數中定義的所有變量在作用域內都是局部的。 不過,它要求您正確聲明變量,但是在任何情況下,我都強烈建議您這樣做。
(function () {
var a = 1;
alert("a is... " + a);
// do more stuff here
}());
alert(typeof a); // should be undefined
示例: http : //jsfiddle.net/AWDzV/
這並不專門處理您的with
語句,但它可能是完成所需內容的最佳方法。 然后,要模擬with
語句的行為,您要做的就是使用一個變量:
(function () {
var a = 1,
some_very_long_object_name = {a: 1, b: 2, c: 3},
obj = some_very_long_object_name;
obj.a = 2;
obj.b = 3;
obj.c = 4;
}());
alert(typeof a); // should be undefined
這不是世界上最好的代碼,但是它確實證明了使用短的變量名來替換長的對象名是完美的。 總而言之,我認為這可能是最好的解決方案。
當然,任何未正確聲明的變量都將“泄漏”到全局范圍內:
(function () {
a = 1; // notice the lack of "var" keyword
}());
alert(a); // should be 1
示例: http : //jsfiddle.net/AWDzV/1/
但是您可以使用JSLint幫助捕獲該特定錯誤。 在上面的代碼上運行它會產生以下錯誤消息:
錯誤:隱含全局:2,4,警報4
我找到了一種完全隔離skript的方法。 這不是好的代碼,但可以。
X = 5;
function ExecuteIsolated(code){
var vars = [];
(function(){
for(var v in window){
vars.push(v);
}
eval("var "+vars.join(",")+";");
//Totally isolated code here:
eval(code);
//End of totally isolated code
})();
var i = 0;
for(var v in window){
if(vars[i++] != v){
delete window[v];
i--;
}
}
}
ExecuteIsolated("X = 8");
console.log(X);
也許對其他人有用;)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.