六、JavaScript常见内置类 Number/Math/String/Array/Date

2022/6/30 JS基础Number数字类型Math对象String字符串类型Array数组Date类型

# 1、原始类型的包装类

  • JavaScript的原始类型并非对象类型,所以从理论上来说,它们是没有办法获取属性或者调用方法的。
  • 但是,在开发中会看到,我们会经常这样操作:
var message = "Hello World"
var words = message.split(" ")
var length = message.length
console.log(words)//["Hello","World"]
console.log(length)//11

var num = 2.54432
num = num.toFixed(2)
console.log(num)//2.54
1
2
3
4
5
6
7
8
9
  • 那么,为什么会出现这样奇怪的现象呢?(悖论)

    • 原始类型是简单的值,默认并不能调用属性和方法;
    • 这是因为JavaScript为了可以使其可以获取属性和调用方法,对其封装了对应的包装类型;
  • 常见的包装类型有:String、Number、Boolean、Symbol、BigInt类型

# 2、包装类型的使用过程

  • 默认情况,当我们调用一个原始类型的属性或者方法时,会进行如下操作:

    • 根据原始值,创建一个原始类型对应的包装类型对象;
    • 就可以调用对应的属性或者方法,返回一个新的值;
    • 创建的包装类对象被销毁;
    • 通常JavaScript引擎会进行很多的优化,它可以跳过创建包装类的过程在内部直接完成属性的获取或者方法的调用。
  • 我们也可以自己来创建一个包装类的对象:

    • name1是字面量(literal)的创建方式,name2是new创建对象的方式;
var name1 = "why"
var name2 = new String("why")
console.log(typeof name1)//string
console.log(typeof name2)//object
console.log(name1 === name2)//false
1
2
3
4
5
  • 注意事项:null、undefined没有任何的方法,也没有对应的“对象包装类”;

# 3、Number类的补充:相关方法属性 number.prototype.toFixed()、toString(); Number.parseInt()

  • 前面我们已经学习了Number类型,它有一个对应的数字包装类型Number,我们来对它的方法做一些补充。

  • Number属性补充:

    • Number.MAX_SAFE_INTEGER:JavaScript 中最大的安全整数 (2^53 - 1);
    • Number.MIN_SAFE_INTEGER:JavaScript 中最小的安全整数 -(2^53 - 1)
  • Number实例方法补充:(在Number 的prototype的方法)

    • 方法一:toString(base),将数字转成字符串,并且按照base进制进行转化

      • base 的范围可以从 2 到 36,默认情况下是 10;
      • 注意:如果是直接对一个数字操作,需要使用..运算符;
    • 方法二:toFixed(digits),格式化一个数字,保留digits位的小数;

      • digits的范围是0到20(包含)之间;
//1、number.toString()
var num = 11
console.log(num.toString(2),typeof num.toString(2))//1011 string (返回值是2进制的字符串))

//2、number.toFixed()
var n = 1.256
console.log(n.toFixed(2))//1.26 
1
2
3
4
5
6
7
  • Number类方法补充:
    • 方法一:Number.parseInt(string[, radix]),将字符串解析成整数,也有对应的全局方法parseInt;
    • 方法二:Number. parseFloat(string),将字符串解析成浮点数,也有对应的全局方法parseFloat;
var n = '19.99a'
console.log(parseInt(n))//19
console.log(parseFloat(n))//19.99
1
2
3

# 4、Math对象:Math.floor() 、 Math.round() 、 Math.random()

  • 在除了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次幂
数字 Math.floor Math.ceil Math.round
3.1 3 4 3
3.6 3 4 4

# 5、String类的补充

# 5.1.基本使用:for / for of 循环 遍历字符串

  • 在开发中,我们经常需要对字符串进行各种各样的操作,String类提供给了我们对应的属性和方法。

  • String常见的属性:

    • length:获取字符串的长度;
  • String也有很多常见的方法和操作,我们来进行学习。

    • 操作一:访问字符串的字符
      • 使用方法一:通过字符串的索引 str[0]
      • 使用方法二:通过str.charAt(pos)方法(String实例方法)
      • 它们的区别是索引的方式没有找到会返回undefined,而charAt没有找到会返回空字符串;
