一、 前言
第四弹内容是操作符。 本章结束。第一个月的内容就完成了, 是一个节点。 下个月我们就要开始函数的学习了。 我们学习完函数之后。很多概念就可以跟大家补充说明了。 OK,那我们就开始本周的操作符学习
本系列为一周一更,计划历时6个月左右。从JS最基础【变量与作用域】到【异步编程,密码学与混淆】。希望自己能坚持下来, 也希望给准备入行JS逆向的朋友一些帮助, 第一次要点赞,评论和收藏。也是希望如果本专栏真的对大家有帮助可以点个赞,有建议或者疑惑可以在下方随时问。
先预告一下【V少JS基础班】的全部内容。看着很少,其实,正儿八经细分下来其实挺多的,第一个月的东西也一点不少。
第一个月【变量 、作用域 、BOM 、DOM 、 数据类型 、操作符】
第二个月【函数、闭包、原型链、this】
第三个月【面向对象编程、异步编程、nodejs】
第四个月【密码学、各类加密函数】
第五个月【jsdom、vm2、express】
第六个月【基本请求库、前端知识对接】
二、本节涉及知识点
操作符
三、重点内容
1- 初始操作符:
在 JavaScript 中,操作符(Operators) 是用来执行各种操作的符号或关键字。操作符可以操作数据(如变量、值)并产生结果。根据操作的对象类型和操作的方式,JavaScript 的操作符可以分为不同的种类。
口语OS: 我们看到的js代码, 无外乎: 常量、变量(声明&赋值)、各种数据类型、操作符、函数、对象、数组、事件、控制流、错误处理、异步编程、模块化等。我们把每个点都过一遍。再复杂的js代码也没有什么看不懂的。
2- 操作符的分类:
操作符是用来操作数据或变量的符号。JavaScript 中的操作符可以分为以下几类:
算术操作符:+、-、*、/、%、++、--
赋值操作符:=、+=、-=、*=、/=、%= 等
比较操作符:==、===、!=、!==、<、>、<=、>=
逻辑操作符:&&、||、!
位操作符:&、|、^、<<、>>、>>>
三元操作符:condition ? expr1 : expr2
类型操作符:typeof、instanceof、in
成员操作符:.、[](访问对象属性或数组元素)
1. 算术操作符
这些操作符用于执行基本的数学运算,如加法、减法、乘法等。
+(加法): 加法运算符,用于两个数相加,或者连接字符串。
5 + 3 // 8
'Hello' + ' ' + 'World' // 'Hello World'
-(减法): 减法运算符,用于两个数相减。
5 - 3 // 2
*(乘法): 乘法运算符,用于两个数相乘。
5 * 3 // 15
/(除法): 除法运算符,用于两个数相除。
6 / 3 // 2
%(取余): 取余运算符,返回除法运算后的余数。
5 % 3 // 2
** (指数): 指数运算符,返回第一个数的指数次方。
2 ** 3 // 8
ok, 首先我们要明确一点。 计算操作符在计算之前,会优先将两边的变量隐式转换为数字类型。 除了一个例外。 那就是加法(+). 我们经常会看到以下代码:
为什么呢? 字符串1与1相加。返回的是字符串’11’。 而字符串1与1相减。就变成了0
OS:认真看
以上问题,就是我们在算数运算符中要注意的点。最基本的已经说过了,但凡碰到运算符。我们默认会将两边的数据转成数字类型。 那加法除外。加法有一套自己的优先级。那就是我们常说的隐式转换。 那我们现在来看一看隐式转换。
2. 隐式转换(Implicit Conversion)
隐式转换是在进行表达式运算时,编程语言会自动地将不同数据类型的值转换为兼容的类型,以避免运行时错误。加法操作符(+)在遇到不同类型的运算对象时,会涉及隐式类型转换。
加法隐式转换的优先级:
1- 如果加法操作数中有一个是字符串类型,那么另外一个操作数会被隐式转换为字符串,并且会执行字符串拼接操作。
let result = 10 + '5'; // '105'
这里,10 会被转换为字符串 '10',然后执行拼接,最终结果为 '105'。
2- 数字与其他类型的加法:
如果加法操作数都是数字类型或可以转换为数字(例如字符串),JavaScript 会自动将其转换为数字进行加法运算。
let result = 10 + '5'; // '105'
let result2 = 10 + 5; // 15
这里的情况涉及到字符串与数字的相加,如果有字符串参与,加法就会优先执行字符串拼接。
3- 布尔值与数字的加法:
布尔值 true 和 false 会分别转换为数字 1 和 0。比如:
let result = true + 1; // 2
let result2 = false + 1; // 1
4- 对象与加法:
当其中一个操作数是对象时,会尝试调用对象的 toString() 或 valueOf() 方法,将其转换为原始类型,然后再进行加法运算。如果这些方法无法进行转换,通常会返回 NaN(Not a Number)。
总结:
加法隐式转换的优先级 是字符串拼接优先于数字加法,布尔值会转换成数字,
某些复杂类型(如对象)会调用其 toString() 或 valueOf() 方法进行转换。
上节也有说过,对象的显示转换和隐式转换的优先级
2. 赋值操作符
1- 基本赋值操作符:
最常用的赋值操作符是 =,它用于将右侧的值赋给左侧的变量。
let x = 5; // 将 5 赋值给变量 x
在上面的例子中,x 被赋值为 5。
这里我们要说一下。 赋值语
2- 扩展赋值操作符
JavaScript 提供了一些扩展赋值操作符,可以简化对变量进行修改的过程。这些操作符会对变量进行某种运算后再赋值。
2.1 加法赋值操作符:+=
let x = 5;
x += 3; // 等同于 x = x + 3;
console.log(x); // 8
2.2 减法赋值操作符:-=
let x = 5;
x -= 2; // 等同于 x = x - 2;
console.log(x); // 3
2.3 乘法赋值操作符:*=
let x = 5;
x *= 2; // 等同于 x = x * 2;
console.log(x); // 10
2.4 除法赋值操作符:/=
let x = 10;
x /= 2; // 等同于 x = x / 2;
console.log(x); // 5
2.5 取余赋值操作符:%=
let x = 10;
x %= 3; // 等同于 x = x % 3;
console.log(x); // 1
2.6 幂赋值操作符:**=(ES6新增)
let x = 2;
x **= 3; // 等同于 x = x ** 3;
console.log(x); // 8
3.对象解构赋值:
在 ES6 中,JavaScript 引入了对象解构赋值,使得从对象中提取值并赋给变量变得更加简洁。
const obj = { a: 1, b: 2 };
const { a, b } = obj; // 解构赋值
console.log(a); // 1
console.log(b); // 2
- 数组解构赋值:
const arr = [10, 20, 30];
const [x, y] = arr; // 解构赋值
console.log(x); // 10
console.log(y); // 20
5.默认赋值:
解构赋值时,如果变量未被赋值,可以使用默认值。
const { a = 1, b = 2 } = { a: 5 };
console.log(a); // 5
console.log(b); // 2
6.条件赋值:||= 和 &&=(ES11新增)
6.1 逻辑或赋值操作符:||=
如果左边的值为 falsy(假值),则给变量赋予右边的值。
let x = 0;
x ||= 5; // 如果 x 是 falsy(0),则 x = 5
console.log(x); // 5
6.2 逻辑与赋值操作符:&&=
如果左边的值为 truthy(真值),则给变量赋予右边的值。
let x = 10;
x &&= 5; // 如果 x 是 truthy(10),则 x = 5
console.log(x); // 5
总结
=:基本的赋值操作符。
+=, -=, *=, /=, %= 等:用于修改变量的值,并赋值回去。
解构赋值:简洁地从对象或数组中提取值。
默认赋值:解构时设置默认值。
||= 和 &&=:条件赋值操作符,用于根据条件修改变量值。
3. 比较操作符
比较操作符用于比较两个值,并返回一个布尔值(true 或 false)。它们通常用于条件判断、循环控制和逻辑表达式中。
1.相等操作符:== 和 ===
==(抽象相等操作符):比较两个值是否相等,会进行类型转换,如果两个值的类型不同,会尝试转换成相同类型后再比较。
===(严格相等操作符):比较两个值是否相等,不会进行类型转换,只有值和类型都相等时才返回 true。
let a = '5';
let b = 5;
console.log(a == b); // true (类型转换后,'5' 转为 5)
console.log(a === b); // false (类型不同,字符串和数字不相等)
!=(抽象不等操作符):比较两个值是否不相等,会进行类型转换。
!==(严格不等操作符):比较两个值是否不相等,不会进行类型转换,只有值或类型不相等时才返回 true。
let a = '5';
let b = 5;
console.log(a != b); // false (类型转换后,'5' 转为 5)
console.log(a !== b); // true (类型不同,字符串和数字不相等)
3.大于与小于:> 和 <
>:检查左侧的值是否大于右侧的值,返回 true 或 false。
<:检查左侧的值是否小于右侧的值,返回 true 或 false。
let a = 5;
let b = 10;
console.log(a > b); // false
console.log(a < b); // true
4.大于等于与小于等于: >= 和 <=
>=:检查左侧的值是否大于或等于右侧的值。
<=:检查左侧的值是否小于或等于右侧的值。
let a = 5;
let b = 5;
console.log(a >= b); // true
console.log(a <= b); // true
5.NaN 的比较
NaN(Not a Number)是一个特殊的数值,它不等于任何值,包括它自己。
也就是说,NaN == NaN 和 NaN === NaN 都返回 false。
let a = NaN;
let b = NaN;
console.log(a == b); // false
console.log(a === b); // false
要检查一个值是否是 NaN,可以使用 Number.isNaN() 方法:
console.log(Number.isNaN(a)); // true
6.字符串比较
在 JavaScript 中,字符串是基于字符的 Unicode 值进行比较的。
这意味着字符串的比较是逐个字符比较 Unicode 值的大小。
let a = 'apple';
let b = 'banana';
console.log(a > b); // false (根据字母顺序比较,第一个字符 'a' 比 'b' 小)
console.log(a < b); // true
7.对象比较
在 JavaScript 中,对象比较是基于引用的,即比较两个对象是否指向同一个内存地址。
let obj1 = { name: 'Alice' };
let obj2 = { name: 'Alice' };
let obj3 = obj1;
console.log(obj1 == obj2); // false (虽然属性值相同,但它们是不同的对象)
console.log(obj1 === obj2); // false (对象比较是基于引用的)
console.log(obj1 === obj3); // true (obj3 和 obj1 引用的是同一个对象)
总结:
== 和 === 用于判断两个值是否相等,后者严格比较类型。
!= 和 !== 用于判断两个值是否不相等,后者严格比较类型。
>、<、>= 和 <= 用于比较数值的大小关系。
NaN 是一个特殊的数值,它不等于任何值,包括它自己。
字符串的比较是根据字符的 Unicode 值进行的。
对象的比较是基于引用的,即比较两个对象是否指向相同的内存地址。
OS: 口语化表达。 == 与=== 的区别在于一个会进行数据类型转换,一个不会。
4. 逻辑操作符
逻辑操作符用于布尔值的运算,常用于控制流语句(如 if、while 等),帮助我们处理逻辑判断。
1.与操作符:&&
&&(与操作符)用于检查两个表达式是否都为真,只有两个表达式都为 true 时,
结果才为 true,否则为 false。
let a = true;
let b = false;
console.log(a && b); // false (因为 b 为 false)
console.log(true && true); // true
console.log(false && false); // false
逻辑与运算的短路特性:
短路:当第一个表达式为 false 时,第二个表达式不会被计算,因为结果已经确定为 false。
console.log(false && (1 / 0)); // false (1 / 0 不会被执行)
2.或操作符:||
||(或操作符)用于检查两个表达式是否至少有一个为真,只有两个表达式都为 false 时,
结果才为 false,否则为 true。
let a = true;
let b = false;
console.log(a || b); // true (因为 a 为 true)
console.log(false || false); // false
逻辑或运算的短路特性:
短路:当第一个表达式为 true 时,第二个表达式不会被计算,因为结果已经确定为 true。
console.log(true || (1 / 0)); // true (1 / 0 不会被执行)
3.非操作符:!
!(非操作符)用于对一个布尔值进行取反,即 true 变成 false,false 变成 true。
let a = true;
let b = false;
console.log(!a); // false (取反)
console.log(!b); // true
4.逻辑运算中的“短路行为”
逻辑运算符 && 和 || 都具有短路特性,它们会在运算过程中提前结束,减少不必要的运算。
&& 短路:如果第一个操作数为 false,则第二个操作数不会被求值,因为不管第二个操作数是什么,
结果都必然为 false。
|| 短路:如果第一个操作数为 true,则第二个操作数不会被求值,因为不管第二个操作数是什么,
结果都必然为 true。
5.逻辑运算符的其他用法
JavaScript 中的逻辑运算符不仅用于布尔值之间的逻辑判断,还常常用于 条件判断 或 赋值操作。
5.1 逻辑与 (&&) 与条件表达式
在 JavaScript 中,逻辑与运算符(&&)常用于简化条件表达式,返回第一个为 false 的值,或者返回最后一个值。
let a = 5;
let b = 10;
let result = (a > b) && 'True'; // 'True'(因为 a > b 是 false,结果是 false)
console.log(result); // false
let result2 = (a < b) && 'True'; // 'True'(因为 a < b 是 true,结果是 'True')
console.log(result2); // 'True'
5.2 逻辑或 (||) 与条件表达式
逻辑或运算符(||)常用于返回第一个为 true 的值,或者返回最后一个值。
let a = 0;
let b = 10;
let result = (a || b); // 10 (因为 a 是 falsy 值,返回 b)
console.log(result); // 10
6.布尔值的隐式转换
逻辑操作符也会涉及到布尔值的隐式类型转换。JavaScript 中的 假值(falsy values) 会在逻辑运算中被自动转换为 false,而 真值(truthy values) 会被自动转换为 true。
假值(falsy values):
false、0、""(空字符串)、null、undefined、NaN
真值(truthy values):
除了上述的假值,其他所有值都是 truthy 值,包括非空字符串、非零数字、对象、数组等。
console.log(0 || 'hello'); // 'hello' (0 是 falsy,返回 'hello')
console.log('' || 'world'); // 'world' (空字符串是 falsy,返回 'world')
console.log(true && 'yes'); // 'yes' (true 是 truthy,返回 'yes')
console.log(false && 'no'); // false (false 是 falsy,返回 false)
7.综合使用
在条件判断中,逻辑运算符的组合使用非常常见,可以在一行中进行复杂的逻辑判断。
let age = 25;
let hasPermission = true;
if (age >= 18 && hasPermission) {
console.log('Access granted');
} else {
console.log('Access denied');
}
let username = '';
let defaultUsername = 'Guest';
let result = username || defaultUsername; // 'Guest' (因为 username 是 falsy,返回 defaultUsername)
console.log(result); // 'Guest'
总结:
&&:返回两个表达式的 true 值,只有当两个操作数都为 true 时,结果为 true。具有短路行为。
||:返回两个表达式的 true 值,只要有一个操作数为 true,结果就是 true。也具有短路行为。
!:将布尔值取反。
短路行为:逻辑操作符的短路特性可以帮助优化代码执行。
布尔值的隐式转换:JavaScript 中的假值和真值会自动转换为 false 或 true,可以方便地进行逻辑判断。
5. 位操作符
位操作符在 JavaScript 中主要用于对整数的二进制位进行操作。它们直接对数字的二进制表示进行操作,这些操作是基于二进制位的 逻辑运算。
1.按位与操作符:&
& 操作符对两个操作数的每一位进行按位与运算。如果两个对应的二进制位都为 1,则结果为 1,否则为 0。
let a = 5; // 二进制: 0101
let b = 3; // 二进制: 0011
console.log(a & b); // 1(二进制: 0001)
解释:
0101(5)
0011(3)
按位与运算的结果是:0001(1)
2.按位或操作符:|
| 操作符对两个操作数的每一位进行按位或运算。如果两个对应的二进制位中至少有一个为 1,则结果为 1,否则为 0。
let a = 5; // 二进制: 0101
let b = 3; // 二进制: 0011
console.log(a | b); // 7(二进制: 0111)
解释:
0101(5)
0011(3)
按位或运算的结果是:0111(7)
3.按位异或操作符:^
^ 操作符对两个操作数的每一位进行按位异或运算。当两个二进制位不同(一个为 0,另一个为 1)时,结果为 1;
当两个二进制位相同(两个都为 0 或两个都为 1)时,结果为 0。
let a = 5; // 二进制: 0101
let b = 3; // 二进制: 0011
console.log(a ^ b); // 6(二进制: 0110)
解释:
0101(5)
0011(3)
按位异或运算的结果是:0110(6)
4.按位非操作符: ~
~ 操作符对操作数的每一位进行按位非运算,也就是将每一位 0 变成 1,将每一位 1 变成 0。
let a = 5; // 二进制: 0101
console.log(~a); // -6(二进制: 1010)
解释:
0101(5)
按位非运算后的结果是:1010(-6)
注意: 按位非操作符执行的是 取反,但它与普通的数学取反不同,
因为 JavaScript 中的数字是 32 位有符号整数,结果会受到 二进制补码 的影响。
5.左移操作符:<<
<< 操作符将数字的二进制位向左移动指定的位数。每左移一位,相当于将数字乘以 2。
let a = 5; // 二进制: 0101
console.log(a << 1); // 10(二进制: 1010)
console.log(a << 2); // 20(二进制: 10100)
解释:
0101(5)左移 1 位后,变成 1010(10)
0101(5)左移 2 位后,变成 10100(20)
6.带符号右移操作符:>>
>> 操作符将数字的二进制位向右移动指定的位数。对于带符号整数,它会保持符号位(即负数会保持负号)。
每右移一位,相当于将数字除以 2。
let a = 5; // 二进制: 0101
let b = -5; // 二进制: 11111111111111111111111111111011(32 位)
console.log(a >> 1); // 2(二进制: 0010)
console.log(b >> 1); // -3(二进制: 11111111111111111111111111111101)
解释:
0101(5)右移 1 位后,变成 0010(2)
11111111111111111111111111111011(-5)右移 1 位后,变成 11111111111111111111111111111101(-3)
7.无符号右移操作符:>>>
>>> 操作符将数字的二进制位向右移动指定的位数,但不同于 >>,它 不保持符号位,
即使是负数也会将符号位当作普通位来处理。
let a = 5; // 二进制: 0101
let b = -5; // 二进制: 11111111111111111111111111111011(32 位)
console.log(a >>> 1); // 2(二进制: 0010)
console.log(b >>> 1); // 2147483643(二进制: 01111111111111111111111111111111)
解释:
0101(5)无符号右移 1 位后,变成 0010(2)
11111111111111111111111111111011(-5)无符号右移 1 位后,变成 01111111111111111111111111111111(2147483643)
总结:
按位与 &:两个二进制位都为 1 时,结果为 1。
按位或 |:只要一个二进制位为 1,结果为 1。
按位异或 ^:两个二进制位不同,结果为 1,相同则为 0。
按位非 ~:将每一位取反(0 变 1,1 变 0)。
左移 <<:将二进制位向左移动,类似于乘以 2。
带符号右移 >>:将二进制位向右移动,保持符号位。
无符号右移 >>>:将二进制位向右移动,不保持符号位。
6. 三元操作符
三元操作符是一种 简化的条件表达式,它可以用来代替常规的 if-else 语句。
三元操作符有三个部分,所以叫做三元(ternary)操作符。
condition ? expression_if_true : expression_if_false;
condition:这是一个布尔表达式。它的值可以是 true 或 false。
expression_if_true:如果 condition 为 true,则返回这个表达式的值。
expression_if_false:如果 condition 为 false,则返回这个表达式的值。
let age = 18;
let canVote = (age >= 18) ? "Yes, you can vote!" : "No, you're too young.";
console.log(canVote); // 输出:Yes, you can vote!
解释:
age >= 18 是条件表达式,它会被评估为 true(因为 age 等于 18)。
如果条件为 true,就返回 "Yes, you can vote!"。
如果条件为 false,就返回 "No, you're too young."。
let score = 85;
let grade = (score >= 90) ? "A" : (score >= 80) ? "B" : (score >= 70) ? "C" : "F";
console.log(grade); // 输出:B
解释:
首先,检查 score >= 90,如果为 true,返回 "A"。
如果 score >= 90 为 false,接着检查 score >= 80,如果为 true,返回 "B"。
如果两个条件都为 false,继续检查 score >= 70,如果为 true,返回 "C"。
如果所有条件都为 false,返回 "F"。
function checkAccess(age) {
return (age >= 18) ? "Access granted" : "Access denied";
}
console.log(checkAccess(20)); // 输出:Access granted
console.log(checkAccess(16)); // 输出:Access denied
解释:
根据 age 的值,三元操作符决定返回 "Access granted" 还是 "Access denied"。
优点:
简洁性:三元操作符将 if-else 语句简化为一行代码,适合用于简单的条件判断。
可读性:对于短小的条件判断,三元操作符使代码更加简洁,容易理解。
缺点:
过度嵌套:如果将多个三元操作符嵌套使用,可能会导致代码难以理解,降低可读性。
不适用于复杂的逻辑:对于复杂的条件判断,还是推荐使用 if-else 语句,因为它会更加清晰。
总结:
三元操作符是条件表达式的简化形式,使用起来简洁高效,适用于简短的条件判断。
它有三个部分:条件、条件为 true 时的结果、条件为 false 时的结果。
尽管三元操作符可以嵌套使用,但如果条件逻辑复杂,使用传统的 if-else 语句可能更为合适。
let userInput = null;
let name = userInput ? userInput : "Guest";
console.log(name); // 输出:Guest
解释:
userInput 是 null,所以条件表达式 userInput 为 false。
因此,返回 "Guest",并且 name 的值为 "Guest"。
7. 类型操作符
1.typeof 操作符
前面已经讲过 typeof,它是一个非常常见的操作符,用于获取变量的数据类型。接下来,
我们可以再详细地讨论一下 typeof 在不同情况下的返回值。
typeof operand
operand:表示要检查的值(变量或表达式)。
特殊情况:
typeof null:返回 "object",这是 JavaScript 中的一个历史遗留问题。虽然 null 是原始类型(primitive type),但 typeof null 却返回 "object",这一点需要特别注意。
console.log(typeof null); // 输出:object
typeof 对数组的返回值:数组是对象的一种特殊形式,typeof 对数组的判断返回 "object",所以如果要判断一个变量是否为数组,需要使用 Array.isArray() 方法。
let arr = [1, 2, 3];
console.log(typeof arr); // 输出:object
typeof 对函数的返回值:对于函数,typeof 会返回 "function"。
function foo() {}
console.log(typeof foo); // 输出:function
2.instanceof 操作符
instanceof 用于判断一个对象是否为某个构造函数的实例。这个操作符常常用于类的实例化检测。
object instanceof constructor
object:要检查的对象。
constructor:构造函数或类,通常是对象的类型。
let arr = [1, 2, 3];
console.log(arr instanceof Array); // 输出:true
let date = new Date();
console.log(date instanceof Date); // 输出:true
let num = 10;
console.log(num instanceof Number); // 输出:false(因为 num 不是通过 Number 构造函数创建的)
let obj = {};
console.log(obj instanceof Object); // 输出:true
注意:
instanceof 检查的是对象的原型链,能有效地检测对象是否是某个类的实例或继承自某个类的实例。
它不能用于基本数据类型,比如 number、string、boolean 等。
3.constructor 属性
constructor 是每个对象都有的属性,指向该对象的构造函数。通过 constructor 属性,你可以检查对象的类型。
let arr = [1, 2, 3];
console.log(arr.constructor === Array); // 输出:true
let date = new Date();
console.log(date.constructor === Date); // 输出:true
let obj = {};
console.log(obj.constructor === Object); // 输出:true
注意:
constructor 只适用于对象,对于原始类型如数字和字符串,它并不存在。
4.Array.isArray() 方法
Array.isArray() 是专门用来判断一个值是否是数组的静态方法。typeof 无法区分数组和普通对象,
所以使用 Array.isArray() 来准确检查数组是一个好选择。
Array.isArray(value)
value:要检查的值。
示例:
javascript
复制代码
let arr = [1, 2, 3];
console.log(Array.isArray(arr)); // 输出:true
let obj = {};
console.log(Array.isArray(obj)); // 输出:false
5.new 操作符
new 操作符用来创建实例化对象。它与构造函数一起使用,可以创建特定类型的对象实例。
function Person(name) {
this.name = name;
}
let person1 = new Person("Alice");
console.log(person1 instanceof Person); // 输出:true
注意:
new 操作符会调用构造函数并返回实例对象。
6.Object() 操作符
Object() 是 JavaScript 中的一个内置函数,用来将一个值转换成对象类型。特别是对于原始类型,
Object() 会将它们包装成对象。
let str = "hello";
let objStr = Object(str);
console.log(typeof objStr); // 输出:object
let num = 123;
let objNum = Object(num);
console.log(typeof objNum); // 输出:object
注意:
Object() 会将原始值(例如字符串、数字、布尔值)转换为它们的包装对象(String、Number、Boolean)。
7.toString() 方法
每个对象都继承自 Object,并且有一个 toString() 方法。这个方法会返回对象的字符串表示形式,
通常用于将对象转换成字符串。
let obj = { name: "Alice" };
console.log(obj.toString()); // 输出:"[object Object]"
let arr = [1, 2, 3];
console.log(arr.toString()); // 输出:"1,2,3"
注意:
对象的 toString() 方法默认返回 [object Object],但你可以在自定义类中重写这个方法。
总结:
typeof:检测基本数据类型,注意 null 会返回 "object",数组和函数有特殊的返回值。
instanceof:检查一个对象是否是某个构造函数或类的实例。
constructor:对象的属性,返回对象的构造函数,适用于对象类型。
Array.isArray():专门判断一个值是否为数组。
new:用于实例化对象。
Object():将原始值转换为对象。
toString():将对象转换为字符串。
8. 成员操作符
成员操作符(Member Operators)主要用于访问对象或数组的属性或元素。它们是操作对象和数组的关键工具,
常见的有 点操作符(.)和 方括号操作符([])。这两种操作符用于访问对象的属性或数组的元素,
但它们在使用时有不同的语法规则和特点。
1.点操作符(.)
点操作符是 JavaScript 中最常用的成员操作符之一,它用于访问对象的属性或方法。
使用点操作符时,属性名称必须是有效的标识符(例如,不可以包含空格或特殊字符)。
object.property
object:目标对象。
property:要访问的属性名称,必须是有效的标识符。
示例:
javascript
复制代码
let person = {
name: "Alice",
age: 25,
greet: function() {
console.log("Hello, " + this.name);
}
};
console.log(person.name); // 输出:"Alice"
console.log(person.age); // 输出:25
person.greet(); // 输出:"Hello, Alice"
注意:
使用点操作符时,属性名称必须是有效的标识符。
如果属性名称包含空格或特殊字符,不能使用点操作符(例如:person["first name"]),这时应使用方括号操作符。
2.方括号操作符([])
方括号操作符用于访问对象的属性或数组的元素。它比点操作符更灵活,允许使用动态或变量作为属性名称,
并支持字符串中包含空格或特殊字符的属性名。
3.成员访问(in 操作符)
property in object
property:要检查的属性名称。
object:要检查的对象。
示例:
javascript
复制代码
let person = {
name: "Alice",
age: 25
};
console.log("name" in person); // 输出:true
console.log("gender" in person); // 输出:false
注意:
in 操作符会检查对象及其原型链中是否有指定的属性。
4.成员遍历(for…in 循环)
for...in 循环用于遍历对象的所有可枚举属性,包括继承的属性。它可以用来访问对象的所有成员。
for (let key in object) {
// 执行操作
}
key:属性名称的变量。
object:要遍历的对象。
let person = {
name: "Alice",
age: 25
};
for (let key in person) {
console.log(key + ": " + person[key]);
}
// 输出:
// name: Alice
// age: 25
注意:
for...in 遍历的是对象的可枚举属性,包括继承的属性。如果只想遍历对象本身的属性,可以结合 hasOwnProperty() 方法使用。
5.数组下标操作符([])
对于数组,方括号操作符不仅可以用来访问数组元素,还可以用来设置数组元素的值。
let arr = [1, 2, 3];
arr[0] = 100; // 修改第一个元素
console.log(arr[0]); // 输出:100
6.对象解构赋值(Destructuring)
虽然解构赋值不是传统意义上的“成员操作符”,但它允许通过属性名从对象或数组中提取值。
这是 JavaScript ES6 引入的一个语法糖。
let person = {
name: "Alice",
age: 25
};
let { name, age } = person;
console.log(name); // 输出:"Alice"
console.log(age); // 输出:25
let arr = [1, 2, 3];
let [first, second] = arr;
console.log(first); // 输出:1
console.log(second); // 输出:2
总结:
.(点操作符):用于访问对象的属性或方法,适用于有效标识符的属性名称。
[](方括号操作符):可以动态访问对象的属性或数组的元素,支持使用变量或包含空格、特殊字符的属性名。
in 操作符:用于检查对象中是否存在某个属性。
for...in 循环:遍历对象的可枚举属性。
数组下标操作符:用于访问或修改数组的元素。
对象解构赋值:通过解构语法从对象或数组中提取值。
操作符是JavaScript的基础之一。 也是js逆向中必定包含的知识点。 所以每个操作符都需要理解。 其中包括经典的。 a++ 和 ++a的区别等。
三、JS中操作符的优先级(重要指数四颗星, js逆向中经常会遇到)
优先级 | 运算符 | 说明 | 结合性 |
---|---|---|---|
1 | [], ., () | 字段访问, 数组索引, 函数调用和表达式分组 | 从左向右 |
2 | ++, --, !, delete, new, typeof, void | 一元运算符, 返回数据类型, 对象穿件, 未定义的值 | 从右向左 |
3 | *, /, % | 相乘, 相除, 求余数 | 从左向右 |
4 | +, - | 相加, 相减, 字符串串联 | 从左向右 |
5 | <<, >>, >>> | 左位移, 右位移, 无符号右移 | 从左向右 |
6 | <, <=, >, >=, instanceof | 小于, 小于等于, 大于, 大于等于, 是否为特定类的实例 | 从左向右 |
7 | ==, !=, =, ! | 相等, 不相等, 全等, 不全等 | 从左向右 |
8 | & | 按位与 | 从左向右 |
9 | ^ | 按位异或 | 从左向右 |
10 | | | 按位或 | 从左向右 |
11 | && | 逻辑与 | 从左向右 |
12 | || | 逻辑或 | 从左向右 |
13 | ?: | 条件运算符 | 从右向左 |
14 | =,+=,-=,*=,/=,%=,!=,^=,>>= | 混合赋值运算符 | 从右向左 |
15 | , | 多个计算 | 按优先顺序计算, 然后从右向左 |
四、思考题
我们校验一下学习成果。 本节操作符,可能会比较枯燥,内容也比较多。为了检验大家是否已经掌握。这里给大家出一个练习题:
有且仅使用以下字符构建出字符串 “result”
(、 )、 [、 ]、 {、 }、 +、 -、 !
例如:
数字0可以使用 +[] 表示
字符串’true’可以使用 []+!![]表示
字符串 ‘false’ 可以使用 []+![]表示
我们可以使用取字符串’true’下标为3的字符串。构建出字符串’e’
那通过我们今天操作符的学习。 我们可以构建出很多初始标识符。如:
true、 false、[object Object]、 undefined