站长资讯网
最全最丰富的资讯网站

深入浅析With的使用

深入浅析With的使用

with用于扩展一个语句的作用域链,但一般情况下不建议使用with语句,因为它可能是引起混淆错误和兼容性问题的根源。在Vue源码中有使用with语句的功能点,因此在这里将简介其功能,以助于阅读框架源码。

性能的利与弊

with语句可以在不造成性能损失的情況下,减少变量的长度。其造成的附加计算量很少。使用'with'可以减少不必要的指针路径解析运算。但是在大部分情况下,即使不使用with,使用临时变量来保存指针或者使用call,也能达到同样的效果。

with语句使得程序在查找变量值时,都是先在指定的对象中查找。所以那些本来不是这个对象的属性的变量,查找起来将会很慢。

示例

let obj = {     a: 1,     b: 2,     c: 3 } with(obj){     console.log(a)    //1     console.log(b)    //2     console.log(c)    //3 }

这段代码中,with关联的obj对象,在with代码块中,每个变量都首选被认为是一个局部变量,如果这个局部变量与obj对象的某个属性同名,则这个局部变量会指向obj对象属性。

function fn(obj){     with(obj){         a = 1;     } } let obj1 = {     a: 2 } let obj2 = {     b: 3 }  fn(obj1); console.log(obj1.a)     //1  fn(obj2) console.log(obj2.a)     //undefined console.log(a)          //1,变量a被泄漏到全局作用域链上

上例中,obj1存在a属性,obj2没有a属性。fn(obj)接收一个obj形参,是一个对象引用,并执行了with(obj)。在with代码块的内部,对a实际上是一个引用,将1赋值给了a。

当传递obj2给with时,with所声明的作用域就是obj2,从这个作用域下开始对a进行查询。obj2的作用域、fn的作用域和全局作用域中都没有查找到标识符a,因此在非严格模式下会自动在全局作用域创建一个全局变量,而严格模式下则会抛出ReferenceError错误。

性能降低

如果在代码中使用了with,那么JS引擎在编译阶段只能简单地假设关于标识符的判断都将无效,因为编译器也不能知道传递给with的作用域对象到底是谁。因此JS引擎在编译阶段进行的性能优化都将无效。最糟糕的情况,那就是如果出现了with,所有的优化都将变得无意义。最简单的做法就是不做任何优化,那么运行起来一定会很慢,这将是无法避免的事实。

Vue中的with

Vue 在 compile 的时候,会把 template 生成对应的 render function,而这个 render function中又正好使用了with语句。按照上文来说,不建议使用with语句,为什么在Vue中又会使用到呢?

赞(0)
分享到: 更多 (0)