Vue教程04:现代Js与函数、数组、时间进阶
本节课继续学习javascript进阶内容!
本文目标
通过本文的学习,我们将:
- 了解现代
javascript
的常用简化操作,了解新的方法和数据结构; - 学习函数、数组的进阶知识,包括一等公民、闭包、数组转换方法等难点;
- 熟悉数字、日期、计时器的使用方法。
现代Js
拆包(Destructuring)
什么是拆包?拆包是将数组或对象中的值解构并赋值到独立的变量中,使代码更简洁和易读。
先来看一个直观易懂的例子:
1 | //数组拆包 |
等号前面是括号,里面对应要瓜分原对象的元素的名称。反正就是有这么个倒反天罡的意思在这儿就对了。
当然,用拆包还有一些很花的玩法,比如:
跳过元素
1 | let [main, , secondary] = [1,2,3]; |
交换变量
1 | // ...... |
嵌套解构
1 | const nested = [2, 4, [5, 6]]; |
最最常见的应用场景就是:当一个函数的返回对象是一个键值对或者多个值时,用拆包去处理它会大大简化代码流程!
示例:
1 | const restaurant = { |
*扩散算子与剩余算子(…)
没错,这两货的语法都是使用 ...
, 但是它们出现的位置和功能截然不同:
- 扩展运算符(spread) 用于展开数组或对象。
应用场景:合并数组或对象
1 | const user = { name: 'John', age: 28 }; |
- 剩余参数(rest) 用于将多个独立的参数组合为数组。
应用场景:在不确定形参数量时使用效果极佳
1 | function calculateTotalPrice(...prices) { |
虽然它们只占了很短的篇幅,但是实际开发中它们几乎到处都在。所以,罚你再读一遍!😈😈😈
运算符缩写
这一部分你会看见很多老朋友,咱们会一笔带过;当然也有新同学要重点介绍,比如空值合并运算符(??
),还有||=
、&&=
之类的缝合怪。
短路运算符
||
或
||
从左到右依次检查每个值并返回第一个为真的值。
1 | console.log(3 || 'Jonas'); // 输出: 3 |
&&
与
&&
从左到右依次检查每个值并返回第一个为假的值。
1 | console.log(0 && 'Jonas'); // 输出: 0 |
空值合并运算符(??
)
空值合并运算符(??
)用于判断值是否为 null
或 undefined
,如果是,则返回右侧的值。
它与 ||
的不同在于: ||
会将 0
或空字符串 ''
视为假值,而 ??
不会。
示例:
1 | restaurant.numGuests = 0; |
在这段代码中,numGuests
的值为 0
。使用 ||
运算符会将 0
当作假值返回 10
,而使用 ??
运算符则会保留 0
的值,因为 0
不属于 null
或 undefined
。
逻辑赋值运算符
其实就是条件判断+赋值呗。。。😅
||=
运算符(或赋值)
||=
运算符用于在左侧值为假(false
、0
、null
、undefined
或 ''
)时,将右侧值赋给左侧变量。
示例:
1 | const rest1 = { name: 'Capri', numGuests: 0 }; |
&&=
运算符(与赋值)
&&=
运算符用于在左侧值为真时,将右侧值赋给左侧变量。这常用于仅在属性已存在的情况下进行更新。
示例:
1 | const rest1 = { name: 'Capri' }; |
??=
运算符(空值赋值)
??=
运算符用于在左侧值为 null
或 undefined
时,将右侧值赋给左侧变量。
示例:
1 | const rest1 = { name: 'Capri', numGuests: 0 }; |
for-of循环
在某些情况下,我们不仅需要数组的每一项内容,还需要每一项的索引。通过 for-of
循环和数组的 entries()
方法,我们可以同时获取到数组的索引和元素:
1 | const menu = ['Pasta', 'Pizza', 'Salad', 'Soup']; |
由于entries方法已经创造了新的数组且为保持原数组完整,通常要加上const
又比如说,我们可以使用 for-of
循环结合 spread
运算符,将两个数组合并并进行遍历:
1 | const restaurant = { |
可选链(?.)
?.
是 JavaScript 中一个非常实用的运算符,用于安全地访问对象的嵌套属性、方法和数组元素。它允许在访问对象属性时,不会因为属性不存在而引发错误。这对处理复杂或不确定结构的对象非常有用。
object.property?.subProperty
,它表达的意思是:
- 如果前面的属性不存在,它将返回
undefined
而不会报错; - 如果存在,继续执行
subProperty
。
1 | const restaurant = { |
配合上前面的空值合并运算符(??
)和循环,还能玩的更花:
示例:检查每天的营业时间
1 | const days = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']; |
Set和Map是现代Js中新出现的两种内置数据类型。它们都可迭代,即都可以在循环中被loop。学习它们时,请熟悉它们的功能并了解其和Array、Object的区别。
Set
Set
是一个无重复值的数据结构,一般来说的用法都是用来对数组去重的。
当创造的Set中有重复值时,Set会自动忽略:
1 | const ordersSet = new Set(['Pasta', 'Pizza', 'Pizza', 'Risotto', 'Pasta']); |
常用操作:
**
size
**:获取Set
的大小。**
has
**:检查某个值是否存在于Set
中。**
add
**:向Set
中添加一个新元素。**
delete
**:删除某个元素。
1 | console.log(ordersSet.size); // 3 |
Set的运用其实并没有很多,反而是Map确确实实弥补了对象的键值只能是String类型的不足,因此出场率更高。
Map
Map
是键值对的集合,其中键可以是任意数据类型。相较于对象,Map
的键不限于字符串和符号,可以是函数、对象、数组等。
1 | const rest = new Map(); |
链式操作
我们可以连续使用 set
方法实现链式操作。
1 | rest |
常用操作
set
:设置键值对。get
:根据键取值。**
has
**:检查Map
中是否存在指定的键。**
delete
**:删除指定键的键值对。**
size
**:获取Map
的大小。
1 | console.log(rest.get('name')); // Classico Italiano |
*转换对象和 Map
可以将对象转为 Map
,或将 Map
转为数组。
1 | // 对象转 Map |
总结:数据类型对比
高效处理String
这里将要介绍五花八门的String方法。对此,你只需要略微了解,然后在恰当的时机查询或使用它们即可,不用死记硬背(❁´◡`❁)
唯一需要警觉的是:请时刻注意这个方法是不是改变了原数组,还是新创建了一个处理后的数组?
为了让字符串操作更高效,JavaScript提供了一系列内置方法,用于分割、拼接、格式化、替换和查找等操作。以下是常用字符串操作方法及其应用示例。
基础字符串操作
获取字符和长度
使用字符串索引可以获取特定位置的字符,length
属性则返回字符串长度。
1 | const airline = 'TAP Air Portugal'; |
查找字符位置
indexOf
和 lastIndexOf
方法用于查找字符或子字符串的起始位置。
1 | console.log(airline.indexOf('r')); // 6 |
截取子字符串
使用 slice
方法截取字符串的一部分,支持负数索引。
1 | console.log(airline.slice(4)); // Air Portugal |
示例:检查座位是否为中间座位
1 | const checkMiddleSeat = function (seat) { |
字符串格式化
大小写转换
toLowerCase
和 toUpperCase
可用来进行大小写转换。
1 | const passenger = 'jOnAS'; |
去除空格
trim
去除字符串首尾的空格,非常适合处理用户输入。
1 | const loginEmail = ' Hello@Jonas.Io \n'; |
查找和替换
替换字符
使用 replace
和正则表达式替换字符串中的字符。
1 | const priceGB = '288,97£'; |
示例:替换所有出现的子字符串
1 | const announcement = 'All passengers come to boarding door 23. Boarding door 23!'; |
判断字符串包含
includes
、startsWith
和 endsWith
可以检查字符串中是否包含特定的子字符串。
1 | const plane = 'Airbus A320neo'; |
分割与拼接
分割字符串
split
方法可以将字符串分割成数组。
1 | console.log('a+very+nice+string'.split('+')); // ['a', 'very', 'nice', 'string'] |
拼接字符串
join
方法将数组中的元素拼接成字符串。
1 | const [firstName, lastName] = 'Jonas Schmedtmann'.split(' '); |
示例:将每个单词首字母大写
1 | const capitalizeName = function (name) { |
填充和重复
填充字符串
padStart
和 padEnd
用于在字符串两侧填充字符。
1 | const message = 'Go to gate 23!'; |
示例:隐藏信用卡号码
1 | const maskCreditCard = function (number) { |
重复字符串
repeat
可以将字符串重复多次。
1 | const message2 = 'Bad weather... All Departures Delayed... '; |
示例:显示排队的飞机数量
1 | const planesInLine = function (n) { |
总结
方法 | 功能说明 | 示例 |
---|---|---|
length |
获取字符串长度 | 'B737'.length → 4 |
[index] |
获取特定位置的字符 | 'A320'[1] → '3' |
indexOf |
查找子字符串的第一次出现位置 | 'TAP Air Portugal'.indexOf('r') → 6 |
lastIndexOf |
查找子字符串的最后一次出现位置 | 'TAP Air Portugal'.lastIndexOf('r') → 10 |
slice |
截取子字符串 | 'TAP Air Portugal'.slice(4, 7) → 'Air' |
toLowerCase |
转换为小写 | 'JonAS'.toLowerCase() → 'jonas' |
toUpperCase |
转换为大写 | 'Jonas'.toUpperCase() → 'JONAS' |
trim |
去除首尾空格 | ' Hello '.trim() → 'Hello' |
replace |
替换子字符串 | '288,97£'.replace('£', '$') → '288,97$' |
replaceAll |
替换所有出现的子字符串 | 'door door'.replaceAll('door', 'gate') → 'gate gate' |
includes |
检查字符串是否包含子字符串 | 'Airbus A320'.includes('A320') → true |
startsWith |
检查字符串是否以指定子字符串开头 | 'Airbus A320'.startsWith('Airb') → true |
endsWith |
检查字符串是否以指定子字符串结尾 | 'Airbus A320neo'.endsWith('neo') → true |
split |
分割字符串成数组 | 'a+nice+string'.split('+') → ['a', 'nice', 'string'] |
join |
将数组元素拼接成字符串 | ['a', 'nice', 'string'].join(' ') → 'a nice string' |
padStart |
在字符串开头填充指定字符 | 'Go to gate 23!'.padStart(20, '+') → '++++++Go to gate 23!' |
padEnd |
在字符串末尾填充指定字符 | 'Go to gate 23!'.padEnd(20, '+') → 'Go to gate 23!++++++' |
repeat |
重复字符串多次 | 'All flights delayed... '.repeat(3) → All flights delayed... All flights delayed... All flights delayed... |
函数进阶
什么是一等公民(first-class citizen)?
一等公民(First-Class Citizen)是指在一个编程语言中,具有与其他数据类型相同地位和功能的数据类型。在JavaScript中,函数可以作为变量赋值、作为参数传递、作为返回值返回,以及可以作为对象的属性等。
我倒是感觉这个名字起的不太恰当,或者说和意思恰恰相反。原来函数这玩意儿挺高大上的,你这么一搞那我和Number还有什么区别?你什么档次还敢和我坐一桌?😡😡😡😡
开玩笑的。把函数作为一等公民能有以下几点好处:
- 函数可作为变量
- 函数作为参数
- 函数作为返回值
这是Javascript
自己最明显的特征,也是其函数式编程思想的基础。
*回调函数(Callback Functions)
在回调函数的使用中,通常一个函数会接受另一个函数作为参数并在合适的时机执行它。我们把作为参数的函数称为回调函数。
基本用法:
1 | function greet(name) { |
说实话,在这个概念出现之前咱们早就用过不知道多少次了。比如,在事件监听中:
1 | document.querySelector('button').addEventListener('click', function () { |
只是当时没有点破而已。也许你现在会更加通透一些?
立即执行函数
立即执行函数表达式(Immediately Invoked Function Expression, IIFE)是一种特殊的函数表达方式,用于定义并立即执行一个函数。常用于在 JavaScript 中创建一个局部作用域,以避免变量污染全局作用域,尤其在有私有数据的情况下十分有用。
IIFE 主要有两种写法:
匿名函数 IIFE 使用
()
包裹函数定义,并紧随一对()
以立即执行。1
2
3
4(function () {
console.log('This will never run again');
const isPrivate = 23; // 局部作用域
})();箭头函数 IIFE 形式简洁。
1
(() => console.log('This will ALSO never run again'))();
IIFE 特点:
- 立即执行:定义时立即执行,只会运行一次。
- 局部作用域:通过 IIFE 创建的局部变量不会污染全局作用域。
**闭包
太好了,是闭包!我们没救了😫😫😫
作为国内大厂面试的高频必问考点之一,闭包的含金量自然不必多言;也有许多人认为,这就是Javascript中最难理解的概念。那么在本章,我们将亲手拆解属于闭包的谜团,帮助你彻底厘清闭包!
闭包奇怪在哪儿?
首先需要明确,闭包并不是我们可以手动执行的,它是程序内部自动发生的操作。因此,我们在这里先写一些代码来模拟闭包的环境:
1 | const secureBooking = function(){ |
在这段代码中,secureBooking
作为函数也返回了一个函数;而booker
成功的调用了 secureBooking
并获取secureBooking
返回的结果,即return
后的这个函数。因此,现在的booker
也是一个函数。
那么当我们在全局作用域调用booker
时,会发生什么呢?
显然,这会让程序在secureBooking
函数的作用域中创建一个 passengerCount
的变量,随后把函数返回给booker
;
这个时候,secureBooking
的调用其实就已经结束了,其也从回调栈中弹出。
请注意:从事实上来说,secureBooking
已经不在活跃环境中,就是已经消失了。这点很重要。
现在,从理论上讲,passengerCount
变量应该也随着secureBooking
一起消失了对吧?然而事实却是:
passengerCount
仍然在随着booker
的调用而增加!
这就是闭包的奇怪之处。简单来说,就是死去的变量开始攻击我。
工作原理
所以我们的核心目标就是搞清楚,booker
是如何获取到passengerAccount
的。
其实核心就是一句话:
任意函数都有权利获取创造它环境时的执行上下文(execution context)。
在这个案例中,由于返回函数在secureBooking
中被创造,因此它就有权利访问secureBooking
函数块域中的所有值,其中包括passengerAccount
变量。而这也正是所谓”闭包”概念的原理。
是的,通过闭包,即使作用域已经被销毁,当函数被调用时仍然可以永远携带被创造环境中的变量。它的优先级是高于作用域链的。也由于闭包的存在,函数不会轻易地失去与变量的链接,变量会永远存在于函数的诞生地。
现在我们回顾闭包的几种严格定义:
当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行的。
闭包是指有权访问另一个函数作用域中变量的函数。
怎么样,是不是感觉很轻松就理解了呢?🤗🤗🤗
数组进阶
我们继续来补充处理数组的各种进阶方法。
at
方法
at()
方法是 ECMAScript 2022 (ES13) 新增的一个字符串和数组方法,允许通过负整数索引从末尾访问数组或字符串的元素。负整数索引使得访问最后几个元素变得更加简洁,避免了使用 length - 1
这种方式。如果索引超出数组的范围,返回 undefined
。
语法
1 | arr.at(index); |
示例:
1 | const arr = [10, 20, 30, 40, 50]; |
forEach
遍历
与传统的 for
循环不同,forEach()
方法可以对数组中的每一个元素执行给定的回调函数。
语法
1 | arr.forEach(callback(currentValue, index, array) { |
callback
: 用来处理数组元素的回调函数。currentValue
: 当前正在处理的元素。index
: 当前元素的索引(可选)。array
: 原始数组本身(可选)。
示例:
示例 1:基本用法
1 | const numbers = [1, 2, 3, 4, 5]; |
示例 2:带索引的遍历
1 | const fruits = ['apple', 'banana', 'cherry']; |
示例 3:箭头函数和 forEach
的结合
1 | const colors = ['red', 'green', 'blue']; |
比较 forEach
与 for
循环
特性 | for 循环 |
forEach |
---|---|---|
可提前退出 | 可以使用 break 或 return 退出循环 |
无法中途退出,无法使用 break |
适用场景 | 对数组元素进行复杂处理、需要控制循环流程 | 适合对所有元素执行相同操作 |
返回值 | 可以返回任意值 | 没有返回值,总是返回 undefined |
执行性能 | 通常比 forEach 快 |
在性能要求较高的场景中不推荐使用 |
可操作索引和元素 | 手动访问索引、元素和条件判断 | 回调函数中自动访问元素及其索引 |
*三幻神:数组转换的三种方式
map
方法
map()
方法用于数组的转换,它会创建一个新数组,其中每个元素是调用回调函数后返回的结果。map()
不会修改原始数组。
语法
1 | const newArray = arr.map(callback(currentValue, index, array) { |
callback
: 回调函数,接收三个参数:currentValue
: 当前元素的值。index
: 当前元素的索引(可选)。array
: 原始数组(可选)。
使用示例
示例 1:将数字数组的每个元素乘以 2
1 | const numbers = [1, 2, 3, 4, 5]; |
示例 2:提取对象数组中的某个字段
1 | const users = [ |
filter
方法
filter()
方法用于筛选数组中的元素,返回一个新数组,包含满足条件的所有元素。filter()
不会修改原始数组。
语法
1 | const newArray = arr.filter(callback(currentValue, index, array) { |
callback
: 回调函数,接收三个参数:currentValue
: 当前元素的值。index
: 当前元素的索引(可选)。array
: 原始数组(可选)。
使用示例
示例 1:筛选出大于 2 的数字
1 | const numbers = [1, 2, 3, 4, 5]; |
示例 2:筛选出年龄大于 30 的用户
1 | const users = [ |
reduce
方法
reduce()
方法用于将数组中的所有元素通过累加或其他计算方式,最终计算成一个单一的值。它接收一个回调函数,该回调函数会对数组中的每个元素执行累积操作。
语法
1 | const result = arr.reduce(callback(accumulator, currentValue, index, array) { |
callback
: 回调函数,接收四个参数:accumulator
: 累计器,记录当前的计算结果,最终返回给reduce()
。currentValue
: 当前元素的值。index
: 当前元素的索引(可选)。array
: 原始数组(可选)。
initialValue
: 可选,设置accumulator
的初始值。如果省略,则第一次迭代时accumulator
为数组的第一个元素。
使用示例
示例 1:求数组的和
1 | const numbers = [1, 2, 3, 4, 5]; |
示例 2:合并字符串
1 | const words = ['Hello', 'world', 'from', 'JavaScript']; |
示例 3:统计数组中每个元素的出现次数
1 | const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']; |
小结
方法 | 返回值 | 描述 | 适用场景 |
---|---|---|---|
map() |
新数组 | 对数组的每个元素执行相同操作并返回新数组 | 数组元素转换、字段提取 |
filter() |
新数组 | 筛选数组中符合条件的元素 | 数组筛选、获取符合条件的元素 |
reduce() |
单一值(任何类型) | 将数组所有元素累加、合并成一个单一值 | 数组求和、生成对象或其他数据形式 |
补充:函数式编程思想与链式方法
函数式编程 + 链式方法就像搭积木,简单的积木组合起来可以创造出强大的功能,同时还能保持代码的整洁和优雅。
比如说,现在我们有一个需求:从一个包含用户年龄的数组中,筛选出大于 18 岁的用户年龄,然后将它们加倍,最后计算它们的总和。
传统的写法就是:
1 | const ages = [12, 19, 7, 25, 34]; |
它的问题是非常的冗长而且不直观,使用了额外的数组 adults
和 doubled
来 存储中间结果。
而函数式 + 链式方法呢?
1 | const ages = [12, 19, 7, 25, 34]; |
高下立判。
接下来又变得很简单了,你只需要:
1.知道有这么个方法;
2.知道这个方法大概干什么活。
留个印象就可以了。大不了忘了再查呗~
find
& findIndex
方法
find
方法
find()
方法返回数组中第一个满足条件的元素。如果没有找到,返回 undefined
。
作用: 查找数组中符合条件的第一个元素。
示例:
1 | const numbers = [5, 12, 8, 130, 44]; |
findIndex
方法
findIndex()
方法返回数组中第一个满足条件的元素的索引。如果没有找到,返回 -1
。
作用: 查找数组中符合条件的第一个元素的索引。
示例:
1 | const numbers = [5, 12, 8, 130, 44]; |
some
& every
方法
some
方法
some()
方法测试数组中的某些元素是否满足指定条件。只要有一个元素符合条件,就返回 true
,否则返回 false
。
作用: 检查数组中是否至少有一个元素满足条件。
示例:
1 | const numbers = [5, 12, 8, 130, 44]; |
every
方法
every()
方法测试数组中的所有元素是否都满足指定条件。只有所有元素都符合条件时,才返回 true
,否则返回 false
。
作用: 检查数组中的所有元素是否都满足条件。
示例:
1 | const numbers = [5, 12, 8, 130, 44]; |
flat
& flatMap
方法
flat
方法
flat()
方法用于将多维数组“拉平”,即将嵌套的数组转换为单一层级的数组。
作用: 展平多维数组。
示例:
1 | const nestedArray = [1, [2, 3], [4, [5, 6]]]; |
flat()
方法可以接收一个参数,表示要展开的层级数,默认为 1
。
flatMap
方法
flatMap()
方法首先对数组中的每个元素应用一个映射函数,然后将结果展开成一个新的数组。它相当于先做 map()
,再做 flat()
。
作用: 对数组中的每个元素先进行映射操作,再将结果展平。
示例:
1 | const arr = [1, 2, 3, 4]; |
flatMap()
方法会将每个元素的返回值“拉平”到一个新数组中。
sort
方法
sort()
方法用于对数组的元素进行排序。排序是 原地修改 的,这意味着会更改原始数组。默认排序顺序是按照 字符串 Unicode 编码 升序。如果需要自定义排序,可以传入比较函数。
语法
1 | arr.sort([compareFunction]); |
compareFunction
(可选):用来定义排序顺序的函数。- 如果
compareFunction(a, b)
返回值小于 0,则a
会排在b
前。 - 如果返回值等于 0,则两者位置不变。
- 如果返回值大于 0,则
b
会排在a
前。
- 如果
默认排序
默认按照字符串 Unicode 排序。
1 | const arr = [100, 50, 2, 10]; |
自定义排序
示例 1:数字排序(升序和降序)
1 | // 结合语法部分仔细品味: |
示例 2:字符串排序
1 | const fruits = ['Banana', 'Apple', 'Orange']; |
示例 3:按对象字段排序
1 | const users = [ |
总结
- 默认按照字符串 Unicode 排序,数字排序需要自定义比较函数。
- 排序会修改原数组,因此需谨慎使用。
- 常用于对数组元素进行排序(数字、字符串、对象等)。
from
方法
Array.from()
方法用于从 类数组对象 或 可迭代对象 创建一个新的数组实例。
语法(看不懂可以先跳):
1 | Array.from(arrayLike, [mapFunction, thisArg]); |
arrayLike
:必须。类数组对象或可迭代对象。mapFunction
(可选):一个函数,用于对每个元素执行操作。thisArg
(可选):执行回调时的this
值。
基本用法
示例 1:从类数组对象创建数组
1 | const str = 'hello'; |
示例 2:从 arguments
创建数组
1 | function test() { |
*示例 3:转换 HTML 集合
1 | const listItems = document.querySelectorAll('li'); |
这种方法常用于处理 DOM 元素集合(如
NodeList
)、生成指定长度的数组、对每个元素进行映射操作等。
小案例
将一组对象按某个字段排序,并从中提取某些属性:
1 | const users = [ |
*总结:23种数组处理方法
数字、时间、日期与计时器
数字相关操作
数字转换与检查
数字转换:
1
2console.log(Number('23')); // 转换字符串为数字,输出:23
console.log(+'23'); // 简写形式,同样输出:23解析字符串中的数字:
1
2console.log(Number.parseInt('30px', 10)); // 解析为 30
console.log(Number.parseFloat(' 2.5rem ')); // 解析为 2.5检查数字有效性:
1
2console.log(Number.isNaN(+'20X')); // 检查是否为 NaN
console.log(Number.isFinite(23 / 0)); // 检查是否为有限数
通常来说,由于无穷大与无穷小并不属于NaN,因此isNaN方法的判定非常有可能是不严谨的。因此,isFinite方法会在实际场景中更常用一些。
数学操作与取整
数学函数:
1
2
3console.log(Math.sqrt(25)); // 开平方
console.log(Math.max(5, '23')); // 最大值
console.log(Math.PI * 10 ** 2); // 计算圆面积取整方法:
1
2
3console.log(Math.round(23.9)); // 四舍五入
console.log(Math.floor(23.9)); // 向下取整
console.log(Math.trunc(23.9)); // 去掉小数部分生成随机数:
1
2
3const randomInt = (min, max) =>
Math.floor(Math.random() * (max - min + 1)) + min;
console.log(randomInt(10, 20)); // 范围内随机整数
余数操作
检查是否为偶数:
1
2const isEven = n => n % 2 === 0;
console.log(isEven(8)); // true
大数字处理 (BigInt)
1 | console.log(123456789012345678901234567890n); // 超大数字 |
日期与时间操作
创建日期对象
- 不同方式创建日期:
1
2
3
4
5const now = new Date();
console.log(now);
const future = new Date(2037, 10, 19, 15, 23); // 年月日时分
console.log(future);
日期操作
获取日期信息:
1
2
3console.log(future.getFullYear()); // 获取年份
console.log(future.getMonth()); // 获取月份 (0-11)
console.log(future.toISOString()); // 转为 ISO 格式设置日期:
1
2future.setFullYear(2040);
console.log(future); // 更新年份日期差计算:
1
2
3const calcDaysPassed = (date1, date2) =>
Math.abs(date2 - date1) / (1000 * 60 * 60 * 24);
console.log(calcDaysPassed(new Date(2037, 3, 4), new Date(2037, 3, 14)));
*计时器与时间间隔
设置定时器
延时执行:
1
2
3
4
5
6
7const ingredients = ['cheese', 'pepperoni'];
const pizzaTimer = setTimeout(
(ing1, ing2) => console.log(`Here is your pizza with ${ing1} and ${ing2}`),
3000,
...ingredients
);
console.log('Waiting...');取消定时器:
1
if (ingredients.includes('pepperoni')) clearTimeout(pizzaTimer);
循环执行
每秒显示当前时间:
1
2
3
4setInterval(() => {
const now = new Date();
console.log(now);
}, 1000);
请注意,若定时器后还有代码,则后面的代码不会等待计时完成后再执行,而是立即执行。详细的原理要等到下一篇讲解。