1. JavaScript常见的内置类
1.0 原始类型的包装类
- JavaScript的原始类型并非对象类型,所以从理论上来说,它们是没有办法获取属性或者调用方法的。
- 但是,在开发中会看到,我们会经常这样操作:
- 那么,为什么会出现这样奇怪的现象呢?(悖论)
- 原始类型是简单的值,默认并不能调用属性和方法;
- 这是因为JavaScript为了可以使其可以获取属性和调用方法,对其封装了对应的包装类型;
- 常见的包装类型有:String、Number、Boolean、Symbol、BigInt类型
1.1 包装类型的使用过程
-
默认情况,当我们调用一个原始类型的属性或者方法时,会进行如下操作:
- 根据原始值,创建一个原始类型对应的包装类型对象;
- 调用对应的属性或者方法,返回一个新的值;
- 创建的包装类对象被销毁;
- 通常JavaScript引擎会进行很多的优化,它可以跳过创建包装类的过程在内部直接完成属性的获取或者方法的调用。通俗的说就是引擎完成一系列的包装类操作
-
我们也可以自己来创建一个包装类的对象:
- name1是字面量(literal)的创建方式,name2是new创建对象的方式;
-
注意事项:null、undefined没有任何的方法,也没有对应的“对象包装类”;
1.2 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(包含)之间;
- 方法一:toString(base),将数字转成字符串,并且按照base进制进行转化
-
Number类方法补充:
- 方法一:Number.parseInt(string[, radix]),将字符串解析成整数,也有对应的全局方法parseInt;
- 方法二:Number. parseFloat(string),将字符串解析成浮点数,也有对应的全局方法parseFloat;
<script>
// Number构造函数 -> window.Number
// var num = 123 // new Number(num)
// 类属性
// Number中本身是有自己的属性
console.log(Number.MAX_VALUE)
console.log(Number.MIN_VALUE)
// integer: 整数
console.log(Number.MAX_SAFE_INTEGER)
console.log(Number.MIN_SAFE_INTEGER)
// 对象的方法
// toString(base),base表示进制
var num = 1000
console.log(num.toString(), typeof num.toString())
console.log(num.toString(2))
console.log(num.toString(8))
console.log(num.toString(16))
// console.log(123..toString(2))
// toFixed的使用(重要)
var pi = 3.1415926
console.log(pi.toFixed(3))
// 类的方法
// parseInt
// parseFloat
// 整数: 123
// 浮点数: 小数 123.321
var num1 = "123.521"
console.log(Number(num1).toFixed(0))
console.log(Number.parseInt(num1))
console.log(Number.parseFloat(num1))
// window对象上面
console.log(parseInt(num1))
console.log(parseFloat(num1))
//模拟系统定义的类方法,Number.parseInt(num1)方法的原理
// function HYNumber() {
// }
// HYNumber.parseInt2 = function() {
// }
//parseInt(num1)方法实现的原理
// window.parseInt2 = HYNumber.parseInt2
// console.log(window.parseInt2 === HYNumber.parseInt2)
console.log(parseInt === Number.parseInt)
</script>
1.3 Math对象
- 在除了Number类可以对数字进行处理之外,JavaScript还提供了一个Math对象。
- Math是一个内置对象(不是一个构造函数),它拥有一些数学常数属性和数学函数方法;
- Math常见的属性:
- Math.PI:圆周率,约等于 3.14159;
- Math常见的方法:
- Math.floor:向下舍入取整
- Math.ceil:向上舍入取整
- Math.round:四舍五入取整
- Math.random:生成0~1的随机数(包含0,不包含1)
- Math.pow(x, y):返回x的y次幂
<script>
console.log('Number的类型',typeof Number) // function
// var num = new Number()
// Math -> 对象
// window/obj/console
console.log('Math的类型',typeof Math) //Obj
// var math = new Math()
// Math对象的属性
// console.log(Math.PI)
// Math对象的方法
// var num = 3.55
// console.log(Math.floor(num)) // 3
// console.log(Math.ceil(num)) // 4
// console.log(Math.round(num)) // 4
// 另外方法
// random: 随机生成 [0, 1)
console.log(Math.random())
// 需求: [5~50)的随机数
// [a, b)
// y = a
// x = b - a
// Math.floor(Math.random() * x) + y
// for (var i = 0; i < 1000; i++) {
// var randomNum = Math.floor(Math.random() * 45) + 5
// console.log(randomNum)
// }
// Math.pow(x, y)
console.log(Math.pow(2, 4))
</script>
1.4 String类的补充-基本使用
- 在开发中,我们经常需要对字符串进行各种各样的操作,String类提供给了我们对应的属性和方法。
- String常见的属性:
- length:获取字符串的长度;
- String也有很多常见的方法和操作,我们来进行学习。
- 操作一:访问字符串的字符
- 使用方法一:通过字符串的索引 str[0]
- 使用方法二:通过str.charAt(pos)方法
- 它们的区别是索引的方式没有找到会返回undefined,而charAt没有找到会返回空字符串;
- 练习:字符串的遍历
- 方式一:普通for循环
- 方式二:for…of遍历
<script>
var message = "Hello World"
// 1.属性: length
console.log(message.length)
// 2.访问字符串中某个位置的字符
// console.log(message[4])
// console.log(message.charAt(4))
// console.log(message[20])
// console.log(message.charAt(20))
// 3.字符串的遍历
// for普通遍历
for (var i = 0; i < message.length; i++) {
console.log(message[i])
}
// for..of的遍历 -> 迭代器
// 目前可迭代对象: 字符串/数组
// 对象是不支持for..of
// String对象内部是将字符串变成了一个可迭代对象
for (var char of message) {
console.log(char)
}
</script>
1.5 String 类的补充-修改字符串
-
字符串的不可变性
- 字符串在定义后是不可以修改的,所以下面的操作是没有任何意义的;
-
所以,在我们改变很多字符串的操作中,都是生成了一个新的字符串
- 比如改变字符串大小的两个方法
- toLowerCase():将所有的字符转成小写;
- toUpperCase() :将所有的字符转成大写;
1.6 String 类的补充-查找字符串
- 在开发中我们经常会在一个字符串中查找或者获取另外一个字符串,String提供了如下方法:
-
方法一:查找字符串位置 str.indexof(searchvalue ,[fromindex])
- 从fromIndex开始,查找searchValue的索引;
- 如果没有找到,那么返回-1,搜索到, 搜索字符串所在索引位置;
- 有一个相似的方法,叫lastIndexOf,从最后开始查找(用的较少)
-
方法二:是否包含字符串 str.includes(searchString,position)
- 从position位置开始查找searchString, 根据情况返回 true 或 false
- 这是ES6新增的方法;
-
<script>
var message = "my name is why."
var name = "why"
// 判断一个字符串中是否有另外一个字符串
// 1.indexOf(searchString, fromIndex)
/*
index:
情况一: 搜索到, 搜索字符串所在索引位置
情况二: 没有搜索到, 返回-1
*/
var index = message.indexOf(name)
if (message.indexOf(name) !== -1) {
console.log("message中包含name")
} else {
console.log("message不包含name")
}
// 2.includes: ES6中新增一个方法, 就是用来判断包含关系
if (message.includes(name)) {
console.log("message中包含name")
}
</script>
1.7 String 类的补充-开头和结尾
-
方法三以xxx开头 str.startswith(searchString,[position])
- 从position位置开始,判断字符串是否已xxxx开头
- ES6新方法
-
方法四以xxx结尾 str.endswith(searchString,[length])
- 从length长度内,,判断字符串是否已xxxx结尾
- ES6新方法
-
方法五 替换字符串 str.replace()
- 查找到对应的字符串,并且使用新的字符串进行替代;
- 这里也可以传入一个正则表达式来查找,也可以传入一个函数来替换;
<script>
var message = "my name is why."
var name = "why"
// 3.startsWith: 是否以xxx开头
if (message.startsWith("my")) {
console.log("message以my开头")
}
// 4.endsWith: 是否以xxx结束
if (message.endsWith("why")) {
console.log("message以why结尾")
}
// 5.replace 替换字符串
var newMessage = message.replace("why", "kobe")
console.log(message)
console.log(newMessage)
var newName = "kobe"
var newMessage = message.replace("why", function() {
return newName.toUpperCase()
})
console.log(newMessage)
</script>
1.8 String类的补充-获取子字符串
-
方法八:获取子字符串
-
推荐开发中使用slice
1.9 String 类的补充-其他方法
- 拼接字符串 str.concat();
- 删除收尾空格 str.trim();
- 分割字符串 str.split();
<script>
var str1 = "Hello"
var str2 = "World"
var str3 = "kobe"
// 1.字符串拼接
// +
// var newString = str1 + str2 + str3
// console.log(newString)
// concat方法: 链式调用
var newString2 = str1.concat(str2).concat(str3)
var newString3 = str1.concat(str2, str3, "abc", "cba")
console.log(newString2)
console.log(newString3)
// 2.删除收尾的空格
console.log(" why abc ".trim())
// 3.字符串切割split
var message = "abc-cba-nba-mba"
var items = message.split("-")
var newMessage = items.join("*")
console.log(newMessage)
</script>
1.10 认识数组 Array
- 什么是数组(Array)呢?
- 对象允许存储键值集合,但是在某些情况下使用键值对来访问并不方便;
- 比如说一系列的商品、用户、英雄,包括HTML元素,我们如何将它们存储在一起呢?
- 这个时候我们需要一种有序的集合,里面的元素是按照某一个顺序来排列的;
- 这个有序的集合,我们可以通过索引来获取到它;
- 这个结构就是数组(Array);
- 数组和对象都是一种保存多个数据的数据结构,在后续的数据结构中我们还会学习其他结构;
- 我们可以通过[]来创建一个数组:
- 数组是一种特殊的对象类型;
1.11 数组的创建方式
-
创建一个数组有两种方式
-
下面的方法是在创建一个数组时,设置数组的长度(很少用)
-
数组元素从 0 开始编号(索引index)
-
我们先来学习一下数组的基本操作:
- 访问数组中的元素;
- 修改数组中的元素;
- 增加数组中的元素;
- 删除数组中的元素;
1.12 数组的基本操作
- 访问数组中的元素:
- 通过中括号[]访问
- arr.at(i):
- ✓ 如果 i >= 0,则与 arr[i] 完全相同。
- ✓ 对于 i 为负数的情况,它则从数组的尾部向前数。
- 修改数组中的元素
- 删除和添加元素虽然也可以通过索引来直接操作,但是开发中很少这样操作。
1.13 数组的添加,删除方法
- 在数组的尾端添加或删除元素:
- push 在末端添加元素.
- pop 从末端取出一个元素.
- 在数组的首端添加或删除元素
- shift 取出队列首端的一个元素,整个数组元素向前前移动;
- unshift 在首端添加元素,整个其他数组元素向后移动;
1.14 数组的添加,删除方法
-
如果我们希望在中间某个位置添加或者删除元素应该如何操作呢?
-
arr.splice 方法可以说是处理数组的利器,它可以做所有事情:添加,删除和替换元素。
-
**arr.splice的语法结构如下:
**- 从start位置开始,处理数组中的元素;
- deleteCount:要删除元素的个数,如果为0或者负数表示不删除;
- item1, item2, …:在添加元素时,需要添加的元素;
-
注意:这个方法会修改原数组
<script>
// 3. 在任意位置添加/删除/替换元素
var names = ["abc", "cba", "nba", "mba", "abcd"]
// 参数一: start, 从什么位置开始操作元素
// 参数二: deleteCount, 删除元素的个数
// 3.1.删除元素
// names.splice(1, 2)
// console.log(names)
// 3.2.新增元素
// deleteCount: 0, 后面可以添加新的元素
// names.splice(1, 0, "why", "kobe")
// console.log(names)
// 3.3.替换元素
names.splice(1, 2, "why", "kobe", "james")
console.log(names)
</script>
1.15 length 属性
- length属性用于获取数组的长度:
- 当我们修改数组的时候,length 属性会自动更新。
- length 属性的另一个有意思的点是它是可写的。
- 如果我们手动增加一个大于默认length的数值,那么会增加数组的长度。
- 但是如果我们减少它,数组就会被截断。
- 所以,清空数组最简单的方法就是:arr.length = 0;。
1.16 数组的遍历
- 普通for循环遍历
- for in 遍历 获取到的索引值
- for of遍历 获取到每一个元素
<script>
var names = ["abc", "cba", "nba", "mba"]
// 2.数组的遍历
// 2.1. 普通的for循环
for (var i = 0; i < names.length; i++) {
console.log(names[i])
}
// 2.2. for..in
for (var index in names) {
console.log(index, names[index])
}
// 2.3. for..of
for (var item of names) {
console.log(item)
}
</script>
1.17 数组方法-slice,cancat,join
- arr.slice 方法:用于对数组进行截取(类似于字符串的slice方法)。
- 包含bigin元素,但是不包含end元素;
- arr.concat方法:创建一个新数组,其中包含来自于其他数组和其他项的值。
- arr.join方法: 将一个数组的所有元素连接成一个字符串并返回这个字符串。
1.17 数组方法-查找元素
-
arr.indexOf方法: 查找某个元素的索引
- 从fromIndex开始查找,如果找到返回对应的索引,没有找到返回-1;
- 也有对应的从最后位置开始查找的 lastIndexOf 方法
-
arr.includes方法:判断数组是否包含某个元素
- 从索引 from 开始搜索 item,如果找到则返回 true(如果没找到,则返回 false)。
◼ find 和 findIndex 直接查找元素或者元素的索引(ES6之后新增的语法)
- 从索引 from 开始搜索 item,如果找到则返回 true(如果没找到,则返回 false)。
<script>
var students = [
{ id: 100, name: "why", age: 18 },
{ id: 101, name: "kobe", age: 30 },
{ id: 102, name: "james", age: 25 },
{ id: 103, name: "why", age: 22 }
]
var stu = students.find(function(item) {
//当返回true时,stu将拿到条件成立的item
if (item.id === 101) return true
})
console.log(stu)
</script>
1.18 数组的排序-sort/reverse
-
sort方法也是一个高阶函数,用于对数组进行排序,并且生成一个排序后的新数组:
- 如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 前面;
- 如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变;
- 如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 前面;
- 也就是说,谁小谁排在前面;
-
reverse()方法将数组中元素的位置颠倒,并返回该数组
<script>
// var nums = [20, 4, 10, 15, 100, 88]
// // sort: 排序
// nums.sort(function(item1, item2) {
// // item1和item2进行比较
// // 返回是 整数
// // 谁小谁在前
// // return item1 - item2
// return item2 - item1
// })
// console.log(nums)
// console.log(nums.reverse())
// 复杂类型的排序
var students = [
{ id: 100, name: "why", age: 18 },
{ id: 101, name: "kobe", age: 30 },
{ id: 102, name: "james", age: 25 },
{ id: 103, name: "curry", age: 22 }
]
students.sort(function(item1, item2) {
return item1.age - item2.age
})
console.log(students)
</script>
1.19 数组的其他高阶方法
- arr.forEach
- 遍历数组,并且让数组中每一个元素都执行一次对应的方法;
- arr.map
- map() 方法创建一个新数组;
- 这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成
- arr.filter
- filter() 方法创建一个新数组;
- 新数组中只包含每个元素调用函数返回为true的元素;
- arr.reduce
- 用于计算数组中所有元素的总和;
- 对数组中的每个元素按序执行一个由您提供的 reducer 函数;
- 每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值;
<script>
// 1.forEach函数
var names = ["abc", "cba", "nba", "mba"]
// 三种方式, 新增一种方式
names.forEach(function(item) {
console.log(item, this)
}, { name: "why" })
// 2.filter函数: 过滤
// var nums = [11, 20, 55, 100, 88, 32]
// 2.1. for循环实现
// var newNums = []
// for (var item of nums) {
// if (item % 2 === 0) {
// newNums.push(item)
// }
// }
// 2.2. filter实现
// var newNums = nums.filter(function(item) {
// return item % 2 === 0
// })
// console.log(newNums)
// 3.map函数: 映射
// var nums = [11, 20, 55, 100, 88, 32]
// var newNums = nums.map(function(item) {
// return item * item
// })
// console.log(newNums)
// 4.reduce
// var nums = [11, 20, 55, 100, 88, 32]
// var result = 0
// for (var item of nums) {
// result += item
// }
// console.log(result)
// 第一次执行: preValue->0 item->11
// 第二次执行: preValue->11 item->20
// 第三次执行: preValue->31 item->55
// 第四次执行: preValue->86 item->100
// 第五次执行: preValue->186 item->88
// 第六次执行: preValue->274 item->32
// 最后一次执行的时候 preValue + item, 它会作为reduce的返回值
// initialValue: 初始化值, 第一次执行的时候, 对应的preValue
// 如果initialValue没有传呢?
// var result = nums.reduce(function(preValue, item) {
// console.log(`preValue:${preValue} item:${item}`)
// return preValue + item
// }, 0)
// console.log(result)
// reduce练习
// var products = [
// { name: "鼠标", price: 88, count: 3 },
// { name: "键盘", price: 200, count: 2 },
// { name: "耳机", price: 9.9, count: 10 },
// ]
// var totalPrice = products.reduce(function(preValue, item) {
// return preValue + item.price * item.count
// }, 0)
// console.log(totalPrice)
// 综合练习:
var nums = [11, 20, 55, 100, 88, 32]
// 过滤所有的偶数, 映射所有偶数的平方, 并且计算他们的和
// var total = nums.filter(function(item) {
// return item % 2 === 0
// }).map(function(item) {
// return item * item
// }).reduce(function(preValue, item) {
// return preValue + item
// }, 0)
// console.log(total)
// var total = nums.filter(item => item % 2 === 0)
// .map(item => item * item)
// .reduce((preValue, item) => preValue + item, 0)
// console.log(total)
</script>
1.20 创建Date对象
- 在JavaScript中我们使用Date来表示和处理时间。
- Date的构造函数有如下用法:
- Date的构造函数有如下用法:
1.21 dateString时间的表示方式
-
日期的表示方式有两种:RFC 2822 标准 或者 ISO 8601 标准。
-
默认打印的时间格式是RFC 2822标准的:
-
我们也可以将其转化成ISO 8601标准的:
- YYYY:年份,0000 ~ 9999
- MM:月份,01 ~ 12
- DD:日,01 ~ 31
- T:分隔日期和时间,没有特殊含义,可以省略
- HH:小时,00 ~ 24
- mm:分钟,00 ~ 59
- ss:秒,00 ~ 59
- .sss:毫秒
- Z:时区
1.22 Date获取信息的方法
- 我们可以从Date对象中获取各种详细的信息:
- getFullYear():获取年份(4 位数);
- getMonth():获取月份,从 0 到 11;
- getDate():获取当月的具体日期,从 1 到 31(方法名字有点迷);
- getHours():获取小时;
- getMinutes():获取分钟;
- getSeconds():获取秒钟;
- getMilliseconds():获取毫秒;
- 获取某周中的星期几:
- getDay():获取一周中的第几天,从 0(星期日)到 6(星期六);
1.23 Date设置信息的方法
- 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)
- 了解:我们可以设置超范围的数值,它会自动校准。
1.24 Date获取Unix时间戳
- Unix 时间戳:它是一个整数值,表示自1970年1月1日00:00:00 UTC以来的毫秒数。
- 在JavaScript中,我们有多种方法可以获取这个时间戳:
- 方式一:new Date().getTime()
- 方式二:new Date().valueOf()
- 方式三:+new Date()
- 方式四:Date.now()
- 获取到Unix时间戳之后,我们可以利用它来测试代码的性能:
1.25 Date.parse方法
- Date.parse(str) 方法可以从一个字符串中读取日期,并且输出对应的Unix时间戳。
- Date.parse(str) :
- 作用等同于 new Date(dateString).getTime() 操作;
- 需要符合 RFC2822 或 ISO 8601 日期格式的字符串;
- 比如YYYY-MM-DDTHH:mm:ss.sssZ
- 其他格式也许也支持,但结果不能保证一定正常;
- 如果输入的格式不能被解析,那么会返回NaN;