var str = 'Hello World'
console.log(str[4])//o
console.log(str[20])//undefined
console.log(str.charAt(20))//"" 空字符串
1
2
3
4
  • 练习:字符串的遍历

    • 方式一:普通for循环

    • 方式二:for..of遍历

// 方式一:普通for循环
var str = "Hello"
for(var i = 0;i<str.length;i++) {
    console.log(str[i])
}

// 方式二:for..of遍历
for(var item of str) {
    console.log(item)
}

//两个方式的打印结果都是:
//> H
//> e
//> l
//> l
//> o
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 5.2.修改字符串方法 (大小写) string.prototype.toUpperCase() 、toLowerCase()

  • 字符串的不可变性:
    • 字符串在定义后是不可以修改的,所以下面的操作是没有任何意义的;
var str = "Hello"
str[1] = "W"
console.log(str)// Hello
1
2
3
  • 所以,在我们改变很多字符串的操作中,都是生成了一个新的字符串;
    • 比如改变字符串大小写的两个方法 (String实例方法)
    • toLowerCase():将所有的字符转成小写;
    • toUpperCase() :将所有的字符转成大写;
var str = "Lyk"
console.log(str.toLowerCase())//lyk
console.log(str.toUpperCase())//LYK
1
2
3

# 5.3.查找字符串方法:String.prototype.indexOf()、includes()

  • 在开发中我们经常会在一个字符串中查找或者获取另外一个字符串,String提供了如下方法:
  • 方法一:查找字符串位置 str.indexOf(searchValue[,fromIndex]) (String实例方法)
    • 从fromIndex(默认值为0)开始,查找searchValue的索引;
    • 如果没有找到,那么返回-1; 找到了则返回字符串最前面字符的索引值
    • 有一个相似的方法,叫lastIndexOf,从最后开始查找(用的较少)
var message = "my name is kobe"
console.log(message.indexOf('name',4))//-1   从索引为4,开始查找,没有找到字符串name,所以返回-1
console.log(message.indexOf('name'))//3    从头开始查找,找到了字符串name,所以返回字符串最前面字符的索引值:3
1
2
3
  • 方法二:是否包含字符串 str.includes(searchString[,position]) (String实例方法)
    • 从position位置开始查找searchString, 根据情况返回 true 或 false
    • 这是ES6新增的方法;String.prototype.includes()
var message = "my name is james"
console.log(message.includes("james"))//true
console.log(message.includes("name",4))//false
1
2
3

# 5.4.字符串方法-开头和结尾及替换:String.prototype.startsWith() 、replace()

  • 方法三:以xxx开头 str.startsWith(searchString[,position])
    • 从position位置开始,判断字符串是否以searchString开头;
    • 这是ES6新增的方法,下面的方法也一样;
var message = "my name is james"
console.log(message.startsWith('name',3))//true
console.log(message.startsWith('name',4))//false
1
2
3
  • 方法四:以xxx结尾 str.endsWith(searchString[,length])
    • 在length长度内,判断字符串是否以searchString结尾;
var message = "my name is james"
console.log(message.endsWith('name',7))//true
console.log(message.endsWith('name',8))//false
1
2
3
  • 方法五:替换字符串 str.replace(regexp | substr,newSubStr| function)
    • 查找到对应的字符串,并且使用新的字符串进行替代;
    • 这里也可以传入一个正则表达式来查找,也可以传入一个函数来替换;
    • 返回值是替换后的 新字符串
var message = "my name is james"

var str = message.replace("james","kobe")
console.log(str)//my name is kobe

str = message.replace("james",function() {
    return "curry"
})
console.log(str)//my name is curry
console.log(message)//my name is james
1
2
3
4
5
6
7
8
9
10

# 5.5.获取子字符串方法:string.prototype.slice()

  • 方法八:提取某个字符串的一部分
方法 选择方式…… 负值参数
slice(start, end) 从 start 到 end(不含 end) 允许
substring(start, end) 从 start 到 end(不含 end) 负值代表 0
substr(start, length) 从 start 开始获取长为 length 的字符串 允许 start 为负数
var str = "Hello World"

