一、语法
1、区分大小写
ECMAScript中一切都区分大小写。无论变量、函数名还是操作符都区分大小写。
2、标识符
标识符就是变量、函数、属性或函数参数的名称
规则
1、第一个字符必须是一个字母、下划线( _ )或者美元符号( $ )
2、其余字符可以是字母、下划线、美元符号、数字。
3、关键字、保留字、true、false和null不能作为标识符。
3、注释
1、单行注释
//单行注释
2、多行注释
/* 多行
注释*/
4、严格模式
ECMAScript 5 增加了严格模式。使用严格模式要在脚本开头增加一行:
"use strict"
也可以在函数体开头写"use strict",单独指定一个函数在严格模式下执行。
function do(){
"use strict"
//函数体
}
5、语句
ECMAScript 中的语句以分号结尾,加分号有助于防止省略造成的问题,也有助于某些情况下提升性能
// 有效,但容易导致错误,应该避免
if (test)
console.log(test);
// 推荐
if (test) {
console.log(test);
}
二 、关键字与保留字
ECMA-262描述了一组保留字,有特殊用途。
ECMA-262第六版规定关键字如下:
break do in typeOf
case else instanceof var
catch export new void
class extends return while
const finally super with
continue for swich yieId
debugger function this
defalue if throw
delete import try
将来保留词汇
//始终保留
enum
//严格模式下保留
implement package public
interface protected static
let private
//模块代码中保留
await
三、变量
ECMAScript变量是松散的类型的,意思是变量可以用于保存任何数据类型的数据。
每个变量只不过是一个用于保存任意值的命名占位符。可以用var、let、const声明变量。
var在ECMAScript的所有版本都可以使用,const和let只能在ECMAScript 6以及更晚版本使用。
1 var 关键字
var操作符后跟变量名。 var mess
(1)、声明作用域
使用var定义变量会成为包含它的函数的局部变量。
在定义变量时不使用var会变成全局变量(不推荐)
定义多个变量时可以用逗号分隔每个变量。
//在一个函数内部定义变量将在函数退出时被销毁
function test(){
var mess = 'hello world';
};
test();
console.log(mess); //出错
//在函数内定义变量时省略var可以创建全局变量
function test(){
mess = 'hello world';
};
test();
console.log(mess); //hello world
//定义多个变量
var mess = 'hello',age = 10,sex = '男' //严格模式下不能定义eval和arguments为变量名的变量,会导致语法错误
(2)、var声明提升
“提升”是指把所有变量声明都拉到所在作用域的顶部。var声明的变量会自动提升到作用域顶部。
可以反复声明同一个变量。(会以最后一次为准)
全局声明时会自动成为window对象的属性
//变量提升
function foo (){
console.log(age);
var age = 22;
}
foo(); //undefined
//之所以不会报错,时因为ECMAScript运行时把它等价于下面代码
function foo (){
var age;
console.log(age);
age = 22;
}
foo(); //undefined
//反复声明同一变量
function foo (){
var age=12;
var age=42;
var age=32;
var age=22;
console.log(age);
}
foo(); //22
//全局声明会成为window对象的属性
var age =10
console.log(window.age) //10
2 let声明
let和var作用差不多,最明显的区别时let声明的范围是块作用域,var声明的范围是函数作用域。
let也不允许同一块作用域中出现冗余声明(同一作用域不能重复声明同一变量)
let 声明的变量不会自动提升。
(1)、暂时性死区
在 let 声明之前的执行瞬间被称为“暂时性死区”(temporal dead zone),在此阶段引用任何后面才声明的变量都会抛出 ReferenceError。
// name 会被提升
console.log(name); // undefined
var name = 'Matt';
// age 不会被提升
console.log(age); // ReferenceError:age 没有定义
let age = 26;
(2)、全局声明
let 全局声明的变量不会成为window对象的属性
let age = 26;
console.log(window.age); // undefined
(3)、条件声明
不能依赖条件声明模式:var声明变量时会被提升。JavaScript引擎会自动将多余的声明在顶部作用域合并为一个声明。因为let的作用域是块,所以不可能检查前面是否已经声明使用let声明过同名变量,同时也就不可能在没有声明的情况下声明它
<script>
var name = 'Nicholas';
let age = 26;
</script>
<script>
// 假设脚本不确定页面中是否已经声明了同名变量
// 那它可以假设还没有声明过
var name = 'Matt';
// 这里没问题,因为可以被作为一个提升声明来处理
// 不需要检查之前是否声明过同名变量
let age = 36;
// 如果 age 之前声明过,这里会报错
</script>
//使用 try/catch 语句或 typeof 操作符也不能解决,因为条件块中 let 声明的作用域仅限于该块。
<script>
let name = 'Nicholas';
let age = 36;
</script>
<script>
// 假设脚本不确定页面中是否已经声明了同名变量
// 那它可以假设还没有声明过
if (typeof name === 'undefined') {
let name;
}
// name 被限制在 if {} 块的作用域内
// 因此这个赋值形同全局赋值
name = 'Matt';
try {
console.log(age); // 如果 age 没有声明过,则会报错
}
catch(error) {
let age;
}
// age 被限制在 catch {}块的作用域内
// 因此这个赋值形同全局赋值
age = 26;
</script>
(4)、for循环中的let声明
for循环中使用let循环定义的迭代变量不会渗透到循环体外部 (for-in、for-of同理)
for (var i = 0; i < 5; ++i) {
// 循环逻辑
}
console.log(i); // 5
//改成使用 let 之后,这个问题就消失了,因为迭代变量的作用域仅限于 for 循环块内部:
for (let i = 0; i < 5; ++i) {
// 循环逻辑
}
console.log(i); // ReferenceError: i 没有定义
3、const声明
const 的行为与 let 基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且
尝试修改 const 声明的变量会导致运行时错误。
const age = 26;
age = 36; // TypeError: 给常量赋值
// const 也不允许重复声明
const name = 'Matt';
const name = 'Nicholas'; // SyntaxError
// const 声明的作用域也是块
const name = 'Matt';
if (true) {
const name = 'Nicholas';
}
console.log(name); // Matt
const 声明的限制只适用于它指向的变量的引用。换句话说,如果 const 变量引用的是一个对象,
那么修改这个对象内部的属性并不违反 const 的限制。
const person = {};
person.name = 'Matt'; // ok
//JavaScript 引擎会为 for 循环中的 let 声明分别创建独立的变量实例,虽然 const 变量跟 let 变
//量很相似,但是不能用 const 来声明迭代变量(因为迭代变量会自增):
for (const i = 0; i < 10; ++i) {} // TypeError:给常量赋值
4、推荐风格
1. 不使用 var
有了 let 和 const,大多数开发者会发现自己不再需要 var 了。限制自己只使用 let 和 const有助于提升代码质量,因为变量有了明确的作用域、声明位置,以及不变的值。
2. const 优先,let 次之
使用 const 声明可以让浏览器运行时强制保持变量不变,也可以让静态代码分析工具提前发现不合法的赋值操作。因此,很多开发者认为应该优先使用 const 来声明变量,只在提前知道未来会有修改时,再使用 let。这样可以让开发者更有信心地推断某些变量的值永远不会变,同时也能迅速发现因意外赋值导致的非预期行为。