JavaScript的内置类
# 原始类型的包装类
JavaScript的原始类型并非是对象类型,理论来说他们是没有办法获取属性或者调用方法的。在实际开发中经常会看到下面的操作
var message = 'Hello World'
var words = message.split(' ')
var length = message.length
var num = 2.54432
num = num.toFixed(2)
2
3
4
5
6
可以做这种操作的原因
- 原始类型是简单的值,默认并不能调用属性和方法
- 因为JavaScript为了可以使其可以获取属性和调用方法,对其封装了对应的包装类型
常见的包装类型有:String、Number、Boolean、Symbol、BigInt类型
# 包装类型的使用过程
默认情况下,当我们调用了一个原始类型的属性或者方法时,会执行如下操作
- 根据原始值,创建一个原始类型对应的包装类型对象
- 调用对应的属性和方法,返回一个新的值
- 创建的包装类对象被销毁
- 通常JavaScript引擎会进行很多的优化,它可以跳过创建包装类的过程在内部直接完成属性的获取或者方法的调用
比如自己可以创建一个包装类的对象
name1是字面量的创建方式,name2是new创建对象的方式
var name1 = 'zs'
var name2 = new String('zs')
console.log(typeof name1) // string
console.log(typeof name2) // object
console.log(name1 === name2) // false
2
3
4
5
注意:null、undefined没有任何的方法,也没有对应的对象包装类
# Number类
Number类型有一个对应的数字包装类型Number。
# Number类型的补充
- Number.MAX_SAFE_INTEGER:JavaScript 中最大的安全整数 (2^53 - 1);
- Number.MIN_SAFE_INTEGER:JavaScript 中最小的安全整数 -(2^53 - 1)
# Number实例方法补充
- toString(base),将数字转成字符串,并且按照base进制进行转化
- base 的范围可以从 2 到 36,默认情况下是 10;
- 如果是直接对一个数字操作,需要使用..运算符;
- toFixed(digits),格式化一个数字,保留digits位的小数;
- digits的范围是0到20(包含)之间;
# Number类方法补充
- Number.parseInt(string[, radix]),将字符串解析成整数,也有对应的全局方法parseInt;
- Number. parseFloat(string),将字符串解析成浮点数,也有对应的全局方法parseFloat;
# Number MDN文档
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number
# Math对象
JavaScript还提供了一个Math对象可以对数字进行处理;Math是一个内置对象(不是一个构造函数),它拥有一些数学常数属性和数学函数方法
# 常见属性
- Math.PI:圆周率
# 常见方法
Math.floor: 向下舍入取整
Math.ceil:向上舍入取整
Math.round:四舍五入取整
Math.random: 生成 0~1 的随机数(包含0, 但是不包含1)
- 生成[a, b)的随机数, y = a, x = b - a Math.floor(Math.random() * 45) + 5
Math.pow(x, y) 返回x的y次幂
# Math MDN 文档
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math
# String类
在实际开发中经常需要对字符串进行各种操做,String类提供了对应的属性和方法
# 基本使用
# String常见属性
- length: 获取字符串的长度
# String操作
访问字符串
- 通过字符串索引:str[0]
- 通过str.charAt(pos)方法
- 上面这两个方法的区别是所用的方式没有找到会返回undefined,而charAt()没有找到会返回空字符串。
# 字符串遍历
- 普通for循环
- for...of遍历
# 修改字符串
字符串具有不可变性,因此字符串在定义后是不可修改的,
var message = 'Hello World'
message[1] = 'A'
console.log(message) // Hello World
2
3
上面这段代码操作没有任何意义,因此在改变很多字符串的操作中,都是生产了一个新的字符串,比如修改字符串大小写的两个方法
- toLowerCase():将所有字符转成小写
- toUpperCase():将所有字符转成大写
# 查找字符串
在开发中经常会有在一个字符串中查找另一个字符串的操作,String提供了如下方法
方法一:查询字符串的位置 str. indexOf(searchValue [,fromIndex])
- 从fromIndex开始,查找searchValue的索引
- 如果没有找到,那么返回-1
- 有一个相似的方法,叫
lastIndexOf
,从最后开始查找
console.log(message.indexOf('name',18))
方法二:是否包含字符串 str.includes(searchString[, position])
- 从position位置开始查找searchString,根据情况返回true或false
- 这是ES6新增的方法
console.log(message.includes('zs'))
# 开头和结尾
方法三:以xxx开头 str.startsWith(searchString[,position])
- 从position位置开始,判断字符串是否以searchString开头
- 这是ES6新增的方法
方法四:以xxx结尾 str.endsWith(searchString[,position]) ES6新增
在length长度内,判断字符串是否以searchString结尾
方法五:替换字符串 str.replace(regexp|substr, newSubStr|function) ES6新增
- 查找对应的字符串,并且使用新的字符串进行替换
- 也可以传入一个正则表达式来查找,也可以传入一个函数来替换
# 获取子字符串
方法六:获取子字符串
方法 | 选择方式 | 负值参数 |
---|---|---|
slice(start, end) | 从start到end(不含end) | 允许 |
substring(start, end) | 从start到end(不含end) | 负值代表0 |
substr(start, length),避免使用,使用 substring() (opens new window) 替代它。 | 从start开始获取长为length的字符串 | 允许start为负数 |
实际开发中推荐使用slice方法,该方法不会改变原本的字符串并返回一个新的字符串。slice参数
- start,从索引0开始提取原字符串中的字符,如果为负数,会被当做
strLength + start
看待,strLength
是字符串的长度,开始位置从后向前数。 - end,在该索引处结束提取字符串,如果省略该参数,slice会一直提取到字符串末尾,如果参数为负数,那么被看成
strLength + end
,结尾位置从后向前数。
方法七:拼接字符串 str.concat(str2,[,...strN])
console.log('Hello'.concat('World'))
console.log('Hello', ' ', 'World', '!')
2
方法八:删除首尾空格 str.trim()
console.log(' sss '.trim())
方法九:字符串分割 srt.split([separator[,limit]])
- separator: 以什么字符串进行分割,也可以是一个正则表达式
- limit:限制返回的片段数量
MDN文档地址
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String
# 数组
数组是一种有序列的集合,里面的元素按照某一个顺序来排列,这个有序的集合可以通过索引来获取
数组和对象都是一种可以保存多个数据的的数据结构
# 数组的创建方式
var arr1 = []
var arr2 = new Array()
var arr3 = ['a','b']
var arr4 = new Array('abc','cba')
2
3
4
5
在创建数组时设置数组的长度
var arr5 = new Array(5)
# 数组的基本操作
访问数组中的元素
通过[]访问
arr.at(i)
- 如果 i >= 0,则与arr[i]完全相同
- 对于i为负数的情况,它则从数组的尾部向前数
console.log(arr[0]) console.log(arr.at(-1))
1
2
修改数组中的元素
arr[0] = 'w'
删除和添加元素虽然也可以通过索引来直接操作,但是实际开发中很少这样操作
# 数组的添加、删除方法
在数组的尾端添加或删除元素
- push 在末端添加元素
- pop 从末端去除一个元素
arr.push('abc', 'cba')
arr.pop()
2
在数组的首端添加或删除元素
- shift 取出队列首端的一个元素,整个数组元素向前移动
- unshift 在首端添加元素,整个其它数组元素向后移动
arr.unshift('c')
arr.shift()
2
提示
pop/push方法运行的比较快,而shift/unshift比较慢
arr.splice
方法是处理数组的利器,可以实现添加、删除和替换元素
语法结构
arr.splice(start[, deleteCouint[, item1 [,item2[, ...]]]])
- 从start位置开始,处理数组中的元素
- deleteCount 要删除的元素的个数,如果为0或者负数表示不删除
- item1, item2, ... 在添加元素时需要添加的元素
arr.splice(1, 1) // 删除一个元素
arr.splice(1, 0, 'a', 'b') // 新增两个元素
arr.splice(1, 2, 'c', 'd') // 替换两个元素
2
3
注意
这个方法会修改原数组
# length属性
length属性用于获取数组的长度,当我们修改数组的时候,length属性会自动更新
length属性是可写的,如果手动增加一个大于默认length的数值,那么会增加数组的长度。如果减少它,数组就会被截断
var arr = ['a', 'b', 'c']
arr.length = 10
console.log(arr) // ['a', 'b', 'c', empty × 7]
arr.length = 2
console.log(arr) // ['a', 'b']
2
3
4
5
提示
索引清空数组最简单的方法就是 arr.length = 0
# 数组的遍历
普通for循环
for(var i = 0; i < arr.length; i++){
console.log(arr[i])
}
2
3
for...in遍历,获取索引值
for(var index in arr) {
console.log(arr[index])
}
2
3
for...of遍历,获取到每一个元素
for(var item of arr) {
console.log(item)
}
2
3
# 数组其它方法
# slice方法
arr.slice()
方法,用于对数组进行截取(类似于字符串的slice方法)
语法:arr.slice([begin[, end]])
,包含begin元素,但是不包含end元素。
console.log(arr.slice(2, 3))
# concat方法
arr.concat
方法创建一个新的数组,其中包含来其于其它数组和其他项目的值
var new_array = old_array.concat(value1[, value2[,...[, valueN]]])
var newArr = arr.concat(['abc', 'cba'], 'nba')
# join方法
arr.join
方法,将一个数组的所有元素连接成一个字符串并返回这个字符串
arr.join[aeparator]
console.log(arr.join('-'))
# 数组查找元素
arr.indexOf
方法,查找某个元素的索引
arr.indexOf(searchElement[, fromIndex])
- 从fromIndex开始查找,如果找到返回对应的索引,没有找到返回-1.
- 也有对应的从最后位置开始查找的
lastIndexOf
方法
arr.includes
方法,判断数组是否包含某个元素
arr.includes(valueToFind [, fromIndex])
- 从索引from开始搜索item,如果找打则返回true,如果没有找到,返回false
find
和findIndex
直接查找元素或者元素的索引(ES6之后新增的方法)
var stu = students.find(function(item, index, arr){
return item.id === 100
})
console.log(stu)
2
3
4
# 数组的排序 sort、reverse
# sort方法
sort
方法也是一个高阶函数,用于对数组进行排序,并且生成一个排序后的新数组
arr.sort([compareFunction])
- 如果compareFunction(a, b)小于0,那么a会被排列到b的前面
- 如果compareFunction(a, b)等于0,a和b的相对位置不变
- 如果compareFunction(a, b)大于0,b会被排列在a的前面
- 谁小谁在前面。
var newStr = students.sort(function(item1, item2){
return item2.age - item1.age // 结果是item1 - item2 的结果的反转,是一种降序排序
})
console.log(newStr)
2
3
4
reverse
方法,将数组中的元素位置颠倒,并返回该数组
# 数组的其它高阶方法
arr.forEach
// 存在传入第二个参数
arr.forEach(function(item){
console.log(item, this) // 第二个参数, 这里的this就是指向传入的第二个参数 {name: 'zs'}
}, {name: 'zs'})
2
3
4
5
- 遍历数组,并且让数组中每一个元素都执行一次对应的方法
arr.map
- map() 方法创建一个新的数组
- 这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成
arr.filter
- filter() 方法创建一个新数组
- 新数组中只包含每个元素调用函数返回true的元素
arr.reduce()
/**
* preVal 前一次的返回值,第一次默认是0,因此reduce第二个位置传入一个0表示初始值,如果没有传值,会默认将数 * 组中的第一个位置的值当做初始值
* item 当前值
* 最后一次执行的时候, preVal + item 会作为reduce的返回值
**/
arr.reduce(function(preVal, item){
return preVal + item
}, 0)
2
3
4
5
6
7
8
- 用于计算数组中素有元素的和
- 对数组中的每个元素按序执行一个由开发者提供的reducer函数
- 每一次运行reducer会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值
# 手动实现forEach函数
例如定义一个js数组
var strArr = ["abc", "123", "cba"];
想要在函数中遍历并显示当前遍历的结果,当前遍历的索引以及当前遍历的数组
# 方案一
定义一个高阶函数,函数中传入一个回调函数,每次循环数组都打印当前循环的值,当前的索引,以及原数组
function myForEach(fn) {
for(var i = 0; i < strArr.length; i++) {
fn(strArr[i], i, strArr)
}
}
myForEach(function(item, index, arr){
console.log(item, index, arr)
})
2
3
4
5
6
7
8
9
这种实现方式与要遍历的数组存在很强的耦合性,并不能通用,也没有实现类似于forEach
函数在数组上可以直接使用的方式。
# 方案二
定义一个高阶函数,同时传入一个函数以及要遍历的数组
function myForEach(fn, arr){
for(var i = 0; i < arr.length; i++){
fn(arr[i], i, arr)
}
}
myForEach(function(item, index, arr){
console.log(item, index, arr)
}, nameStr)
2
3
4
5
6
7
8
这种方式减少了参数和函数的耦合性,但是依然没有实现forEach
可以直接使用的方式。
# 方案三
给数组上绑定一个方法,在函数内部使用this
关键字访问调用者,可以实现类似于forEach
的形式
strArr.myForEach = function(fn){
for(var i = 0; i < this.length; i++){
fn(this[1], i, this)
}
}
strArr.myForEach(function(item, index, arr){
console.log(item, index, arr)
})
2
3
4
5
6
7
8
9
这种方法虽然实现了类似于forEach
的形式,但是每次遍历一个新的数组都要给数组绑定一个这样的方法,通用性很差
# 方案四
将自己定义的方法绑定到Array
对象的原型上,那么只要是数组就可以调用
Array.prototype.myForEach = function(fn){
for(var i = 0; i < this.length; i++){
fn(this[i], i, this)
}
}
strArr.myForEach(function(item, index, arr){
console.log(item, index, arr)
})
2
3
4
5
6
7
8
如此就完美实现了forEach
的效果。
# 手动实现find函数
Array.prototype.myFind = function(fn){
var item = undefined
for(var i = 0; i < this.length; i++){
var isFind = fn(this[i], i, this)
if(isFind) {
// item = this[i]
// break;
return this[i]
}
}
return item
}
// 如果没有找到, find函数返回的是undefined
var stuArr = [
{id: 100, name: 'zs'},
{id: 101, name: 'ls'}
]
stuArr.myFind(function(item ,index, arr){
if(item.id === 100) return true;
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 时间的表示
最开始制定的标准时间是本初子午线时间称之为(GMT),但是公转有一定的误差,也会造成GMT的时间有一定的误差,于是就有了根据原子钟计算的标准时间UTC。GMT目前仍然在使用,而UTC是标准的时间。
# Date对象
在JavaScript中使用Date来表示和处理时间,Date的构造函数有如下使用
new Date()
new Date(value)
new Date(dateString)
new Date(year, monthIndex [,day [, hours[, minutes[, seconds[, milliseconds]]]]])
2
3
4
// 不传入任何参数
var date1 = new Date()
// 传入毫秒的时间戳
var date2 = new Date(1000)
// 传入日期
var date3 = new Date('2022-08-08')
// 传入 年 月 日 时 分 秒 毫秒
var date4 = new Date(2022, 08, 08, 08, 08, 08, 08)
2
3
4
5
6
7
8
# dateString时间的表示方式
日期的表示方式有两种: RFC 2822标准或者ISO 8601标准,默认打印的时间格式是RFC 2811标准的
也可以将其转化成为ISO 8601标准的
- YYYY:年份,0000 - 9999
- MM:月份,01 - 12
- DD:日,01 - 31
- T:分隔日期和时间,没有特殊含义,可以省略
- HH:小时, 00 - 24
- mm:分钟,00 - 59
- ss:秒,00 ~ 59
- .sss:毫秒
- Z:时区
# Date获取信息的方法
可以从Date对象中获取各种详细的信息
- getFullYear(): 获取年份
- getMonth(): 获取月份(0 - 11)
- getDate(): 获取当月的具体日期,从1到31
- getHours(): 获取小时
- getMinutes(): 获取分钟
- getSeconds(): 获取秒
- getMilliseconds(): 获取毫秒
获取某周中的星期几
- getDay(): 获取一周中的第几天, 从0(星期日)到6(星期六)
# Date设置信息
- setFullYear(year, [month], [date])
- setMonth(month, [date])
- setDate(date)
- setHours(hour, [min], [sec], [ms])
- setMinutes(min, [sec], [ms])
- setSeconds(sec, [ms])
- setMilliseconds(ms)
- setTime(milliseconds)
# Date获取Unix时间戳
Unix 时间戳:它是一个整数值,表示自1970年1月1日00:00:00 UTC以来的毫秒数。
在JavaScript中,我们有多种方法可以获取当前时间戳:
- new Date().getTime()
- new Date().valueOf()
- +new Date()
- Date.now()
获取到Unix时间戳之后,我们可以利用它来测试代码的性能:
var startTime = Date.now()
for(var i = 0; i < 1000; i++){
console.log(i)
}
var endTime = Date.now()
console.log(endTime - startTime)
2
3
4
5
6
# Date.parse方法
Date.parse(str) 方法可以从一个字符串中读取日期,并且输出对应的Unix时间戳。
Date.parse(str) :
- 作用等同于 new Date(dateString).getTime() 操作;
- 需要符合 RFC2822 或 ISO 8601 日期格式的字符串;比如YYYY-MM-DDTHH:mm:ss.sssZ
- 其他格式也许也支持,但结果不能保证一定正常;
- 如果输入的格式不能被解析,那么会返回NaN;
var time1 = Date.parse('2022-08-08T08:08:08.666z')
console.log(time1) // 1659946088666 获取到Unix时间戳
2
# 时间格式化方法
/**
* @param1 时间戳
* @param2 时间格式
**/
function formatDate(time, fmt) {
let date = new Date(time)
if(/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
}
let o = {
'M+': date.getMonth + 1,
'd+': date.getDate(),
'h+': date.getHours()
'm+': date.getMinutes(),
's+': date.getSeconds()
}
for(let k in o){
if(new RegExp(`${k}`).test(fmt)){
let str = o[k] + ''
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? str:padLeftZero(str))
}
}
return fmt;
}
function padLeftZero(str){
return ('00'+str).substr(str.length)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29