标识符
标识符就是变量、函数、属性或者函数参数的名称,一般使用 小驼峰; 关键字不能作为标识符
var variableName = "xxx";
function funName(argName) {
xxx
};
var 声明变量
// 不初始化的情况下,变量的值时 undefined
var variableName;
// 定义变量并赋值
var str = "abc";
// 定义多个变量, 每个变量使用逗号隔开
var v1 = 1, v2 = 2, v3 = 3;
var 声明作用域
var 操作服定义的变狼会成为包含它的函数的局部变量
function fn() {
// 局部变量, 在函数退出时被销毁
var msg = "hi";
}
fn();
console.log(message); // 出错
如果省略 var 关键字,可能会造成创建一个全局变量;
注意: 在严格模式下 使用 "use strict"; 如果给未声明的变量赋值,会导致 ReferenceError 异常
function fn() {
// 当 fn 被调用的时候会被创建一个全局变量 msg
msg = "hi";
}
fn();
// “hi”
console.log(msg);
var 声明提升
变量提升,就是把所有变量声明都放到函数作用域顶部,此外反复使用 var 声明同一个变量也没有问题(最终会覆盖的)
function foo() {
console.log(age); // undefined
var age = 26;
}
foo();
// 如上的代码相当于这样
function foo() {
// 这就是变量提升,就是把所有变量都
var age;
console.log(age); // undefined
age = 26;
}
foo();
let 声明
let 也可以声明变量,let 声明的范围是块作用域,而 var 声明的范围是函数作用域。
var name;
// var 可以允许重复声明
var name;
let age;
// let 重复声明将会报错、let 不允许同一个块作用域中出现冗余声明
let age;
对于声明冗余报错不会因为 混用 let 和 var 而受影响
var name;
let name; // SyntaxError
暂存性死区
const、let 声明的变量不会在作用域中被提升; js 引擎不允许以在let 声明之前的任何方式来引用 其变量。
// 因为 const、let 声明的变量不会被提升, 所以会出现 ReferenceError
console.log(num);
let age = 26;
全局变量
let 声明的变量不会挂载到 window 对象的属性上,var 声明的变量则会,不过 let 声明仍然会在全局作用域中发生,相应变量会在 页面的生命周期内存续。
var name = "varStr";
console.log(window.name); // varStr
let age = 26;
console.log(window.age); // undefined;
let 不能依赖条件声明模式,如尝试检查 一个变量是否为 undefined,如果 为 undefined 则使用 let 声明
if(typeof name === "undefined") {
let name = "kj"; // 这牙膏 name 就被限制在了 if {} 块中
}
for 循环中的 let 声明
在 let 出现之前,for 循环 var 定义的迭代变量会被渗透到循环体外部
for(var i = 0; i < 5; i++) {
// 循环逻辑
}
console.log(i); // 5, 糟糕 i 被渗透到了 for 循环体外部
以为 let 声明的是 块级作用域,因此声明的变量只会绑定到 let 出现在 {} 内部
for (let i = 0; i < 5; i++) {
// xxxx
}
console.log(i); // ReferenceError, 太棒了, i 没有渗透出来
const 声明
const 的行为和 let 基本相同,区别在于 const 声明变量时必须同时使用初始化变量,初始化后不能修改其变量的引用。
const str = "hi";
str = "hello"; // TypeError
const 声明的限制只适用于它指向的变量的引用,换句话说,如果 const 变量引用的是一个对象,那么修改这个对象内部的属性并不违反 const 的限制
const person = {
age: 23,
};
person.age = "33"; // 没有问题
person = "hello"; // 错误,因为 这个改变了变量的引用
const 的循环
如果在 for 循环中 迭代变量是变化的,则不能使用 const 来声明,如果迭代变量是不变化的则可以使用 const 来定义
// error
for (const i = 0; i < 10; i++) {} // TypeError 给常量 i 赋值了
// ok
for (const key in { a:1,b:2 }) {
console.log(key);
}
声明风格以及最佳实践
-
不使用 var, var 的维护成本高,不小心就定义了全局变量、变量声明提升等问题
-
const 优先、let 次之
const 声明可以让那个浏览器运行时强制保持变量不变,也可以静态代码分析工具提前发现不合法的赋值操作,只在提前知道未来会有修改时,再使用 let。