Published on

语言基础

Authors
  • avatar
    Name
    李丹秋
    Twitter

语句

let sum = a + b // 没有分号也有效,但不推荐
let diff = a - b; // 加分号有效,推荐

即使语句末尾的分号不是必需的,也应该加上。记着加分号有助于防止省略造成的问题,比如可以 避免输入内容不完整。此外,加分号也便于开发者通过删除空行来压缩代码(如果没有结尾的分号,只删除空行,则会导致语法错误)。加分号也有助于在某些情况下提升性能,因为解析器会尝试在合适的位置补上分号以纠正语法错误。

// 有效,但容易导致错误,应该避免
if (test) 
 console.log(test); 
// 推荐
if (test) { 
 console.log(test); 
} 

在控制语句中使用代码块可以让内容更清晰,在需要修改代码时也可以减少出错的可能性。

变量

var关键字

1. var 声明作用域

使用 var 操作符定义的变量会成为包含它的函数的局部变量。比如,使用 var在一个函数内部定义一个变量,就意味着该变量将在函数退出时被销毁

function test() { 
 var message = "hi"; // 局部变量
} 
test(); 
console.log(message); // 出错!

var也允许重复声明相同变量

var声明提升

这就是所谓的“提升”(hoist),也就是把所有变量声明都拉到函数作用域的顶部。

function foo() { 
 console.log(age); 
 var age = 26; 
} 
foo(); // undefined

等价于
function foo() { 
 var age; 
 console.log(age); 
 age = 26; 
} 
foo(); // undefined

let关键子

let声明的范围是块作用域,var是函数作用域

if (true) { 
 var name = 'Matt'; 
 console.log(name); // Matt 
} 
console.log(name); // Matt

if (true) { 
 let age = 26; 
 console.log(age); // 26 
} 
console.log(age); // ReferenceError: age 没有定义

在这里,age 变量之所以不能在 if 块外部被引用,是因为它的作用域仅限于该块内部。块作用域 是函数作用域的子集,因此适用于 var 的作用域限制同样也适用于 let。并且let也不能在同一个块级作用域中重复声明

  1. let不会变量提升,在声明之前访问会报错
  2. let全局声明的变量不会挂在到window上

for循环中的let声明

for (var i = 0; i < 5; ++i) { 
 setTimeout(() => console.log(i), 0) 
} 
// 你可能以为会输出 0、1、2、3、4 
// 实际上会输出 5、5、5、5、5

之所以会这样,是因为在退出循环时,迭代变量保存的是导致循环退出的值:5。在之后执行超时逻辑时,所有的 i 都是同一个变量,因而输出的都是同一个最终值。 而在使用 let 声明迭代变量时,JavaScript 引擎在后台会为每个迭代循环声明一个新的迭代变量。每个 setTimeout 引用的都是不同的变量实例,所以 console.log 输出的是我们期望的值,也就是循环执行过程中每个迭代变量的值。

for (let i = 0; i < 5; ++i) { 
 setTimeout(() => console.log(i), 0) 
} 
// 会输出 0、1、2、3、4

const声明

const行为和let相似,唯一区别是声明的同时必须初始化变量 const 声明的限制只适用于它指向的变量的引用。换句话说,如果 const 变量引用的是一个对象,那么修改这个对象内部的属性并不违反 const 的限制。