V8引擎与作用域:JS变量的「幸福家园」指南

56 阅读4分钟

各位前端小伙伴们,今天咱们来唠唠V8引擎和作用域这对「CP」——一个是JS代码的「超级翻译官」,一个是变量的「幸福家园管理员」。想知道你的变量都住在哪?为什么有时候找得到它,有时候又找不到?坐稳了,咱们发车啦!

V8引擎:JS代码的「超级翻译官」

V8引擎就像一个庞大的函数工厂,它把咱们写的JS代码翻译成机器能懂的语言。它的工作流程分三步走:

  1. 分词/词法分析:把代码切成一个个「词块」,比如vara=1这些
  2. 解析/语法分析:把词块组成「句子」,生成抽象语法树(AST)
  3. 代码生成:把AST转换成机器码,让电脑执行

这过程就像你点外卖:分词是拆快递,解析是看菜单,代码生成就是厨师做饭~

作用域:变量的「幸福小区」

作用域其实就是变量的「家」,它决定了变量住在哪,以及你能不能找到它。JS里有两种主要的「小区」:

  • 全局作用域:相当于「市中心大社区」,谁都能访问
  • 函数作用域:相当于「高档小区」,只有小区里的人(函数内部)才能进

作用域查找规则:「从内到外」的串门法则

变量查找就像串亲戚:先在自己家(当前作用域)找,找不到就去爸妈家(外层作用域),再找不到就去爷爷奶奶家(更外层作用域),直到找到或者到全局作用域为止。

var a = 10;
function foo(b) {
  function bar() {
    console.log(a + b);  // 先在bar里找a,找不到去foo,还找不到去全局,最终找到a=10
  }
  bar();
}
foo(2);  // 输出12

注意啦,这个查找只能「从内到外」,不能「从外到内」!就像你不能随便闯进邻居家找东西~

欺骗词法:作用域里的「潜入者」

词法作用域是写代码时就确定的,但有些「坏家伙」能欺骗它:

1. with:变量的「蹭住者」

with本来想帮我们简化对象属性访问,结果却可能让变量「蹭住」到全局作用域:

var o2 = { b: 2 };
function foo(obj) {
  with(obj) {
    a = 2;  // obj里没有a,a就变成全局变量了
  }
}
foo(o2);
console.log(o2);  // { b: 2 }
console.log(a);   // 2,变量泄露到全局了!

这就像你带朋友回家,结果他赖在你家不走了~

2. eval:作用域的「偷渡者」

eval能把字符串当代码执行,还能偷偷修改当前作用域:

function foo(str) {
  eval(str);  // 执行"var a = 10",在foo作用域里创建了a
  console.log(a, b);  // 10 2
}
var b = 2;
foo('var a = 10');

这就像有人偷渡进小区,还在你家客厅摆了张沙发~

letconst vs var:变量的「身份升级」

ES6的letconst给变量带来了「身份升级」,和var相比有这些不同:

  1. 没有声明提升var像个「提前占座」的,letconst则是「准时赴约」
// console.log(a);  // 用var的话会输出undefined
// var a = 2;

// console.log(a);  // 用let的话会报错:Cannot access 'a' before initialization
// let a = 2;
  1. 不能重复声明var可以「一房多卖」,letconst则「一房一证」

  2. 不污染全局对象var声明的全局变量会挂载到window上,letconst不会

  3. const声明的变量不能修改const就像「上了锁的保险柜」,里面的内容不能换

const a = 1;
a = 2;  // 报错:Assignment to constant variable.

块级作用域:变量的「私人空间」

letconst配合{}能创建块级作用域,就像给变量一个「私人空间」:

let a = 1;
if (true) {
  let a = 2;  // 这个a只在if块里有效
  console.log(a);  // 2
}
console.log(a);  // 1,外面的a不受影响

而且块级作用域里还有「暂时性死区」:在变量声明前访问它,会直接报错,就像你不能提前住进还没建好的房子~

总结:作用域的「生存法则」

  1. 变量有自己的「家」(作用域),别乱闯
  2. 找变量要「从内到外」,别想「从外到内」
  3. 少用witheval,它们是作用域的「破坏者」
  4. 优先用letconst,它们是变量的「合法身份」
  5. 块级作用域是变量的「私人空间」,请尊重隐私

希望这篇文章能帮你理解V8引擎和作用域的关系,以及JS变量的「生存法则」。下次写代码时,想想你的变量住在哪,能不能被找到,这样就能避免很多bug啦!

如果你有更多关于作用域的问题,欢迎在评论区留言讨论~