V少JS基础班之第四弹

news2025/1/15 2:46:10

一、 前言

第四弹内容是操作符。 本章结束。第一个月的内容就完成了, 是一个节点。 下个月我们就要开始函数的学习了。 我们学习完函数之后。很多概念就可以跟大家补充说明了。 OK,那我们就开始本周的操作符学习
本系列为一周一更,计划历时6个月左右。从JS最基础【变量与作用域】到【异步编程,密码学与混淆】。希望自己能坚持下来, 也希望给准备入行JS逆向的朋友一些帮助, 第一次要点赞,评论和收藏。也是希望如果本专栏真的对大家有帮助可以点个赞,有建议或者疑惑可以在下方随时问。
先预告一下【V少JS基础班】的全部内容。看着很少,其实,正儿八经细分下来其实挺多的,第一个月的东西也一点不少。
第一个月【变量作用域BOMDOM数据类型操作符
第二个月【函数、闭包、原型链、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
  1. 数组解构赋值:
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)
解释:
0101500113)
按位与运算的结果是:00011

2.按位或操作符:|

| 操作符对两个操作数的每一位进行按位或运算。如果两个对应的二进制位中至少有一个为 1,则结果为 1,否则为 0。
let a = 5;  // 二进制: 0101
let b = 3;  // 二进制: 0011
console.log(a | b);  // 7(二进制: 0111)
解释:
0101500113)
按位或运算的结果是:01117

3.按位异或操作符:^

^ 操作符对两个操作数的每一位进行按位异或运算。当两个二进制位不同(一个为 0,另一个为 1)时,结果为 1;
当两个二进制位相同(两个都为 0 或两个都为 1)时,结果为 0。
let a = 5;  // 二进制: 0101
let b = 3;  // 二进制: 0011
console.log(a ^ b);  // 6(二进制: 0110)
解释:
0101500113)
按位异或运算的结果是:01106

4.按位非操作符: ~

~ 操作符对操作数的每一位进行按位非运算,也就是将每一位 0 变成 1,将每一位 1 变成 0。
let a = 5;  // 二进制: 0101
console.log(~a);  // -6(二进制: 1010)
解释:
01015)
按位非运算后的结果是:1010-6
注意: 按位非操作符执行的是 取反,但它与普通的数学取反不同,
因为 JavaScript 中的数字是 32 位有符号整数,结果会受到 二进制补码 的影响。

5.左移操作符:<<

<< 操作符将数字的二进制位向左移动指定的位数。每左移一位,相当于将数字乘以 2。
let a = 5;  // 二进制: 0101
console.log(a << 1);  // 10(二进制: 1010)
console.log(a << 2);  // 20(二进制: 10100)
解释:
01015)左移 1 位后,变成 10101001015)左移 2 位后,变成 1010020

6.带符号右移操作符:>>

>> 操作符将数字的二进制位向右移动指定的位数。对于带符号整数,它会保持符号位(即负数会保持负号)。
每右移一位,相当于将数字除以 2。
let a = 5;   // 二进制: 0101
let b = -5;  // 二进制: 11111111111111111111111111111011(32 位)
console.log(a >> 1);  // 2(二进制: 0010)
console.log(b >> 1);  // -3(二进制: 11111111111111111111111111111101)
解释:
01015)右移 1 位后,变成 0010211111111111111111111111111111011-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)
解释:
01015)无符号右移 1 位后,变成 0010211111111111111111111111111111011-5)无符号右移 1 位后,变成 011111111111111111111111111111112147483643
总结:
按位与 &:两个二进制位都为 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 >= 90false,接着检查 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2276758.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【STM32-学习笔记-7-】USART串口通信

文章目录 USART串口通信Ⅰ、硬件电路Ⅱ、常见的电平标准Ⅲ、串口参数及时序Ⅳ、STM32的USART简介数据帧起始位侦测数据采样波特率发生器 Ⅴ、USART函数介绍Ⅵ、USART_InitTypeDef结构体参数1、USART_BaudRate2、USART_WordLength3、USART_StopBits4、USART_Parity5、USART_Mode…

Docker 安装开源的IT资产管理系统Snipe-IT

一、安装 1、创建docker-compose.yaml version: 3services:snipeit:container_name: snipeitimage: snipe/snipe-it:v6.1.2restart: alwaysports:- "8000:80"volumes:- ./logs:/var/www/html/storage/logsdepends_on:- mysqlenv_file:- .env.dockernetworks:- snip…

达梦8-DMSQL程序设计学习笔记1-DMSQL程序简介

1、DMSQL程序简介 DMSQL程序是达梦数据库对标准SQL语言的扩展&#xff0c;是一种过程化SQL语言。在DMSQL程序中&#xff0c;包括一整套数据类型、条件结构、循环结构和异常处理结构等&#xff0c;DMSQL程序中可以执行SQL语句&#xff0c;SQL语句中也可以使用DMSQL函数。 DMSQ…

NLP中常见的分词算法(BPE、WordPiece、Unigram、SentencePiece)

文章目录 一、基本概念二、传统分词方法2.1 古典分词方法2.2 拆分为单个字符 三、基于子词的分词方法&#xff08;Subword Tokenization&#xff09;3.1 主要思想3.2 主流的 Subword 算法3.3 Subword 与 传统分词方法的比较 四、Byte Pair Encoding (BPE)4.1 主要思想4.2 算法过…

第三十六章 Spring之假如让你来写MVC——拦截器篇

Spring源码阅读目录 第一部分——IOC篇 第一章 Spring之最熟悉的陌生人——IOC 第二章 Spring之假如让你来写IOC容器——加载资源篇 第三章 Spring之假如让你来写IOC容器——解析配置文件篇 第四章 Spring之假如让你来写IOC容器——XML配置文件篇 第五章 Spring之假如让你来写…