console.log(str.slice(0,6))//Hello
console.log(str.slice(-5))//World   
console.log(str.slice(-11,5))//Hello
console.log(str.substring(-1,6))//Hello   相当于str.substring(0,6)
console.log(str.substr(0,3))//Hel
1
2
3
4
5
6
7
  • 开发中推荐使用slice方法。

# 5.6.字符串的其他方法:string.prototype.concat()、trim()、split()

  • 方法六:拼接字符串 str.concat(str2,[,...strN])
var str = "Hello"
console.log(str.concat("World"))//HelloWorld
1
2
  • 方法七:删除首尾空格 str.trim()
console.log("    ly k   ".trim())// ly k
1
  • 方法九:字符串分割 str.split([separator[,limit]])
    • separator:以什么字符串进行分割,也可以是一个正则表达式;
    • limit:限制返回片段的数量;
var message = "my name is kobe"
console.log(message.split(" ",3))// ["my","name","is"]
1
2

# 6、数组Array

# 6.1.认识数组(Array)

  • 什么是数组(Array)呢?

    • 对象允许存储键值集合,但是在某些情况下使用键值对来访问并不方便;
    • 比如说一系列的商品、用户、英雄,包括HTML元素,我们如何将它们存储在一起呢?
    • 这个时候我们需要一种有序的集合,里面的元素是按照某一个顺序来排列的;
    • 这个有序的集合,我们可以通过索引来获取到它;
    • 这个结构就是数组(Array);
  • 数组和对象都是一种保存多个数据的数据结构,在后续的数据结构中我们还会学习其他结构;如:map,set

  • 我们可以通过[]来创建一个数组:数组是一种特殊的对象类型;

var personArr = [
  {name:'lyk',age:17},
  {name:'kobe',age:27},
  {name:'james',age:19},
  {name:'curry',age:22}
]
1
2
3
4
5
6

# 6.2.数组的创建方式

  • 创建一个数组有两种语法:
var arr1 = []
var arr2 = new Array()
var arr3 = ["james","kobe","curry"]
var arr4 = new Array("james","kobe","curry")
1
2
3
4
  • 下面的方法是在创建一个数组时,设置数组的长度(很少用)
var arr5 = new Array(5)
console.log(arr5)
1
2
  • 数组元素从 0 开始编号(索引index)。

    • 一些编程语言允许我们使用负数索引来实现这一点,例如 fruits[-1]
    • JavaScript并不支持这种写法
  • 我们先来学习一下数组的基本操作:

    • 访问数组中的元素;
    • 修改数组中的元素;
    • 增加数组中的元素;
    • 删除数组中的元素;

# 6.3.数组的基本操作

  • 访问数组中的元素:
    • 通过中括号[]访问
    • arr.at(i):
      • 如果 i >= 0,则与 arr[i] 完全相同。
      • 对于 i 为负数的情况,它则从数组的尾部向前数。
var arr = ["james","kobe","curry"]
console.log(arr[0])//james
console.log(arr.at(-1))//curry
1
2
3
  • 修改数组中的元素:下面方式会修改原数组
var arr = ["james","kobe","curry"]
arr[0] = "lyk"
console.log(arr)// ["lyk","kobe","curry"]
1
2
3
  • 删除和添加元素虽然也可以通过索引来直接操作,但是开发中很少这样操作。

# 6.4.数组的添加、删除方法array.prototype.splice()、push()、pop()、unshift()、shift()

  • 在数组的尾端添加或删除元素:这个方法会修改原数组
    • push 在末端添加元素.
    • pop 从末端取出一个元素.
var arr = ["james","kobe","curry"]
arr.push("lyk","nba")
console.log(arr)// ["james","kobe","curry","lyk","nba"]
var arr1 = arr.pop()
console.log(arr1)//nba
console.log(arr)// ["james","kobe","curry","lyk","nba"]
1
2
3
4
5
6
  • 在数组的首端添加或删除元素:这个方法会修改原数组
    • shift 取出队列首端的一个元素,整个数组元素向前前移动;
    • unshift 在首端添加元素,整个其他数组元素向后移动;
    • 注意:push/pop 方法运行的比较快,而 shift/unshift 比较慢。
