JavaScript中with的某个具体事例

JavaScript中with的某个具体事例

Introduce

在初学JavaScript的时候,就在权威指南(犀牛书)中看到, with会导致原型链异常,导致词法分析器对js的优化效果降低,不建议使用,尤其是严格模式下,不允许with,所以从来就没有深入的学习过这个东西,直到今天卡住了。

details

先从简单的开始说起吧。 要说with,当然就要讲到scope chain,(范围链)。好像有点高大上啊。其实就是,你搜索一个标识符(比如 变量x。)它会让吧代码上下文的所有变量都弄成一个列表,然后你就遍历啊。。嗯,很粗糙的理解。在你自己范围域里找不到的变量,你就去父级节点找,父级节点找不到就去更祖先级别的找。举个例子

var x = 10;
 
(function foo() {
  var y = 20;
  (function bar() {
    var z = 30;
    // "x" and "y" are "free variables"
    // and are found in the next (after
    // bar's activation object) object
    // of the bar's scope chain
    console.log(x + y + z);
  })();
})();

你会发现在bar函数中,明明没有x和y,但是却可以正确的输出,这是因为当需要变量x和y的时候,在bar范围域里找不到,就会沿着原型链往上找,在foo函数中找到了y,在全局作用域中找到了x。如图所示

JavaScript中with的某个具体事例

是不是非常容易理解,但是啊, 关系到with的时候就有点头疼了。with’语句將某个对象添加的作用域链的顶部,如果在statement中有某个未使用命名空间的变量,跟作用域链中的某个属性同名,则这个变量将指向这个属性值。如果沒有同名的属性,则将拋出ReferenceError异常。

Object.prototype.x = 10;
 
var w = 20;
var y = 30;
 
// in SpiderMonkey global object
// i.e. variable object of the global
// context inherits from "Object.prototype",
// so we may refer "not defined global
// variable x", which is found in
// the prototype chain
 
console.log(x); // 10
 
(function foo() {
 
  // "foo" local variables
  var w = 40;
  var x = 100;
 
  // "x" is found in the
  // "Object.prototype", because
  // {z: 50} inherits from it
 
  with ({z: 50}) {
    console.log(w, x, y , z); // 40, 10, 30, 50
  }
 
  // after "with" object is removed
  // from the scope chain, "x" is
  // again found in the AO of "foo" context;
  // variable "w" is also local
  console.log(x, w); // 100, 40
 
  // and that's how we may refer
  // shadowed global "w" variable in
  // the browser host environment
  console.log(window.w); // 20
 
})();
  1. 在没有with的时候,object的原型上有个x,在全局中打印x自然是10

  2. 在函数中

    with({z: 50}) {
        console.log(w, x, y , z); // 40, 10, 30, 50
      }
    

    他首先搜索的不是作用域链,而是with插入的作用域链顶部,你可以发现{z: 50}这是一个对象,也就是说,他把一个对象插入到了作用域链顶部,搜索标识符自然是从顶部开始搜索的,所以这里的x指向的是object.prototype.x。而其余的w,y,z在对象的作用域链找不到,那么就沿着上下文找。

JavaScript中with的某个具体事例

其实说到底,他还是破坏了作用域链,吧一个东西强行插了进去,真感觉没必要。

writer&contact

{
  "name":"Jontyy" , 
  "email": " [email protected]"
}