JavaScript中的with

来源:互联网 发布:数据分析员职业规划 编辑:程序博客网 时间:2024/05/21 04:43

最近读了《JavaScript高级程序设计第三版》,在此对其中第四章中提到的的with语句进行一个总结记录。

1.书中写到“有些语句可以在作用域链的前端临时增加一个变量对象,该对象会在代码执行后被移除”,在这里主要说明with语句。首先看下面的例子。

function removeAfterExe(){    var obj = {a:1};    var a = 10;    with(obj){        console.log(a);    }    console.log(a);}
        调用函数输出结果:1,10。

        解释:在执行with语句后,将with语句中的obj对象添加到了作用域链的最前端,所以在第一个console.log(a)时,查找的是obj中的a,所以输出的结果是1。当代码执行完后,with语句中的对象会被移除。所以此时作用域链上最前端的是removeAfterExe这个函数的活动对象,所以在再次查找a的值的时候,就是查找到定义的var a = 10这里的a的值。所以当with执行完毕后,对象被消除了。

2. 有关在with语句里声明变量。在书中有一个例子如下:

function buildUrl(){    var qs = ‘?debug=true’;    with(location){        var url = href+qs;    }    return url}

        在读到这里的时候,产生了一个疑问,为什么在with语句中定义的url变量在with语句的外部也可以访问到呢?

        其实这一点在书中接下来的部分给出了一个解释。“使用var声明的变量会自动被添加到最近的环境中。在函数内部,最接近的环境就是函数的局部环境;在with语句中最接近的环境是函数环境”读到这里明白了在上面例子中with语句中声明的变量url其实是被添加到了函数的环境中。而不是这个对象中。(其实想想在JavaScript中没有块级作用域的概念,所以这里自然相当于定义在了外面的函数作用域中)。
3.用with改变对象的属性

下面的例子来源于《你不知道的JavaScript上》

function foo(obj){    with(obj){        a=2;    }}var obj1 = {a:3};var obj2 = {b:3};foo(obj1);console.log(obj1.a);   //输出2foo(obj2);console.log(obj2.a);   //输出undefinedconsole.log(a);       //输出2
        当给foo传递obj1时,因为obj1有a属性,所以在with添加的临时变量对象中有a变量,所以foo函数直接改变了该变量。而当给foo传递Obj2时,因为在with语句创建的变量对象中找不到a变量,所以就沿着作用域链向上寻找,在这里就找到了全局作用域,并给全局作用域添加了一个属性a,并赋值为2。所以在接下来的输出中obj2.a的值为undefined,而全局中的a为2。这个例子也提醒我们要注意变量泄漏到全局上。

        其实还是和上面类似的道理,with语句可以将一个对象处理为一个新的变量对象,但是在这里新的变量对象中的操作不会被限制在这个块的作用域中。

4.总结

(1)with语句接收的对象会添加到作用域链的前端并在代码执行完之后移除。

(2)在with语句中声明的变量会放在with所在的环境中。

(3)在使用with操作对象的属性时,要注意不要泄漏在全局上。





0 0
原创粉丝点击