var arr = ["james","kobe","curry"]
arr.unshift("lyk","nba")
console.log(arr)//  ["lyk","nba","james","kobe","curry"]
var arr1 = arr.shift()
console.log(arr1)//lyk
console.log(arr)// ["nba","james","kobe","curry"]
1
2
3
4
5
6
  • 如果我们希望在中间某个位置添加或者删除元素应该如何操作呢?
    • arr.splice 方法可以说是处理数组的利器,它可以做所有事情:添加,删除和替换元素。 (注意:这个方法会修改原数组)
    • arr.splice的语法结构如下: array.prototype.splice(start[,deleteCount[,item1[,item2[, ...]]]])
      • 从start位置开始,处理数组中的元素;
      • deleteCount:要删除元素的个数,如果为0或者负数表示不删除;
      • item1, item2, ...:在添加元素时,需要添加的元素;
var arr = ["james","kobe","curry"]
//1.删除第一个元素
var arr1 = arr.splice(1,1)
console.log(arr1)// ["kobe"]
console.log(arr)//["james","curry"]

//2.添加两个元素
var arr2 = arr.splice(1,0,'cba','nba')
console.log(arr2)//  ["james","cba","nba","curry"]
console.log(arr)// ["james","cba","nba","curry"]

//3.替换两个元素
var arr3 = arr.splice(1,2,'ncaa','bcaa')
console.log(arr3)//  ["cba","nba"]
console.log(arr)// ["james","ncaa","bcaa","curry"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 6.5.数组的length属性

  • length属性用于获取数组的长度:

    • 当我们修改数组的时候,length 属性会自动更新。
  • length 属性的另一个有意思的点是它是可写的。

    • 如果我们手动增加一个大于默认length的数值,那么会增加数组的长度。
    • 但是如果我们减少它,数组就会被截断。
var arr = ["james","kobe","curry"]
arr.length = 10
console.log(arr)//["james","kobe","curry",empty x 7]

arr.length = 2
console.log(arr)// ["james","kobe"]
1
2
3
4
5
6
  • 所以,清空数组最简单的方法就是:arr.length = 0;。

# 6.6.数组的遍历-for、for in、for of(三种)

  • 普通for循环遍历:
var arr = ["james","kobe","curry"]
for(var i=0;i<arr.length;i++){
  console.log(arr[i])//james kobe curry
}
1
2
3
4
  • for..in 遍历,获取到索引值:
var arr = ["james","kobe","curry"]
for(var index in arr) {
  console.log(arr[index])//james kobe curry
}
1
2
3
4
  • for..of 遍历,获取到每一个元素
var arr = ["james","kobe","curry"]
for(var item of arr) {
  console.log(item)//james kobe curry
}
1
2
3
4

# 6.7.数组方法array.prototype.slice()、cancat()、 join()

  • arr.slice 方法:用于对数组进行截取(类似于字符串的slice方法)。 arr.slice([begin[,end]]) 这个方法不会修改原数组
    • 包含bigin元素,但是不包含end元素;
var arr = ['abc','nba','cba','ncaa']
var arr1 = arr.slice(2,3)
console.log(arr1)//['cba']
console.log(arr)//['abc','nba','cba','ncaa']
1
2
3
4
  • arr.concat方法:创建一个新数组,其中包含来自于其他数组和其他项的值。这个方法不会修改原数组
    • var new_array = old_array.concat(value1[,value2[, ...[, valueN]]])
var arr = ['abc','nba','cba','ncaa']
var arr1 = ['lyk']
var arr2 = arr.concat(arr1,'kobe')
console.log(arr)//['abc','nba','cba','ncaa']
console.log(arr2)//['abc','nba','cba','ncaa','lyk','kobe']
1
2
3
4
5
  • arr.join方法: 将一个数组的所有元素连接成一个字符串并返回这个字符 arr.join([separator])
    • 这个方法不会修改原数组
