1、对于引号的使用:
数字、布尔、对象、数组这类原生类型不需要引号。
只有键名带空格、横杠、关键字、特殊符号时,引号才强制不能省。
var person = {"name":"Jack", "age":18, "id":89757};
name / "age" / id 是属性键(属性名)
属性键规则和值不一样:
正常英文单词、合法标识符(name、age、id):可加引号、可不加引号,效果完全一样
name:"Jack" 等价 "name":"Jack"
"age":18 等价 age:18
这两个代码运行的区别:
var person = {name:"Jack","age":18,id:89757};
console.log(person.name1);
对象 person 里只有 name、age、id 三个属性,不存在 name1 属性
访问对象上未定义的属性,返回:undefined
var person = {name:"Jack","age":18,id:89757};
console.log(person1.name);
代码中只声明了变量 person,完全没有定义变量 person1
直接读取未声明的变量,浏览器 / 控制台会抛出引用错误:
Uncaught ReferenceError: person1 is not defined
总结: 属性不存在:对象。不存在的属性 → undefined(不会报错)
变量不存在:直接写一个从没 var/let/const 声明的变量 → 直接抛引用错误
①加性运算符
NaN:不是一个有效数字(Not a Number),只要计算乱套了就会出 NaN
只要任意一边是 NaN → 结果一定是 NaN
大白话:一堆数字里混了一个 "无效数字",整体计算直接作废,结果全是无效数字
举例:正无穷 + 负无穷 = NaN
一个无限大、一个无限小,两者没法抵消算出固定值,直接判定无效数字
好比:无限大减去无限大,没有固定答案
注意:如果有一边是字符串,加法会变成「拼接文字」,不再走这套数字加法规则 举例: 10 + "20" // "1020" 字符串拼接,不是数字30
极简记忆口诀:
沾 NaN 必出 NaN;
同号无穷相加不变号;
正负无穷一对碰直接变 NaN;
零相加:俩负零得负零,其余搭配全是正零。
②减性运算符
极简记忆口诀:
遇 NaN 必得 NaN;
同无穷相减(∞−∞ /-∞−-∞)必出 NaN;
异无穷相减:∞减负∞得∞,-∞减∞得 -∞;
零相减,只有负零减正零才得负零,其余大多归正零。
加/减无穷区别:
加法:同无穷相加不变;正负无穷碰一起直接 NaN
减法:同无穷相减直接 NaN;正负无穷相减会叠加放大(∞减负∞=∞;-∞减∞=-∞)
额外小提示(和加法区分):
加法里 ∞ + (-∞) = NaN
减法里 ∞ - (-∞) = ∞ 符号逻辑不一样,别记混。
而且减法永远不会字符串拼接,不像加号碰到文字会拼文本;只要用减号,一定会强制转数字计算。
例:"20" - 10 → 10(自动把 "20" 转数字 20 再减)
③递增和递减运算符:
可以作用于非数字变量,自动隐式转换
转换规则:先用Number()转值,再 ±1
字符串数字:
let s = "10";
s++; // "10"→10 → 11,s最终变成数字11
布尔值: true=1、false=0
let flag = true;
flag++; // 1+1=2
let f = false;
f--; //0-1=-1
undefined:转 Number 是 NaN,自增后依旧 NaN
null:转 Number 是 0
let n = null;
n++; //0+1=1
JS 只有一种 Number 类型(64 位浮点数),小数可以直接 ++/--
let x = 2.5;
x++; //3.5
④乘法运算符:
乘法不会像加号那样拼接字符串,遇到非数字一律先用 Number() 转成数字再计算,转失败得到 NaN
字符串数字
"5" * "2"; //10 字符串自动转5、2相乘
"10" * 3; //30
纯文本字符串(转不成数字)
"abc" * 2; //NaN
"12a" * 4; //NaN
布尔值
true=1、false=0
true * 6; //1*6=6
false * 9; //0*9=0
null / undefined
null 转数字是 0
undefined 转数字是 NaN
null * 7; //0*7=0
undefined * 3; //NaN
速记口诀:
沾 NaN 必出 NaN;
无穷乘大数留无穷,无穷乘 0 直接变 NaN;
正负 0 相乘,正负看乘数符号;
遇文本不拼接,全部强制转数字,转失败就是 NaN。
⑤除法运算符:
JS 除法不会像 C 语言整数相除自动取整,会保留小数结果
除法没有字符串拼接,所有非数字操作数自动用Number()转为数字再计算,转换失败则结果 NaN
C:两个 int 相除,直接舍弃小数、向下取整;7/2=3
JS:不分 int/float,统一浮点除法;7/2=3.5,想要取整要用Math.floor()、parseInt()
C:整数除以 0直接程序崩溃报错;浮点才会出现无穷 / NaN
JS:任何数字除以 0 不会崩溃,返回 Infinity/-Infinity;0/0 固定 NaN
速记口诀:
遇 NaN 必出 NaN;
正数除 0 正无穷,负数除 0 负无穷;0 除 0 直接 NaN;
无穷除以无穷算不出,结果归 NaN;
字符串不拼接,全部强制转数字;
和 C 不一样,整数相除保留小数,不会自动截断。
⑥求模运算符:
任一操作数为 NaN → 结果一定 NaN
四则通用规则,混入无效数字直接失效
NaN % 5 // NaN
9 % NaN // NaN
NaN % NaN // NaN
Infinity 无穷大运算规则:
无穷大 % 任意有限数字 = NaN
任意有限数字 % Infinity = 自身原值
Infinity % Infinity = NaN
Infinity % 10 // NaN
25 % Infinity // 25
-18 % Infinity // -18
Infinity % -Infinity // NaN
余数符号 = 被除数符号:
-10 % 3 // -1 被除数-10是负,余数负
10 % -3 // 1 被除数10是正,余数正
-10 % -3 // -1 被除数负,余数负
0、正负零运算规则:
非 0 数字 % ±0 → NaN(除数不能是 0 系列)
±0 % 任意非 0 数字 → 和被除数同号的 0
8 % 0 // NaN
-5 % -0 // NaN
+0 % 6 // +0
-0 % 9 // -0
% 不会拼接字符串,全部自动用Number()转数字计算,转换失败 = NaN
浮点数可以直接取模(JS 全是浮点):
C 语言 int 不能带小数取模,JS 支持小数运算
5.5 % 2 // 1.5
4.2 % 1 // 0.2
-3.6 % 2 // -1.6
相等操作符
严格相等 ===
规则:
先对比数据类型,类型不一样直接返回 false
类型相同,再对比值;值完全一致才返回 true
不做任何自动类型转换
特殊值严格相等规则:
NaN === 任何值 全是 false,包括 NaN === NaN → false
判断 NaN 只能用 Number.isNaN(值)
+0 === -0 → true(正负零严格相等)
对象 / 数组:对比内存地址,不是里面内容
宽松相等 ==(会自动隐式转类型,坑多尽量少用)
核心逻辑:
两边类型不同时,JS 自动调用Number()把两边转成数字,再对比值;有一套固定转换规则。
null 和 undefined 特殊配对
null == undefined → true;除此之外它们和任何值 == 都是 false
严格不等 !==类型不同直接 true
宽松不等 != 同样会自动转类型
null/undefined在C和js中的区别:
C 没有undefined;C 的NULL本质是宏0,NULL == 0为 true;
JS 里null == 0是 false,null==undefined才 true
C:数组名是地址,arr1 == arr2对比内存地址;结构体不能直接用 == 对比,要逐个成员判断
JS:对象 / 数组无论== / ===全对比引用地址,不对比内容
关系操作符:
任一操作数是 NaN → 结果一定是 false
只要有无效数字参与比较,全部返回 false
NaN > 1 // false
5 < NaN // false
NaN >= NaN // false
Infinity > Infinity // false
-Infinity < -Infinity // false
正负 0 互相比较完全相等:
+0 和 -0 在大小对比里无区别
+0 > -0 // false
+0 >= -0 // true
两边都是字符串: 不转数字,按ASCII 字符编码逐位对比
一边 / 两边不是字符串:全部调用Number()转为数字再对比大小
速记口诀:
遇 NaN,所有大小比较全 false;
两字符串比 ASCII 编码,其余组合统一转数字;
Infinity 最大,-Infinity 最小;±0 大小相等;
禁止连续连写比较,必须用&&拆分;
C 比 JS 严格太多,字符串不能直接大小对比。
逻辑操作符:
! 逻辑非(取反): 一元运算符,单个值取真假反向
&& 逻辑与: 两边都真,整体才真;一假即假
|| 逻辑或: 一边真,整体就真;一真即真
连续两个 !! 等价强制转布尔(常用小技巧)!!5 // true 等价 Boolean(5)
&& 逻辑与(短路与)
求值规则(短路核心 )
左边为假值:直接返回左边原值,右边代码完全不执行(短路)
左边为真值:返回右边原值
|| 逻辑或(短路或)
求值规则
左边为真值:直接返回左边原值,右边短路不执行
左边为假值:返回右边原值
优先级顺序:
! 最高 > && 次之 > || 最低
易踩坑易错点:
空数组\[\]、空对象{}是真值:
\[\] && 123 //123(左为真,返回右)
\[\] || 456 //\[\](左为真,返回左)
"0"字符串是真值,只有数字 0 是假:
"0" || 99 //"0"
0 || 99 //99
不能用 && || 替代 if 做复杂多分支,但适合简单默认赋值、条件执行
赋值操作符
基础赋值 =
解构赋值(JS 独有,C 语言没有)
快速把数组、对象里的值批量提取给变量
1. 数组解构
let arr = 10,20,30;
let x,y,z = arr;
// x=10,y=20,z=30
// 跳过元素
let m,,n = arr; // m=10,n=30
2. 对象解构
let person = {name:"Jack",age:18};
let {name,age} = person;
// name="Jack",age=18
// 自定义变量名
let {name:username} = person; // username = "Jack"
3. 函数参数解构(高频实用)
function show({name,age}){
console.log(name,age);
}
show({name:"Rose",age:17});
位操作符
按位与 &
规则:对应二进制位同时为 1,结果才是 1;否则 0
按位或 |
规则:对应二进制位有一个为 1,结果就是 1;全 0 才 0
按位异或 ^
规则:对应二进制位相同为 0,不同为 1
一个数异或自身 = 0:a ^ a = 0
一个数异或 0 = 自身:a ^ 0 = a
经典用法:交换两个变量,不用临时变量
let a=2,b=3;
a = a^b;
b = a^b;
a = a^b;
// a=3,b=2
按位取反 ~ (一元运算符)
规则:把 32 位每一位 0 变 1、1 变 0,本质公式:~x = -(x+1)
console.log(~5); //-6
console.log(~0); //-1
console.log(~-3); //2
小技巧:~~num 等价快速取整小数(正负都可用)
~~2.9 //2
~~-2.9 //-2
左移 <<
格式:a << n
规则:二进制整体向左挪 n 位,右侧补 0;等价 a × 2ⁿ
有符号右移 >>
格式:a >> n
规则:二进制整体向右挪 n 位,左侧补符号位(正数补 0,负数补 1);等价除以 2ⁿ,向下取整
无符号右移 >>>(JS 独有特色,C 无完全一样)
格式:a >>> n
规则:不管正负,左侧统一补 0;负数会变成超大正数(因为符号位 1 被替换成 0)
console.log(-1 >>> 0); //4294967295(32位全1转无符号最大值)
console.log(8 >>> 2); //2(正数和>>效果一致)
>>> 无符号右移
C 语言:只有无符号 unsigned 类型才能>>实现无符号右移,signed 负数右移补 1
JS 不分有无符号类型,统一用>>>强制全补 0,负数移位后变巨大正数
速记口诀
与 & 同 1 出 1,或 | 有 1 出 1,异或 ^ 不同出 1;
取反~公式:~x = -(x+1);双波浪快速取整;
左移 <<乘 2,有符号>> 除 2,无符号 >>> 正数同、负数变超大;
C 只允许整数运算,JS 所有值自动转 32 位整数;
常用实用小技巧:
快速取整:~~x、x|0、x>>0
奇偶判断:x & 1
乘除 2 的幂:x<<n等价 ×2ⁿ;x>>n等价 ÷2ⁿ(整数)
不用中间变量交换两数:a^=b;b^=a;a^=b
取相反数:~x +1(补码规则)
条件操作符
是一个三元运算符。
条件 ? 真值结果 : 假值结果
逗号操作符
逗号操作符可以用来在一条语句中执行多个操作:
let num1 = 1, num2 = 2, num3 = 3;
逗号运算符规则:从左到右执行所有表达式,返回最后一个的结果。
let a = (1 + 2, 3 + 4, 5 + 6);
// 分步执行:
// 1. 执行1+2(结果3,丢弃)
// 2. 执行3+4(结果7,丢弃)
// 3. 执行5+6(结果11,作为整体返回值)
console.log(a); // 11
for 循环头部批量更新(最经典用途):
for 循环三段里,用逗号同时更新多个变量
// i从0、j从10;每次i++ 同时 j--
for(let i=0, j=10; i<j; i++, j--){
console.log(i,j);
}
这里 i=0, j=10、i++, j-- 里的逗号就是逗号操作符,批量执行。
指数操作符
符号:**,作用:计算底数的幂次方
公式:a ** b = a的b次方
对比旧写法:等价 Math.pow(a, b)
注意:不能写成 -a ** b
运算优先级:** 高于一元负号 -
-3 ** 2 等价 -(3**2) = -9,不是 (-3)²
想要负数整体做底数必须加括号:(-3)**2