词法作用域

2017-07-24  本文已影响0人  后发而先制

词法阶段

词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的,因此当词法分析器处理代码时会保持作用域不变(大部分情况下是这样的)。

嵌套作用域

function foo(a) {

var b = a * 2;

function bar(c) {

console.log( a, b, c );

}

bar( b * 3 );

}

foo( 2 ); // 2, 4, 12

标识符 foo() 作用域

标识符 foo(a){} 作用域

标识符 bar(c) 作用域

欺骗词法

eval () 函数可以接受一个字符串为参数,并将其中的内容视为好像在书写时就存在于程序中这个位置的代码。

setTimeout(..) 和 setInterval(..) 的第一个参数可以是字符串,字符串的内容可以被解释为一段动态生成的函数代码。

new Function(..) 函数的行为也很类似,最后一个参数可以接受代码字符串,并将其转化为动态生成的函数(前面的参数是这个新生成的函数的形参)。

function foo(str, a) {

eval( str ); // 欺骗!

console.log( a, b );

}

var b = 2;

foo( "var b = 3;", 1 ); // 1, 3

with

with 通常被当作重复引用同一个对象中的多个属性的快捷方式,可以不需要重复引用对象本身。

with坑

function foo(obj) {

with (obj) {

a = 2;

}

}

var o2 = {

b: 3

};

foo( o2 );

console.log( o2.a ); // undefined

console.log( a ); // 2——不好,a 被泄漏到全局作用域上了!

o2中没有a 放入with中后 无法赋值  a=2就会变为全局变量 通过LHS来查找滴话。

性能

eval(..) 和 with 会在运行时修改或创建新的作用域,以此来欺骗其他在书写时定义的词法作用域。

JavaScript 引擎会在编译阶段进行数项的性能优化。其中有些优化依赖于能够根据代码的词法进行静态分析,并预先确定所有变量和函数的定义位置,才能在执行过程中快速找到标识符。

最悲观的情况是如果出现了 eval(..) 或 with,所有的优化可能都是无意义的,因此最简单的做法就是完全不做任何优化。

上一篇 下一篇

猜你喜欢

热点阅读