var arr = ['abc','nba','cba','ncaa']
var arr1 = arr.join('-')
console.log(arr1)//abc-nba-cba-ncaa
console.log(arr)//['abc','nba','cba','ncaa']
1
2
3
4

# 6.8.数组方法 – 查找元素array.prototype.indexOf()、includes()、find()、findIndex()

  • arr.indexOf方法: 查找某个元素的索引
    • 从fromIndex开始查找,如果找到返回对应的索引,没有找到返回-1;
    • 也有对应的从最后位置开始查找的 lastIndexOf 方法
var arr = ['nba','cba','ncaa']
console.log(arr.indexOf('cba'))//1  找到了返回该索引值
console.log(arr.indexOf('NCAA'))//-1  没有找到返回-1
1
2
3
  • arr.includes方法:判断数组是否包含某个元素
    • 从索引 from 开始搜索 item,如果找到则返回 true(如果没找到,则返回 false)。
var arr = ['nba','cba','ncaa']
console.log(arr.includes('cba'))//true  
console.log(arr.includes('NCAA'))//false  
1
2
3
//1、基本使用
var arr = [
  {name:'lyk',age:18,address:'北京'},
  {name:'kobe',age:40,address:'洛杉矶'},
  {name:'james',age:37,address:'克利夫兰'}
]

//1.1、find 方法 (没有找到则返回值是:undefined)
var arr1 = arr.find(function(item,index,arr){
  console.log(item,index,arr)
  return item.name === 'kobe' //返回是true   则find方法的 返回值是 该元素
})
console.log(arr1)//{"name":"kobe","age":40,"address":"洛杉矶"}

//1.2、findIndex方法 (没有找到则返回值是:-1)
var arrIndex = arr.findIndex(function(item,index,arr){
  return item.name === 'james'  //返回是true   则findIndex方法的 返回值是 该元素在数组中的索引
})
console.log(arrIndex)//2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  • 实现一下array.prototype.find()方法
var arr = [
  {name:'lyk',age:18,address:'北京'},
  {name:'kobe',age:40,address:'洛杉矶'},
  {name:'james',age:37,address:'克利夫兰'}
]

//2、实现一下array.prototype.find()

Array.prototype.hyFind = function(fn,thisArg) {
  for(var i=0;i<this.length;i++) {
    var isFlag = fn.call(thisArg,this[i],i,this)
    if(isFlag) return this[i]
  }
}

var arr1  = arr.hyFind(function(item,index,arr){
  console.log(item,index,arr)
  console.log(this)
  return item.age === 37
},{name;'lyk'})

