1.内置对象
对象,是任何一个开发者都无法绕开和逃避的话题,她似乎有些深不可测,但如此伟大和巧妙的存在,一定值得你去摸索、发现、征服。
我们都知道,JavaScript有3大对象,分别是本地对象、内置对象和宿主对象。
在此引用ECMA-262(ECMAScript的制定标准)对于他们的定义:
-
本地对象
- 与宿主无关,独立于宿主环境的ECMAScript实现提供的对象。
- 简单来说,本地对象就是 ECMA-262 定义的类(引用类型)。
- 这些引用类型在运行过程中需要通过new来创建所需的实例对象。
- 包含:
Object、Array、Date、RegExp、Function、Boolean、Number、String等。
-
内置对象
- 与宿主无关,独立于宿主环境的ECMAScript实现提供的对象。
- 在 ECMAScript 程序开始执行前就存在,本身就是实例化内置对象,开发者无需再去实例化。
- 内置对象是本地对象的子集。
- 包含:
Global和Math。 - ECMAScript5中增添了
JSON这个存在于全局的内置对象。
-
宿主对象
- 由 ECMAScript 实现的宿主环境提供的对象,包含两大类,一个是宿主提供,一个是自定义类对象。
- 所有非本地对象都属于宿主对象。
- 对于嵌入到网页中的JS来说,其宿主对象就是浏览器提供的对象,浏览器对象有很多,如
Window和Document等。 - 所有的
DOM和BOM对象都属于宿主对象。
1. 常见内置类
1.1 原始类型的包装类
- javascript的原始类型并非对象类型,所以从理论上来说,它们是没有办法获取属性或者调用方法的。
- 但是,在开发中会看到,我们会经常这样操作:
- 那么,为什么会出现这样奇怪的现象呢?(悖论)
- 始类型是简单的值,默认并不能调用属性和方法;
- 这是因为JavaScript为了可以使其可以获取属性和调用方法,对其封装了对应的包装类型;
- 常见的包装类型有:
String、Number、Boolean、Symbol、BigInt类型 name.split(" ")拿基本数据类型去调用属性或者方法,js引擎会在底层作做一件事情,
-
- 首先会根据原始类型,创建一个对象,再将运来的数据传递进去。
-
- 创建的对象里面有对应的属性,所以可以调name.length和name.split(" ")
-
- 调用完获取对应的结果之后,js引擎,会自动将内存回收。name回到原来的基本数据类型
var name = "Hello World"
var height = 1.8888888
function String(str) {
this.str = str
this.length = 11
this.split = function() {
}
}
// 在调用原始类型的属性或者方法时, 内部的操作 name = new String(name)
console.log(name.length)
// name.split(" ")拿基本数据类型去调用属性或者方法,js引擎会在底层作做一件事情,
// 1. 首先会根据原始类型,创建一个对象,再将运来的数据传递进去。
// 2. 创建的对象里面有对应的属性,所以可以调name.length和name.split(" ")
// 3. 调用完获取对应的结果之后,js引擎,会自动将内存回收调。name回到原来的基本数据类型
console.log(name.split(" "))
console.log(height.toFixed(2))
1.2 包装类型的使用过程
- 默认情况,当我们调用一个原始类型的属性或者方法时,会进行如下操作:
- 根据原始值,创建一个原始类型对应的包装类型对象;
- 调用对应的属性或者方法,返回一个新的值;
- 创建的包装类对象被销毁;
- 通常JavaScript引擎会进行很多的优化,它可以跳过创建包装类的过程在内部直接完成属性的获取或者方法的调用。
- 我们也可以自己来创建一个包装类的对象:
- name1是字面量(literal)的创建方式,name2是new创建对象的方式;
- 注意事项:null、undefined没有任何的方法,也没有对应的“对象包装类”;
1.3 包装类型,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文档:文档地址
1.4 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次幂
// 需求: [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)
}
1.5 String类的补充
- 基本使用
- String常见的属性: length:获取字符串的长度;
- String也有很多常见的方法和操作,我们来进行学习。
- 操作一:访问字符串的字符
- 使用方法一:通过字符串的索引 str[0]
- 使用方法二:通过str.charAt(pos)方法
- 它们的区别是索引的方式没有找到会返回undefined,而charAt没有找到会返回空字符串;
- 修改字符串
- 字符串的不可变性: 字符串在定义后是不可以修改的,所以下面的操作是没有任何意义的;
- 所以,在我们改变很多字符串的操作中,都是生成了一个新的字符串;
- 比如改变字符串大小的两个方法
- toLowerCase():将所有的字符转成小写;
- toUpperCase() :将所有的字符转成
3. 查找字符串
- 在开发中我们经常会在一个字符串中查找或者获取另外一个字符串,String提供了如下方法:
- 方法一:查找字符串位置
- 从fromIndex开始,查找searchValue的索引;
- 如果没有找到,那么返回-1;
- 有一个相似的方法,叫lastIndexOf,从最后开始查找(用的较少)
- 方法二:是否包含字符串
- 从position位置开始查找searchString, 根据情况返回 true 或 false
- 这是ES6新增的方法;
-
方法三:以xxx开头
-
从position位置开始,判断字符串是否以searchString开头;
-
这是ES6新增的方法,下面的方法也一样;
-
-
方法四:以xxx结尾
- 在length长度内,判断字符串是否以searchString结尾;
- 在length长度内,判断字符串是否以searchString结尾;
-
方法五:替换字符串
- 查找到对应的字符串,并且使用新的字符串进行替代;
- 这里也可以传入一个正则表达式来查找,也可以传入一个函数来替换;
-
方法八:获取子字符串
- 其他方法
2. 数组
数组和对象都是一种保存多个数据的数据结构, 我们可以通过[]来创建一个数组, 数组是一种特殊的对象类型;
2.1 数组的基本操作
- 访问数组中的元素:
- 通过中括号[]访问
- arr.at(i):
- 如果 i >= 0,则与 arr[i] 完全相同。
- 对于 i 为负数的情况,它则从数组的尾部向前数。
- 修改数组中的元素,通过下标直接修改
2.2 添加或者删除
- arr.splice 方法可以说是处理数组的利器,它可以做所有事情:添加,删除和替换元素。
-
arr.splice的语法结构如下:
- 从start位置开始,处理数组中的元素;
- deleteCount:要删除元素的个数,如果为0或者负数表示不删除;
- item1, item2, ...:在添加元素时,需要添加的元素;
-
删除元素
// 3. 在任意位置添加/删除/替换元素
var names = ["abc", "cba", "nba", "mba", "abcd"]
// 参数一: start, 从什么位置开始操作元素
// 参数二: deleteCount, 删除元素的个数
// 3.1.删除元素
names.splice(1, 2)//表示从第一个位置开始删除两个元素,修改的是数组本身
console.log(names)//['abc', 'mba', 'ab
- 新增元素
// 3. 在任意位置添加/删除/替换元素
var names = ["abc", "cba", "nba", "mba", "abcd"]
// 3.2.新增元素
// deleteCount: 0, 后面可以添加新的元素
names.splice(1, 0, "aa", "bb")//表示从第一个位置,0表示不需要删除元素,新增,"aa", "bb"
console.log(names)//['abc', 'aa', 'bb', 'cba', 'nba', 'mba', 'abcd']
- 替换元素
// 3. 在任意位置添加/删除/替换元素
var names = ["abc", "cba", "nba", "mba", "abcd"]
// 3.3.替换元素
names.splice(1, 2, "aa", "bb")////表示从第一个位置,2表示需要删除2个元素,新增,"aa", "bb"
console.log(names)//['abc', 'aa', 'bb', 'mba', 'abcd']
2.3 数组的遍历
2.4 slice、cancat、 join、indexOf、includes
- arr.slice 方法:用于对数组进行截取(类似于字符串的slice方法)。
var names = ["abc", "cba", "nba", "mba", "why", "kobe"]
// 1.slice方法: 不会修改原数组
// splice有区别: splice修改原有的数组
// start 从什么位置开始
// end 结束位置, 不包含end本身
//names.slice(2)表示从第二个位置开始截取所有的数据
var newNames = names.slice(2, 4)//从第2个位置开始,截取到第四个位置(不含第四个)
console.log(newNames)
- arr.concat方法:创建一个新数组,其中包含来自于其他数组和其他项的值
var names1 = ["abc", "cba"]
var names2 = ["nba", "mba"]
var names3 = ["why", "kobe"]
var newNames2 = names1.concat(names2, names3)
console.log(newNames2)//['abc', 'cba', 'nba', 'mba', 'why', 'kobe']
- arr.join方法: 将一个数组的所有元素连接成一个字符串并返回这个字符串。
var names = ["abc", "cba", "nba", "mba", "why", "kobe"
// 3.join方法: 字符串split
console.log(names.join("-"))//abc-cba-nba-mba-why-kobe
- arr.indexOf方法: 查找某个元素的索引
- 从fromIndex开始查找,如果找到返回对应的索引,没有找到返回-1;
- 也有对应的从最后位置开始查找的
// 1.数组中存放的是原始类型
var names = ["abc", "cba", "nba", "mba"]
// 1.1. indexOf
// 可以找到, 返回对应的索引
// 没有找到, 返回-1
console.log(names.indexOf("nbb"))//-1
-
lastIndexOf 方法
-
arr.includes方法:判断数组是否包含某个元素
- 从索引 from 开始搜索 item,如果找到则返回 true(如果没找到,则返回 false)。
- find 和 findIndex 直接查找元素或者元素的索引(ES6之后新增的语法)
sort方法也是一个高阶函数,用于对数组进行排序,并且生成一个排序后的新数组:
- 如果
compareFunction(a, b)小于 0 ,那么 a 会被排列到 b 前面; - 如果
compareFunction(a, b)等于 0 , a 和 b 的相对位置不变; - 如果
compareFunction(a, b)大于 0 , b 会被排列到 a 前面; - 也就是说,谁小谁排在前面;
8. reverse() 方法将数组中元素的位置颠倒,并返回该数组。
9. arr.forEach
- 遍历数组,并且让数组中每一个元素都执行一次对应的方法; 10 . arr.map
- map() 方法创建一个新数组;
- 这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成;
- arr.filter
- filter() 方法创建一个新数组;
- 新数组中只包含每个元素调用函数返回为true的元素;
- arr.reduce
- 用于计算数组中所有元素的总和;
- 对数组中的每个元素按序执行一个由您提供的 reducer 函数;
- 每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值;
// initialValue: 初始化值, 第一次执行的时候, 对应的preValue
// 如果initialValue没有传呢?
var result = nums.reduce(function (preValue, item) {
console.log(`preValue:${preValue} item:${item}`)
return preValue + item
}, 0)
console.log(result)
3.手动实现高阶函数
3.1 实现ForEach
- 版本一
function fyForEach (fn) {
for (let i = 0; i < arr.length; i++) {
fn(arr[i], i, arr)//2. 回调fn的时候,传入参数
}
}
// 1. 调用fyForEach,传入一匿名函数,在调用fyForEach函数内部会做一个for循环,重复的调用fn函数
fyForEach(function (item, index, arr) {//3. 在function接收三个参数
console.log("----", item, index, arr);
})
- 版本二,传入数组
- 版本三 添加属性
// 3. 版本三
arr.fyForEach = function (fn) {
for (let i = 0; i < this.length; i++) {
fn(this[i], i, this)//this指向调用的对象
}
}
arr.fyForEach(function (item, index, arr) {
console.log("----", item, index, arr);
})
- 版本四,给原型里面添加fyForEach
// 版本四,将fyEach添加到原型里面去
Array.prototype.fyForEach = function (fn) {
for (let i = 0; i < this.length; i++) {
fn(this[i], i, this)//this指向调用的对象
}
}
let a = ['3', 'e', 10]
a.fyForEach(function (item, index, arr) {
console.log("----", item, index, arr);
})
3.2 实现find
- 原始类型查找
// 1.原始类型的查找
var names = ["abc", "cba", "nba", "mba"]
// 原生find方法
var findName = names.find(function (item, index, arr) {
console.log(item, index, arr)
return item === "nba"
})
console.log(findName)
- 对象中查找
// 2.数组中对象类型的查找
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 findStu = students.find(function (item) {
return item.id === 101
})
console.log(findStu)
- 往原型里面添加
// 3.自己实现hyFind(百分90以上的不要求)
Array.prototype.hyFind = function (fn) {
for (var i = 0; i < this.length; i++) {
var isFlag = fn(this[i], i, this)
if (isFlag) {
return this[i]
}
}
}
var findStu = students.hyFind(function (item, index, arr) {
// console.log(item)
return item.id === 101
})
console.log(findStu)
4. 时间Date对象
4.1 时间表示的基本概念
- 我们先来了解一下时间表示的基本概念: 最初,人们是通过观察太阳的位置来决定时间的,但是这种方式有一个最大的弊端就是不同区域位置大家使用的时间是不一致的。
- 相互之间没有办法通过一个统一的时间来沟通、交流。
- 之后,人们开始制定的标准时间是英国伦敦的皇家格林威治( Greenwich )天文台的标准时间(刚好在本初子午线经过的地方),这个时 间也称之为GMT(Greenwich Mean Time)。 其他时区根据标准时间来确定自己的时间,往东的时区(GMT+hh:mm),往西的时区(GMT+hh:mm);
- 但是,根据公转有一定的误差,也会造成GMT的时间会造成一定的误差,于是就提出了根据原子钟计算的标准时间UTC(Coordinated Universal Time)
- 目前GMT依然在使用,主要表示的是某个时区中的时间,而UTC是标准的时间。
4.2 创建Date对象
<script>
// 创建Date对象的方式
// 1.没有传入任何的参数, 获取到当前时间
var date1 = new Date()
console.log(date1)
// 2.传入参数: 时间字符串
var date2 = new Date("2022-08-08")//根据“2022-08-08”字符串创建date对象
console.log(date2)
// 3.传入具体的年月日时分秒毫秒
var date3 = new Date(2033, 10, 10, 09, 08, 07, 333)
console.log(date3)
// 4.传入一个Unix时间戳
// 1s -> 1000ms
var date4 = new Date(10004343433)
console.log(date4)
</script>
- dateString时间的表示方式
2. Date获取信息的方法
我们可以从Date对象中获取各种详细的信息:
- getFullYear():获取年份(4 位数);
- getMonth():获取月份,从 0 到 11;
- getDate():获取当月的具体日期,从 1 到 31(方法名字有点迷);
- getHours():获取小时;
- getMinutes():获取分钟;
- getSeconds():获取秒钟;
- getMilliseconds():获取毫秒;
- 获取某周中的星期几: getDay():获取一周中的第几天,从 0(星期日)到 6(星期六);
- Date获取Unix时间戳
// Date对象, 转成时间戳
var date = new Date()
var date2 = new Date("2033-03-03")
// 方法一: 当前时间的时间戳
var timestamp1 = Date.now()
console.log(timestamp1)
// 方法二/三将一个date对象转成时间戳
var timestamp2 = date.getTime()
var timestamp3 = date2.valueOf()
console.log(timestamp2, timestamp3)
// 方法四: 了解
console.log(+date)
// 计算这个操作所花费的时间
var startTime = Date.now()
for (var i = 0; i < 100000; i++) {
console.log(i)
}
var endTime = Date.now()
console.log("执行100000次for循环的打印所消耗的时间:", endTime - startTime)
// 封装一个简单函数
function testPerformance(fn) {
var startTime = Date.now()
fn()
var endTime = Date.now()
}
Date.parse方法
- Date.parse(str) 方法可以从一个字符串中读取日期,并且输出对应的Unix时间戳。
- Date.parse(str) :
- 作用等同于 new Date(dateString).getTime() 操作;
- 需要符合
RFC2822或ISO 8601日期格式的字符串; - 比如YYYY-MM-DDTHH:mm:ss.sssZ
- 其他格式也许也支持,但结果不能保证一定正常;
- 如果输入的格式不能被解析,那么会返回NaN;
var timeString = "03/23/2033"
// 1.方式一:
// var date = new Date(timeString)
// var timestamp = date.getTime()
// 2.方式二:
var timestamp = Date.parse(timeString)
console.log(timestamp)