当我们在使用JS进行开发时,可能会遇到使用with关键字的代码。with可以被用来打破常规的JS作用域规则,允许我们更方便地访问某些对象中的属性和方法。然而,with关键字在使用上很容易出错,也容易导致代码不易阅读和维护。因此,在使用with语句时,需要谨慎使用,遵循一些约定和最佳实践,下面将详细讲解“理解JavaScript中的with关键字”,帮助读者更好地理解with语句。
什么是With语句
在JavaScript中,with语句是一种让你在多次访问同一个对象的时候,可以省略对象名进行访问的方式。
一般语法如下:
with (expression) statement
例如:
var obj = {num:42};
with(obj) {
console.log(num); // 42
}
With语句的用法
JavaScript的with语句可以让你在多次访问同一个对象的时候,可以省略对象名进行访问的方式,这无疑带来了一定的便利。 然而,使用with语句不仅会降低代码的可读性、可调试性,而且还可能造成性能上的问题,并且有安全漏洞,因此在实际应用中,我们应该尽量避免使用它。
with语句当中expression所返回的对象,会被绑定到with语句体内的一个新变量当中。我们随后就可以通过省略对象名,直接调用这个对象内的所有方法和属性了。
例如:
var obj = {num: 42};
with (obj){
console.log(num); // 42
}
通过上面的代码,我们可以看到,with语句中的obj对象被绑定到了num变量上,并且可以直接访问到num属性。
With语句的缺点
虽然with语句可能使编码更容易,但它也有很多缺点:
-
可读性差:代码在使用 with语句时变得混乱。代码没有清晰地表达出操作的对象,尤其是钩子代码和回调函数,会被嵌入到 with 上下文中,使其难以确定。
-
性能问题:with 语句会使 JavaScript 引擎难以优化代码,从而导致程序运行缓慢。如果应用程序需要处理许多对象,那么大量使用 with 语句会增加资源消耗的可能性。
-
安全问题:with语句存在安全漏洞,使用with语句,就意味着你信任数值传递到with语句中的属性名称,如果传递了一个恶意对象而不是可预料的对象,攻击者可能可以定义有害行为,并可能比使用显式对象引用错误更难发现和诊断这些行为。
因此,我们不建议使用 with 语句,相反请使用显式对象引用,例如:
var obj = {num: 42};
console.log(obj.num); // 42
不要使用 With 语句的情况。
一般来说,我们不建议使用 with 语句,下面是使用 with 的情况列表:
- 速度
如果您的 JavaScript 程序需要处理许多对象,则大量使用 with 语句会增加资源消耗的可能性,因此会导致程序运行缓慢。
- 可读性
代码在使用 with 语句时变得混乱。如果您使用回调,将难以判断回调的目标对象。
- 安全
如果编写不可预测的代码,with 语句会导致 JavaScript 漏洞。
为了弥补 with 语句 带来的缺点,可以使用立即执行函数(Immediately Invoked Function Expressions, IIFEs),也就是JavaScript中的自执行函数:
var obj = {num: 42};
(function(obj){
console.log(obj.num); // 42
})(obj);
在以上代码中,我们使用了自执行函数并将obj作为它的参数传递进去,这样就避免了with语句的缺点。
示例1:
var book = {
"name": "《JavaScript高级程序设计》",
"author": "尼古拉斯·C.萨卡斯",
"publishTime": "2013年3月6日",
"price": 89.00
};
with(book) {
console.log("书名 = ", name);
console.log("作者 = " , author);
console.log("发布时间 = ",publishTime);
console.log("价格 = ", price);
}
代码执行效果如下:
书名 = 《JavaScript高级程序设计》
作者 = 尼古拉斯·C.萨卡斯
发布时间 = 2013年3月6日
价格 = 89
示例2:
var x = 1, y = 2;
with({x: 3, y: 4}){
console.log(x + y); // 7
console.log(x - y); // -1
}
代码执行效果如下:
7
-1
因为我们在with语句中传入了一个新的对象,这个新对象属性值和原先的变量名是一样的,但是结果不一样,从这里我们可以看出,代码中的x和y示例,是有时候不一定会指向全局变量。