js 基础
基础语法
语句
console.log("Hello, world!");
注释
// single line comment
/* This is a multi-line comment */
Strict Mode
strict mode
- 特殊模式;
- 禁止不稳定行为;
开启方式
// 全局开启
"use strict";
// ..;
// 局部位置开启
function doSomething() {
"use strict";
// ..;
}
变量
声明变量
声明变量
- 未初始化赋值 undefined;
let message;
let message, found, age;
let message = "hi";
变量赋值的本质
- 储存的并不是变量值本身;
- 而是变量值在栈中的内存地址;
不同关键字混合声明
- 关键字并非定义不同变量,而是指明变量作用域;
var name;
let name; // SyntaxError
let age;
var age; // SyntaxError
命名规则
变量
- 大小写敏感;
- 字母 + 下划线 + $ + 数字;
- 字母,下划线和 $ 开头;
- 小驼峰形式;
常量
- 大写字母;
- 下划线;
不声明
- 自动添加至 global context (window/globalThis);
- 推荐不要使用;
var 声明
作用域
- 函数作用域;
- 浏览器环境绑定至 windows 上;
- node 不会绑定在 globalThis 上;
变量提升
- var 声明会自动提升至所在作用域的顶端;
var name = "Jake";
// 等效于
name = "Jake";
var name;
声明前使用 var 变量
- var 变量赋值为 undefined;
console.log(name); // undefined
var name = "Jake";
重复声明
- var 允许重复声明;
var name;
var name;
let 声明
作用域
- 块作用域: 包裹的区域;
重复声明
- let 不允许重复声明;
let age;
let age; // SyntaxError; identifier 'age' has already been declared
变量提升
- let 不会发生变量提升;
console.log(age); // ReferenceError: age is not defined
let age = 26;
全局声明
- let 出现在全局上下文时;
- 其具有全局作用域;
- 但其不会绑定到 window 上;
let age = 26;
console.log(window.age); // undefined
const 声明
机制
- 与 let 基本一致;
初始化
- const 声明后必须初始化;
- const 声明变量不可修改;
更快的 const
- 使用 const 声明时;
- 编译器直接用其实际值进行替换;
- 节约查变量表的时间;
关键字和保留字
关键字一览
break | do | in | typeof |
case | else | instanceof | var |
catch | export | new | void |
class | extends | return | while |
const | finally | super | with |
continue | for | switch | yield |
debugger | function | this | |
default | if | throw | |
delete | import | try |
保留关键字一览
enum | ||
implements | package | public |
interface | protected | static |
let | private | |
await |
操作符
一元操作符
自增自减操作符
// ++x, 先自增再返回值
// --x, 先自减再返回值
// x++, 先返回值再自增
// x--, 先返回值再自减
let num1 = 29;
let num2 = --num1 + 2; // 30
let num3 = num1-- + 2; // 31
一元加减运算符
操作符 | 机制 |
---|---|
+ (一元) | 正值, 无左操作数等效于 Number() 函数 |
- (一元) | 负值, 无左操作数等效于 -Number() 函数 |
位操作符
操作符 | 机制 |
---|---|
~ | 按位非 |
& | 按位与 |
| | 按位或 |
^ | 按位异或 |
<< | 左移, 保留符号位 |
>> | 右移, 保留符号位 |
>>> | 右移, 不保留符号位, 负数差距较大, 正数不影响 |
逻辑操作符
逻辑操作符
操作符 | 含义 | 机制 | 应用 |
---|---|---|---|
!expr | 非 | 转换为 boolean 并取反 | !! 等效于 Boolean() |
expr1 && expr2 | 与 | 一假即假, 全真才真 | 若 expr1 为真, 返回 expr2, 反之返回 expr1 |
expr1 || expr2 | 或 | 一真即真, 全假才假 | 若 expr1 为假, 返回 expr2, 反之返回 expr1 |
expr1 ?? expr2 | 空值合并 | 返回第一个不为 null 或 undefined 的值 | 无 |
短路机制
- false && anything,返回 false,anything 不被计算;
- true || anything 返回 true,anything 不被计算;
|| 与 ?? 的区别
- || 返回第一个真值,即无法区分 false,0 和 "";
- ??返回第一个已定义的值;
let height = 0;
height || 100; // 100
height ?? 100; // 0
四则运算操作符
基本语法
let result = 34 * 56; // 乘
let result = 66 / 11; // 除
let result = 26 % 5; // 取余
let result = 3 ** 2; // 幂运算, 等效于 Math.pow(3, 2)
let result = 1 + 2; // 加
let result = 2 - 1; // 减
隐式转换原则
- 任一操作数为非数字,自动执行 Number() 函数;
- + 中任一操作数为字符串,非字符串操作数自动执行 String() 函数;
计算原则
- 两个数字返回计算结果,若超范围返回对应 Infinity;
- 任一操作数为 NaN,返回 NaN;
- 若计算无效,返回 NaN;
- 其中一个操作数为 (-)Infinity;
- 乘除 0:NaN;
- 无逻辑上的结果:NaN;
- 其余:Infinity;
关系运算符
比较机制
运算符 | 机制 |
---|---|
> | 若左操作数大于右操作数返回 true, 反之返回 false |
>= | 若左操作数大于等于右操作数返回 true, 反之返回 false |
<= | 若左操作数小于右操作数返回 true, 反之返回 false |
<= | 若左操作数小于等于右操作数返回 true, 反之返回 false |
比较机制
- 若均为数字,比较数字大小;
- 若均为 string,比较对应字符中第一个不同的字符的字符编码;
- 若任一为数字,另一转换为数字;
- 若任一为 object;
- 首先执行 valueOf() 返回 number;
- 其次执行 toString(),返回 string;
- 任一为 NaN,返回 false;
判等操作符
简单判等
判等机制
运算符 | 机制 |
---|---|
== | 若转换后的操作数相等返回 true, 反之返回 false |
!= | 若转换后的操作数不相等返回 true, 反之返回 false |
隐式转换原则
- 若任一操作符为非数字;
- 利用 Number() 将其转换为数字;
- 若仅有一个为 object;
- 仅执行 valueOf() 返回 number;
特殊判等机制
- null 和 undefined 相等;
- 任一为 NaN;
- == 返回 false;
- != 返回 true;
- 均为 object,判断两者是否指向同一个 object;
严格判等
判等机制
运算符 | 机制 |
---|---|
=== | 若不经转换的操作数相等且类型相同返回 true, 反之返回 false |
!== | 若不经转换的操作数不相等或类型不相同返回 true, 反之返回 false |
条件操作符
// boolean_expression 为真返回 true_value, 反之返回 false_value
variable = boolean_expression ? true_value : false_value;
赋值操作符
Name | Shorthand operator | Meaning |
---|---|---|
赋值 | x = f() | x = f() |
加赋值 | x += f() | x = x + f() |
减赋值 | x -= f() | x = x - f() |
乘赋值 | x *= f() | x = x * f() |
除赋值 | x /= f() | x = x / f() |
取余赋值 | x %= f() | x = x % f() |
乘方赋值 | x **= f() | x = x ** f() |
左移赋值 | x <<= f() | x = x << f() |
右移赋值 | x >>= f() | x = x >> f() |
无符号右移赋值 | x >>>= f() | x = x >>> f() |
逗号操作符
// 分割表达式
// 返回最后一个操作符的值
let num = (5, 1, 4, 8, 0); // num becomes 0
优先级和结合性
优先级
- 运算符的优先次序;
结合性
- 相同优先级运算符的执行顺序;
优先级和结合性列表
Operator type | Individual operators | Associativity |
---|---|---|
member | . [] | left-to-right |
call / create instance | () new | left-to-right |
negation/increment | ! ~ - -- + ++ -- typeof void delete | right-to-left |
exponentiate | ** | right-to-left |
multiply/divide | * / % | left-to-right |
addition/subtraction | + - | left-to-right |
bitwise shift | << >> >>> | left-to-right |
relational | < <= > >= in instanceof | left-to-right |
equality | == != === !== | left-to-right |
bitwise-and | & | left-to-right |
bitwise-xor | ^ | left-to-right |
bitwise-or | | | left-to-right |
logical-and | && | left-to-right |
logical-or | || | left-to-right |
conditional | ?: | right-to-left |
assignment | = += -= **= *= /= %= <<= >>= >>>= &= ^= |= &&= ||= ??= | right-to-left |
comma | , | left-to-right |
提高优先级
- 使用 ();
最佳实践
变量使用
使用原则
- 推荐不要使用 var;
- 推荐使用 let 和 const;
- 能用 const 就用 const;
循环中的变量声明
var 声明
for (var i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0);
}
// It will actually console.log 5, 5, 5, 5, 5
let 声明
// 每一次循环声明一个新的变量;
// 每个 setTimeout() 引用五个不同的变量;
for (let i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0);
}
// console.logs 0, 1, 2, 3, 4
const 变量
- const 无法声明循环迭代器;
同名变量和同名函数
同名变量
- 使用忽略原则,后声明的被忽略;
同名函数
- 使用覆盖原则,先声明的被忽略;
同名的函数和变量
- 使用忽略原则;
- 函数提升会提升到变量之前,变量会被忽略;
- js function 和 var 分为声明和赋值两个操作;
var a = undefined;
function a() {
console.log(1);
}
a();
// 解析
function a() {
console.log(1);
}
var a;
a = undefined;
a(); // 此时a已经是个变量undefined, 报错;