javascipt:with语句 延长作用域

前言

在《javascript高级程序设计》中看到延长作用域链小节,一脸茫然。既然好奇心已起,便一探究竟,查缺补漏。

知识点

作用域链

作用域链的作用是用于查找标识符,沿着作用域链向外冒泡查找,找到第一个就停下。

可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除。当执行流进入下列任何一个语句时,作用域链就会得到加长。

with语句

with语法

with (expression) {
    statement
}
复制代码
  • expression将给定的表达式添加到在评估语句时使用的作用域链上。表达式周围的括号是必需的。
  • statement要执行多个语句。

作用

  • with语句statement的语句的变量进行作用域链查找,首先查找当前的expression作用域,如果存在相同变量的定义,则这个变量将指向这个属性值。而with语句块中作用域的‘变量对象’是只读的,不能存储标识符,只能存储在其上一层,这就是延长作用域链

延长作用域链

内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。但有些语句:

  1. try-catch语句中的catch块;
  2. with语句;
let Person = {
  name: 'Bob'
}
function Run () {
  with (Person) {
    name = 'Tom'
    age = 12
  }
}
Run()
console.log(Person.name) // Tom
console.log(Person.age)  // undefined
console.log(age)         // 12
复制代码

Person对象中定义了name属性,而没有定义age属性,所以在with语句的作用下,name属性的值被修改,而age只能存储在作用域的上一层即全局,age的作用域相对于Person被延长了。

with的利与弊

  • with语句可以在不造成性能损失的情況下,减少变量的长度。其造成的附加计算量很少。使用with可以减少不必要的指针路径解析运算。需要注意的是,很多情況下,也可以不使用with语句,而是使用一个临时变量来保存指针,来达到同样的效果。
let Person = {
  name: '',
  age: '',
  sex: ''
}
// 不使用with
Person.name = 'Tom'
Person.age = 22
Person.sex = 'Girl'
// 使用with
with (Person) {
  name = 'Tom'
  age = 22
  sex = 'Girl'
}
// 临时变量
Person = {
  name: 'Tom',
  age: 22,
  sex: 'Girl'
}
复制代码
  • with语句使得程序在查找变量值时,都是先在指定的对象中查找。所以那些本来不是这个对象的属性的变量,查找起来将会很慢。导致性能下降。

对arr进行赋值,让下标值等于下标。

  • 不使用with:用时2.849853515625ms
function func() {
  console.time("func");
  var obj = {
    a: [1, 2, 3]
  };
  for(var i = 0; i < 100000; i++)
  {
    var v = obj.a[0];
  }
  console.timeEnd("func"); // func: 2.849853515625ms
}
func();
复制代码
  • 使用with:用时67.050048828125ms
function funcWith() {
    console.time("funcWith");
    var obj = {
        a: [1, 2, 3]
    };
    with(obj) {
        for(var i = 0; i < 100000; i++) {
            var v = a[0];
        }
    }
    console.timeEnd("funcWith"); // funcWith: 67.050048828125ms
}

funcWith();
复制代码

总结

终上所述,with语句做不到任何优化,还会导致性能下降。所以不推荐使用。而且在严格模式下不支持该语句。

参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值