JavaScript中 with的用法

刚看到这个东西的时候我是懵的,with是什么玩意,我咋从来没听过,抱着学习的态度,于是开干学习with。查阅了相关资料发现,不推荐使用with关键字,嘿嘿嘿,是不是可以不要学了,no,学无止境,有的底层代码会用到这个,或者面试官可能会问到。所以不管怎么说,还是了解一下的好。

with语句 扩展一个语句的作用域链。
语法:

        with (expression) {
                statement
        }

expression:将给定的表达式添加到在评估语句时使用的作用域链上。表达式周围的括号是必需的。
statement:任何语句。要执行多个语句,请使用一个块语句 ({ ... })对这些语句进行分组

基本用法 

var obj = {
    a: 1,
    b: 2,
    c: 3
}
with (obj) {
    a = 10
    b = 20
    c = 30
}
console.log(obj)    // {a: 10, b: 20, c: 30}

弊端

1、代码不易阅读,难以在作用域链上查找某个变量,难以决定应该在哪个对象上来取值

function fn(a,b) {
    with(b) {
        console.log(a);
    }
}

打印的这个a可能是形参b对象里的a变量,也可能是形参a的值,所以难以确定是哪个对象上来取值

2、数据泄露

function fn(obj) {
    with(obj) {
        a = 66
    }
}
var obj1 = {
    a:1
}
var obj2 = {
    b:2
}

fn(obj1)
console.log(obj1.a)   // 66

fn(obj2) 
console.log(obj2.a)   // undefined
console.log(a)  // 66   此时a已经泄露到全局变量里去了

首先创建obj1和obj2对象,前者有a属性,后者没有,我们先把obj1传到fn函数中,这个时候with去obj1找a属性,找到后修改a为66,这个时候obj1的a就被修改掉了,这是没问题的。但是我们把obj2传给fn函数,with会去obj2对象中去查找a属性,结果发现没有找到,那么with就会去全局作用域找,如果也没有找到,就会在全局作用域创建一个a变量,并且赋值为66。这就是with泄漏数据的全过程

3、性能下降

function fn1() {
    console.time('fn1')
    let obj = {
        arr: []
    }
    for(let i=0;i<100000;i++) {
        obj.arr[i] = i*2+3
    }
    console.timeEnd('fn1')
}
fn1()

function fn2() {
    console.time('fn2')
    let obj = {
        arr: []
    }
    with(obj) {
        for(let i=0;i<100000;i++) {
            arr[i] = i*2+3
        }
    }
    console.timeEnd('fn2')
}
fn2()

         可以看到with用的时间是普通代码逻辑的n倍,为啥with会这么慢呢?原因是 JavaScript 引擎会在编译阶段进行数项的性能优化。其中有些优化依赖于能够根据代码的词法进行静态分析,并预先确定所有变量和函数的定义位置,才能在执行过程中快速找到标识符。
        但如果引擎在代码中发现了 with,它只能简单地假设关于标识符位置的判断都是无效的,因为无法知道传递给 with 用来创建新词法作用域的对象的内容到底是什么。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值