很多人可能不知道这个东西,也许你知道with关键字的作用在于改变作用域但会说它无用,但不管你是否知道或者支持with无用论,如果哪天有人拿它作为一道面试题,你事先没踩过这个坑或许难倒了你,下面结合实例理解下with。
with的基本用法
1 2 3 4 5 6 7 8
| var obj = {
a: 1,
b: 2,
c: 3
};
// 如果想获取obj中的字段你恐怕会这样
console.log(obj.a,obj.b,obj.c) |
使用with
1 2 3
| with(obj){
console.log(a,b,c)
} |
面试题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| var a = null;
function foo(obj) {
with (obj) {
a = 2;
}
}
var o1 = {
a: 3
};
var o2 = {
b: 3
}
foo(o1);
console.log(o1.a);
foo(o2);
console.log(o2.a);
console.log(a);
// 答案:2 nudefined 2 |
分析理解
- 首先,第一个o1传进去的是{a:3},with中obj获取到了{a:3},并且其中a再次改写成2,这时候我们输出o1.a就是2,因为对象改变是引用地址改变
- 同样道理我们再传入o2,但o2传进去的是{b:3},with接收到了这个参数对象,重新改写a,发现这个对象没得a这个字段,然后你还要打印o2.a,结果就是undefined
- 在这一步时候我们虽然没有改写o2下的a成功,但执行a = 2,那既然传过来的对象没有a字段,那作为直接赋值变量就给到了全局a,结果第三步直接打印a找到了2
小结
浓缩点说:实例中原本想改变的是传进来的obj,如果obj有对应的a,那就把这个a给改变 = 2,如果发现obj中没有,那它也不会自动往obj上添加,但它会直接给全局增加一个a = 2,这就是with引起的变量泄露问题,想想上面我们一开始给全局定义了一个a初始化为null,但在后期使用with过程中某次修改失败,导致改变了全局的a,想想是不是有些可怕,这恐怕就是很多人支持with无用论的由来。
「梦想一旦被付诸行动,就会变得神圣,如果觉得我的文章对您有用,请帮助本站成长」
共 0 条评论关于"理解js中的作用域链增强with上下文以及变量泄露问题"
最新评论