PyTorch 深度学习框架快速入门 (小土堆)

PyTorch 深度学习框架快速入门 深度学习框架常用模块数据集存取图片数据处理库 —— PILOS 模块实例 Tensorboard 记录机器学习的过程Transform 进行图像变换数据集的下载DataLoaderModule 自定义网络前向传播卷积层卷积简单应用 最大池化非线性层线性层 简单的整合基于现有网络…

FPGA的 基本结构(Xilinx 公司Virtex-II 系列FPGA )

以Xilinx 公司Virtex-II 系列FPGA 为例&#xff0c;其基本结构由下图所示。它是主要由两大部分组成&#xff1a;可编程输入/输出&#xff08;Programmable I/Os&#xff09;部分和内部可配置&#xff08;Configurable Logic&#xff09;部分。 可编程输入/输出&#xff08;I/Os…

【Elasticsearch】批量操作:优化性能

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编程,高并发设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s,热衷于探…

C++、Haskell 和 Rust 三种语言实现 Faster Suffix Sort 算法的比较

对 C、Haskell 和 Rust 三种语言实现 Faster Suffix Sort 算法的比较&#xff1a; 1. 编程效率 C&#xff1a; 优点&#xff1a;C 提供了丰富的标准库&#xff0c;如 std::sort&#xff0c;可以方便地结合自定义比较函数对后缀数组进行排序。使用 Lambda 表达式可以简洁地实现…

校园跑腿小程序---轮播图,导航栏开发

hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生…

uniapp实现H5页面内容居中与两边留白,打造类似微信公众号阅读体验

在 UniApp 中&#xff0c;由于需要兼容多端应用&#xff0c;我们通常使用 rpx 作为尺寸单位。然而&#xff0c;在某些情况下&#xff0c;如需要实现内容居中且两边留白时&#xff0c;直接使用 rpx 可能会带来一些限制。这时&#xff0c;我们可以考虑使用 px 或 rem 等单位&…

【Uniapp-Vue3】pages.json页面路由globalStyle的属性

项目的全局配置在pages.json中。 一、导航栏设置 二、下拉刷新设置 下拉就可以看到设置的样式 三、上拉触底 这个页面中&#xff0c;向下滑动页面到底部就会输出“到底了” 现在将触底距离设置为500 走到半路就会输出“到底了”

Type-C双屏显示器方案

在数字化时代&#xff0c;高效的信息处理和视觉体验已成为我们日常生活和工作的关键需求。随着科技的进步&#xff0c;一款结合了便携性和高效视觉输出的设备——双屏便携屏&#xff0c;逐渐崭露头角&#xff0c;成为追求高效工作和娱乐体验人群的新宠。本文将深入探讨双屏便携…

Linux下部署Redis(本地部署超详细)

非docker 1、下载Redis 历史版本&#xff1a; http://download.redis.io/releases 我的&#xff1a; http://download.redis.io/releases/redis-7.0.5.tar.gz 2.安装教程 1.Redis是基于c语言编写的需要安装依赖&#xff0c;需要安装gcc yum install gcc-c 2.查看gcc版…

使用 Multer 上传图片到阿里云 OSS

文件上传到哪里更好&#xff1f; 上传到服务器本地 上传到服务器本地&#xff0c;这种方法在现今商业项目中&#xff0c;几乎已经见不到了。因为服务器带宽&#xff0c;磁盘 IO 都是非常有限的。将文件上传和读取放在自己服务器上&#xff0c;并不是明智的选择。 上传到云储存…

UE5 打包项目

UE5 打包项目 flyfish 通过 “文件”->“打开项目”&#xff0c;然后在弹出的对话框中选择项目文件&#xff08;通常是以.uproject为后缀的文件&#xff09; 选择目标平台&#xff1a; 在 UE5 主界面中&#xff0c;找到 “平台”&#xff08;Platforms&#xff09;。根据…

自然语言转 SQL:通过 One API 将 llama3 模型部署在 Bytebase SQL 编辑器

使用 Open AI 兼容的 API&#xff0c;可以在 Bytebase SQL 编辑器中使用自然语言查询数据库。 出于数据安全的考虑&#xff0c;私有部署大语言模型是一个较好的选择 – 本文选择功能强大的开源模型 llama3。 由于 OpenAI 默认阻止出站流量&#xff0c;为了简化网络配置&#…

杭州铭师堂的云原生升级实践

作者&#xff1a;升学e网通研发部基建团队 公司介绍 杭州铭师堂&#xff0c;是一个致力于为人的全面发展而服务的在线教育品牌。杭州铭师堂秉持“用互联网改变教育&#xff0c;让中国人都有好书读”的使命&#xff0c;致力于用“互联网教育”的科技手段让更多的孩子都能享有优…

STM32 FreeRTOS移植

目录 FreeRTOS源码结构介绍 获取源码 1、 官网下载 2、 Github下载 源码结构介绍 源码整体结构 FreeRTOS文件夹结构 Source文件夹结构如下 portable文件夹结构 RVDS文件夹 MemMang文件夹 FreeRTOS在基于寄存器项目中移植步骤 目录添加源码文件 工程添加源码文件 …

可以进行重复测量的方差分析的AI agent

可以进行重复测量的方差分析的AI agent 前几天做了机器学习的AI agent&#xff0c;把一个糖尿病机器学习模型采用API的形式接入到LLM模型中&#xff0c;结合LLM的智能性和机器学习模型的准确性&#xff0c;利用两者的有点&#xff0c;有可以避免两者的缺点&#xff0c;是一条合…