console.log(arr1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 6.9.数组的排序 – array.prototype.sort()、reverse()

  • sort方法也是一个高阶函数,用于对数组进行排序,并且生成一个排序后的新数组:arr.sort([compareFunction])
    • 如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 前面;
    • 如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变;
    • 如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 前面;
    • 也就是说,谁小谁排在前面;
    • 这个方法会修改原数组
var arr = [9,6,12,3,30,18,27,21,15,24]

var arr1 = arr.sort(function(item1,item2) {
  return item1 - item2
})
console.log(arr)// [3,6,9,12,15,18,21,24,27,30]
console.log(arr1)//[3,6,9,12,15,18,21,24,27,30]

var arr2 = arr.sort(function(item1,item2) {
  return item2 - item1
})
console.log(arr2)//[30,27,24,21,18,15,12,9,6,3]
1
2
3
4
5
6
7
8
9
10
11
12
  • 等到后续讲解数据结构与算法时,我们会编写自己的排序算法:

    • 冒泡排序、插入排序、选择排序、堆排序、希尔排序、快速排序等;
  • reverse() 方法将数组中元素的位置颠倒**,**并返回该数组;这个方法会修改原数组

var arr = [30,27,24,21,18,15,12,9,6,3]
var arr1 = arr.reverse()
console.log(arr)//[3,6,9,12,15,18,21,24,27,30]
console.log(arr1)//[3,6,9,12,15,18,21,24,27,30]
1
2
3
4

# 6.10.数组的其他高阶方法: array.prototype.forEach、map()、filter()、reduce()

  • arr.forEach
    • 遍历数组,并且让数组中每一个元素都执行一次对应的方法;
    • 语法: arr.forEach(callback(currentValue [, index [, array]])[, thisArg])
var arr = ['nba','cba','NCAA']
arr.forEach(function(item,index,arr){
  console.log(item,index,arr)
})
1
2
3
4
  • 实现一下array.prototype.forEach()方法
var arr = ['nba','cba','NCAA']

//2、实现一下array.prototype.forEach()

Array.prototype.hyForEach = function(fn,thisArg) {
  for(var i=0;i<this.length;i++) {
    fn.call(thisArg,this[i],i,this)
  }
}

arr.hyForEach(function(item,index,arr){
  console.log(item,index,arr,this)
},{name:'lyk'})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  • arr.map
    • map() 方法创建一个新数组;这个方法不会修改原数组
    • 这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成
//arr.map语法:

var new_array = arr.map(function callback(currentValue[, index[, array]]) {
 // Return element for new_array 
}[, thisArg])
1
2
3
4
5
var arr = [1,2,3]
var arr1 = arr.map(function(item,index,arr) {
  console.log(item,index,arr)
  return item + 3
})
console.log(arr1)//[4,5,6]
console.log(arr)//[1,2,3]
1
2
3
4
5
6
7
  • arr.filter
    • filter() 方法创建一个新数组;这个方法不会修改原数组
    • 新数组中只包含每个元素调用函数返回为true的元素;
    • 语法:var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
var arr = [1,2,3,4,5,6,7,8,9,10]
var arr1 = arr.filter(function(item,index,arr) {
  return item > 4
})
console.log(arr1)//[5,6,7,8,9,10]
console.log(arr)//[1,2,3,4,5,6,7,8,9,10]
1
2
3
4
5
6
  • arr.reduce
    • 用于计算数组中所有元素的总和;
    • 对数组中的每个元素按序执行一个由您提供的 reducer 函数;
    • 每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值;
    • 语法:arr.reduce语法参考 (opens new window)
var arr = [1,2,3,4,5,6,7,8,9,10]
var arr1 = arr.reduce(function(previousValue,currentValue,currentIndex,array){
  return previousValue + currentValue
},5)//这里的5是初始值(initialValue);作为第一次调用 callback 函数时参数 previousValue 的值。
console.log(arr1)//60
1
2
3
4
5
  • 链式调用练习:
//如下arr数组
//取出arr中值大于16的元素
//再对这些元素进行平方
//然后再进行求和
var arr = [3,12,8,16,20,100]
var arr1 = arr.filter(function(item) {
    return item > 16
}).map(function(item) {
    return item * item
}).reduce(function(preValue,currentValue){
    return preValue + currentValue
})
console.log(arr1)//10400

//补充:还有一种箭头函数写法
var arr2 = arr.filter(item => item > 16)
              .map(item => item**2)
              .reduce((preValue,currentValue) => preValue + currentValue)

console.log(arr2)//10400
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 7、Date时间对象

# 7.1.时间的表示方式

  • 关于《时间》,有很多话题可以讨论:

    • 比如物理学有《时间简史:从大爆炸到黑洞》,讲述的是关于宇宙的起源、命运;
    • 比如文学上有《记念刘和珍君》:时间永是流驶,街市依旧太平;
    • 比如音乐上有《时间都去哪儿了》:时间都去哪儿了,还没好好感受年轻就老了;
  • 我们先来了解一下时间表示的基本概念:

  • 最初,人们是通过观察太阳的位置来决定时间的,但是这种方式有一个最大的弊端就是不同区域位置大家使用的时间是不一致的。

    • 相互之间没有办法通过一个统一的时间来沟通、交流。
  • 之后,人们开始制定的标准时间是英国伦敦的皇家格林威治( Greenwich )天文台的标准时间(刚好在本初子午线经过的地方),这个时间也称之为GMT(Greenwich Mean Time)。

    • 其他时区根据标准时间来确定自己的时间,往东的时区(GMT+hh:mm),往西的时区(GMT+hh:mm);
  • 但是,根据公转有一定的误差,也会造成GMT的时间会造成一定的误差,于是就提出了根据原子钟计算的标准时间UTC(Coordinated Universal Time)

  • 目前GMT依然在使用,主要表示的是某个时区中的时间,而UTC是标准的时间**。**

  • 时区对比图:

jJbQTP.png

# 7.2.创建Date对象方式

  • 在JavaScript中我们使用Date来表示和处理时间。
    • Date的构造函数有如下用法:
//创建Date对象的四种语法
new Date();
new Date(value);
new Date(dateString);

注意:monthIndex表示月份的整数值,从 0(1 月)到 11(12 月)。
new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]]);
1
2
3
4
5
6
7
//创建Date对象
var date1 = new Date().toISOString()//获取的是当前时间
var date2 = new Date(1000).toISOString()//传入的是毫秒数,表示从1970-01-01 00:00:00 UTC 经过的毫秒数
var date3 = new Date('2022-05-20 13:52:00.789').toISOString()//传入的是dateString, 日期的字符串值
var date4 = new Date(2022, 05, 20, 13, 52, 01, 01)
var date5 = new Date(2022, 05, 20, 13, 52, 01, 01).toISOString()

