跳到主要内容

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 声明时;
  • 编译器直接用其实际值进行替换;
  • 节约查变量表的时间;

关键字和保留字

关键字一览
breakdointypeof
caseelseinstanceofvar
catchexportnewvoid
classextendsreturnwhile
constfinallysuperwith
continueforswitchyield
debuggerfunctionthis
defaultifthrow
deleteimporttry
保留关键字一览
enum
implementspackagepublic
interfaceprotectedstatic
letprivate
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;

赋值操作符

NameShorthand operatorMeaning
赋值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 typeIndividual operatorsAssociativity
member. []left-to-right
call / create instance() newleft-to-right
negation/increment! ~ - -- + ++ -- typeof void deleteright-to-left
exponentiate**right-to-left
multiply/divide* / %left-to-right
addition/subtraction+ -left-to-right
bitwise shift<< >> >>>left-to-right
relational< <= > >= in instanceofleft-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, 报错;