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,所以解决方案只适用于此无关紧要。
希望有人知道如何实现这一点。
感谢您的帮助!
答案 0 :(得分:3)
您正尝试从根本上改变with
语句在JavaScript中的工作方式。这是不可能的,因为您无法保证解释器正在使用hasOwnProperty
(或您有权访问的任何其他构造)来检查您正在使用的对象上是否存在属性。
你加入了一个很好的传统,希望with
的工作方式不同,但事实并非如此。它的工作原理如何,最好避免使用。
答案 1 :(得分:2)
两件事:
请勿修改Object.prototype
。它被认为是不好的做法,并且会在任何地方引起意想不到的结果,而且如果它被修改,其他JS框架甚至都不会运行。
请不要使用with
。它是从javascript中弃用的,因为当存在与属性同名的局部变量时,无法确定它应该如何最佳运行。
如果需要迭代对象的属性,只需执行以下操作:
for (var i in myObject) {
if (myObject.hasOwnProperty(i)) {
// processing logic here
}
}
您提到的代码可以帮助您实现覆盖该设置逻辑。 https://developer.mozilla.org/en/JavaScript/Guide/Working_with_Objects包含有关使用 defineSetter 覆盖设置部分的信息,但强烈建议使用此功能,甚至不能使用JavaScript 1.8.1及更高版本。我会推荐另一种方法。
答案 2 :(得分:0)
要使变量不在全局范围内,可以使用匿名函数;由于JavaScript具有功能范围,因此函数中定义的所有变量都是本地范围的。但是,它要求你正确地声明变量,但我强烈建议在任何情况下。
(function () {
var a = 1;
alert("a is... " + a);
// do more stuff here
}());
alert(typeof a); // should be undefined
这并不专门处理您的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
答案 3 :(得分:0)
我找到了一种完全隔离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);
也许它对其他人有用;)