console.log(date1)
console.log(date2)//1970-01-01T00:00:01.000Z
console.log(date3)//2022-05-20T05:52:00.789Z
console.log(date4)//Mon Jun 20 2022 13:52:01 GMT+0800 (中国标准时间)
console.log(date5)//2022-06-20T05:52:01.001Z
1
2
3
4
5
6
7
8
9
10
11
12
  • 2022-06-20T05:52:01.001Z 这个时间格式是什么意思意思呢? ISO 8601 标准

# 7.3.dateString时间的表示方式:Date.prototype.toISOString()

  • 日期的表示方式有两种:RFC 2822 标准 或者 ISO 8601 标准。

  • 默认打印的时间格式是RFC 2822标准的: Mon Jun 20 2022 13:52:01 GMT+0800 (中国标准时间)

  • 我们也可以将其转化成ISO 8601标准的:2022-06-20T05:52:01.001Z

    • 通过该方法:Date.prototype.toISOString() 将其转化成ISO 8601标准
  • 2022-06-20T05:52:01.001Z; 分别代表什么:

    • YYYY:年份,0000 ~ 9999
    • MM:月份,01 ~ 12
    • DD:日,01 ~ 31
    • T:分隔日期和时间,没有特殊含义,可以省略
    • HH:小时,00 ~ 24
    • mm:分钟,00 ~ 59
    • ss:秒,00 ~ 59
    • .sss:毫秒
    • Z:时区

# 7.4.Date获取信息的方法

  • 我们可以从Date对象中获取各种详细的信息:

    • getFullYear():获取年份(4 位数);
    • getMonth():获取月份,从 0 到 11;
    • getDate():获取当月的具体日期,从 1 到 31(方法名字有点迷);
    • getHours():获取小时;
    • getMinutes():获取分钟;
    • getSeconds():获取秒钟;
    • getMilliseconds():获取毫秒;
  • 获取某周中的星期几:

    • getDay():获取一周中的第几天,从 0(星期日)到 6(星期六);

# 7.5.Date设置信息的方法

  • Date也有对应的设置方法:

    • setFullYear(year, [month], [date])
    • setMonth(month, [date]); 注意month设置:从 0(1 月)到 11(12 月)。
    • setDate(date)
    • setHours(hour, [min], [sec], [ms])
    • setMinutes(min, [sec], [ms])
    • setSeconds(sec, [ms])
    • setMilliseconds(ms)
    • setTime(milliseconds)
  • 了解:我们可以设置超范围的数值,它会自动校准。

# 7.6.Date获取Unix时间戳

  • Unix 时间戳:它是一个整数值,表示自1970年1月1日00:00:00 UTC以来的毫秒数。
  • 在JavaScript中,我们有多种方法可以获取这个时间戳:
    • 方式一:new Date().getTime() 方法的返回值一个数值,表示从 1970 年 1 月 1 日 0 时 0 分 0 秒(UTC,即协调世界时)距离该日期对象所代表时间的毫秒数。
    • 方式二:new Date().valueOf() 方法返回值是:从 1970 年 1 月 1 日 0 时 0 分 0 秒(UTC,即协调世界时)到该日期的毫秒数。
    • 方式三:+new Date()
    • 方式四:Date.now() 方法返回自 1970 年 1 月 1 日 00:00:00 (UTC) 到当前时间的毫秒数。
  var date1 = Date.now()
  console.log(date1)//1656948027054

  var date2 = new Date('1970-01-01T00:00:01.000Z').valueOf()
  console.log(date2)//1000

  var date3 = +new Date('1970-01-01T00:00:01.000Z')
  console.log(date3)//1000


// 为什么下面两个字符串写的是同样的时间日期,返回的时间戳却不同?

// 1.因为date3中的日期字符串是:ISO 8601标准写法;所以拿到的是UTC标准时间的时间戳(正常是1000毫秒->没错的)
// 2.而date4中的日期字符串不是ISO 8601标准写法;所以拿到的是咱们当地时区,
//  也就是东8区的时间的时间戳,即北京时间,比UTC标准时间快8个小时左右;
//  转换成UTC标准时间应该是 1969-12-31T16:00:01.000Z(所以是-28799000毫秒->这样就没错啦)
  var date4 = new Date('1970-01-01T00:00:01.000Z').getTime()
  console.log(date4)//1000
  console.log(new Date('1970-01-01 08:00:01.000').getTime())//1000

  var date5 = new Date('1970-01-01 00:00:01.000').getTime()
  console.log(date5)//-28799000
  console.log(new Date('1969-12-31T16:00:01.000Z').getTime())//-28799000
    

  var ISOdate = new Date().toISOString()
  console.log(ISOdate)//这里拿到的时间是比中国北京时间慢8个小时左右的时间(即UTC标准时间)

1
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
  • 获取到Unix时间戳之后,我们可以利用它来测试代码的性能
var startDate = Date.now()
for(var i = 0;i < 10000;i++){
  console.log(i)
}
var endDate = Date.now()
console.log(endDate - startDate)//返回一个时间戳:单位为毫秒
1
2
3
4
5
6

# 7.7.Date.parse方法

  • Date.parse(str) 方法可以从一个字符串中读取日期,并且输出对应的Unix时间戳。
  • Date.parse(str) :
    • 作用等同于 new Date(dateString).getTime() 操作;
    • 需要符合 RFC2822 或 ISO 8601 日期格式的字符串;
      • 比如YYYY-MM-DDTHH:mm:ss.sssZ
    • 其他格式也许也支持,但结果不能保证一定正常;
    • 如果输入的格式不能被解析,那么会返回NaN;
var date1 = Date.parse('2022-01-09 18:21:00.233')
console.log(date1)//1641723660233
var date2 = new Date(date1)
console.log(date2.toISOString())//2022-01-09T10:21:00.233Z

var date3 = Date.parse('2022-01-09--18:21:00.233')
console.log(date3)//NaN
1
2
3
4
5
6
7
  • 具体时间格式化的方法(后续js高级部分带你们实现)

# 7.8.案例:时间页面展示且会随时间改变而改变

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div class="box"> </div>
  <script>
    // 时间个位数时的展示格式化 方法封装
    function padLeft(num, count, str) {
      count = count || 2
      str = str || '0'
      
      return String(num).padStart(count,str)
    }

    var boxEl = document.querySelector('.box')

    setInterval(() => {
    // 获取当前时间
      var date = new Date()
      var year = date.getFullYear()
      var month = padLeft(date.getMonth() + 1)
      var day = padLeft(date.getDate())
      var hours = padLeft(date.getHours())
      var minutes = padLeft(date.getMinutes())
      var seconds = padLeft(date.getSeconds())
      var milliSeconds = padLeft(date.getMilliseconds(),3)

      boxEl.textContent = `北京时间:${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliSeconds}`
    }, 1);

  </script>
</body>

</html>
1
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
30
31
32
33
34
35
36
37
38
39
40
41
最后更新时间: 2022/07/08, 10:54:07
彩虹
周杰伦