精简《JavaScript高级程序设计》五、引用类型(上)
第五章概况
5.1 Object类型
引用类型是一种数据结构,用于将数据和功能组织在一起。对象是某个特定引用类型的实例
创建Object实例的方式有两种:
- new+Object构造函数
var person = new Object()
- 使用对象字面量
var person = {
name:"fur",
age:"1"
}
//或者
var person = {}
person.name = "fur"
person.age = "1"
注意:属性名也可以为字符串,但是数值属性名会自动转换为字符串 eg
let person = {
"name":"fur",
"age":"1",
5:true //5自动转换为字符串
}
//console.log(person.5)直接打印报错
console.log(typeof person[5])//只能用方括号的形式
//验证数字5 被 转换为字符串
for (let i in person) {
console.log(i + ' 类型是:'+ typeof i )
}
运行结果如图:
访问对象属性的方式两种:
点表示法:简单常用
方括号表示法:可以通过遍历访问属性,常用于遍历,或者不能用点表示法时候
let person = {
"name":"fur",
"age":"1",
5:true //5自动转换为字符串
"first name" : "jiang"
}
//以下只能用方括号表示,不提倡这样定义
console.log(typeof person[5])
console.log(typeof person["first name"])
5.2 Array类型
创建数组的方式两种:
第一种 使用Array构造函数,new可以省略
let arr = new Array()
let arr = new Array(20)
let arr = new Array("fur","frufur")
第二种,数组字面量表示法
let arr = []
let arr = ["fur","furfur"]
注意:数组长度不是一个只读属性,可以被修改
验证:
let arr = ['fur','furfur','furfur-jiang']
console.log(arr[2])//furfur-jiang
arr.length = 2
console.log(arr[2])//undefined
可以方便的句末添加属性
let arr = ['fur','furfur','furfur-jiang']
arr[arr.length]= "fur1"
arr[arr.length]= "fur2"
console.log(arr)
//Array(5) [ "fur", "furfur", "furfur-jiang", "fur1", "fur2" ]
注意:数组上限4294967295项
Array.isArray()
用于检测是否为数组,当网页包含多个框架,存在不同版本的Array构造函数时,通过这个方法确定是不是数组
let arr = ['fur','furfur','furfur-jiang']
console.log(Array.isArray(arr))//true
转换方法
所有对象都具有toLocaleString()
,toString()
,valueOf()
toLocaleString()
,toString()
输出以逗号隔开的字符串
valueOf()
返回一个数组
注意:alert默认会调用toString方法,所有输出的都是字符串
join()
可以用不同分隔符构建字符串,只接受一个参数
let arr = ['fur','furfur','furfur-jiang']
console.log(arr.join("!!!"))//fur!!!furfur!!!furfur-jiang
console.log(arr.join("___"))//fur___furfur___furfur-jiang
如果数组中间某一项是null或者undefined,在toLocaleString()
,toString()
,join()
返回的结构中以空字符串表示,而valueOf()
会返回对应元素(valueOf()
运行结果与书里的解释不同,书中将其与前面三种方法归为一类)
let arr = ['fur',null,undefined,'furfur-jiang']
arr[5] = "fur0"
console.log(arr.toString())//fur,,,furfur-jiang,,fur0
console.log(arr.toLocaleString())//fur,,,furfur-jiang,,fur0
console.log(arr.join(","))//fur,,,furfur-jiang,,fur0
console.log(arr.valueOf())
//火狐结果
//Array(6) [ "fur", null, undefined, "furfur-jiang", undefined, "fur0" ]
//谷歌结果
//(6) ["fur", null, undefined, "furfur-jiang", empty, "fur0"]
栈方法
栈方法是一种LIFO(Last-In-First-Out,后入先出)的数据结构,栈中项的插入(推入)和移除(弹出),只发生在栈的顶部。对应push()
和pop()
方法
push()
接受任意数量的参数,把他们逐个添加到数组末尾,并返回修改后的数组长度。
pop()
从数组末尾移除最后一项并返回
let arr = ['fur',"furfur",'furfur-jiang']
console.log(arr.push("fur1","fur2"))//5
console.log(arr.pop())//fur2
console.log(arr.length)//4
push进行推入操作,操作结束后返回数组长度,pop进行移除操作,操作结束后返回被移除的那一项,数组长度减一
队列方法
栈方法是一种LIFO(First-In-First-Out,先入先出)的数据结构,队列的末端添加项,从队列前端移除项,对应push()
和shift()
方法
shift()
移除数组第一项并返回该项
let arr = ['fur',"furfur",'furfur-jiang']
console.log(arr.push("fur1","fur2"))//5
console.log(arr.shift())//fur
console.log(arr.length)//4
unshift()
能在数组前端添加任意个项并返回新数组长度
总结:
unshift()
和push()
都是添加任意元素,前者在数组前端添加,后者在数组末尾添加shift()
和pop()
都是移除一个元素,前者在数组前端移除,后者在数组末尾移除
重排序方法
数组已经存在reverse()
和sort()
两个方法
reverse()
具有从反转数组项的顺序
let arr = ['fur','furfur-jiang',"furfur"]
console.log(arr.reverse())
//Array(3) [ "furfur", "furfur-jiang", "fur" ]
sort()
按升序排列数组项,每个数组项调用toString()
方法,也就是比较的其实是字符串,即使数组内的元素都是数字
let arr = ['fur','aaa',"abc"]
console.log(arr.sort())
// Array(3) [ "aaa", "abc", "fur" ]
let arr = [5,16,11]
console.log(arr.sort())
// Array(3) [ 11, 16, 5 ]
所以sort()
正确使用方式是接受一个比较函数作为参数
let arr = [5,16,11]
//升序
function compareUp (value1,value2){
return value1 - value2;
}
//降序
function compareDown (value1,value2){
return value2 - value1;
}
console.log(arr.sort(compareUp))
//Array(3) [ 5, 11, 16 ]
console.log(arr.sort(compareDown))
//Array(3) [ 16, 11, 5 ]
操作方法
concat()
,slice()
,splice()
三种方法
concat()
可以基于当前数组中的所有项创建新数组,如果传递的是一个或多个数组,会将这些数组的每一项添加到结果数组里;如果不是数组,则简单添加到结果数组末尾,不会干扰原来的数组。
let arr = ['fur',"furfur"]
console.log(arr.concat("furfur-jiang"))
//[ "fur", "furfur", "furfur-jiang" ]
console.log(arr.concat(['fur1',"fur2"]))
//[ "fur", "furfur", "fur1", "fur2" ]
slice()
可以基于当前数组在的一个或多个项创建一个新数组,接受一或两个参数,返回项的起始和结束位置。如果只有一个参数即从这个参数到数组末尾所有项。返回对应的值,包括起始位置而不包括结束位置的元素(包头不包尾)
let arr = ['fur',"furfur","furfur-jiang","fur1"]
console.log(arr.slice(1))
//[ "furfur", "furfur-jiang", "fur1" ]
console.log(arr.slice(1,3))
//[ "furfur", "furfur-jiang" ]
splice()
主要用于向数组中部插入项,返回删除的元素,会影响原数组,使用方法有如下三种
- 删除:只需指定两个参数,要删除的第一项和要删除的项数
- 插入:只需指定3个参数:起始位置,0(要删除的项数),要插入的项
- 替换:向指定位置插入任意数量的项,同时删除任意数量的项,只需指定三个参数:起始位置,要删除的项数,要插入的任意数量的项
//删除操作,第一项furfur开始删除,删除两个
let arr1 = ['fur',"furfur","furfur-jiang","fur1"]
console.log(arr1.splice(1,2))
//[ "furfur", "furfur-jiang" ]
console.log(arr1)
// [ "fur", "fur1" ]
//插入操作,从第一项furfur开始插入,插入两个元素
let arr2 = ['fur',"furfur","furfur-jiang","fur1"]
console.log(arr2.splice(1,0,"fur2","fur3"))
//[]
console.log(arr2)
// [ "fur", "fur2", "fur3", "furfur", "furfur-jiang", "fur1" ]
//替换操作,从第一项furfur开始插入,插入两个同时删除原来的两个的位置
let arr3 = ['fur',"furfur","furfur-jiang","fur1"]
console.log(arr3.splice(1,2,"fur2","fur3"))
//[ "furfur", "furfur-jiang" ]
console.log(arr3)
//[ "fur", "fur2", "fur3", "fur1" ]
位置方法
indexOf()
和lastIndexOf()
两个方法都接收两个参数:要查找的项和(可选的)表示要查找起点位置的索引。
其中indexOf()
从数组开头开始向后查找,lastIndexOf()
表示从数组的末尾向前查找。两个方法都返回查找项在数组的位置,没找到返回-1。
注意:要求查找的项必须严格相等(就像使用===一样)
let arr = ['fur',"furfur","furfur-jiang"]
console.log(arr.indexOf("furfur"))//1
console.log(arr.indexOf("furfur",1))//1
console.log(arr.indexOf("furfur",2))//-1
console.log(arr.lastIndexOf("furfur",2))//1
console.log(arr.lastIndexOf("fur-fur"))//-1
迭代方法
ES5定义了五个迭代的方法,每个方法就收两个参数:要在每一项上运行的函数和(可选的)运行该函数的作用域对象–影响this的值,其中传入的函数接受三个参数:数组项的值,该项在数组中的位置和数组对象本身,数组对象本身
every()
,对数组的每一项运行给定函数,如果该函数对每一项都返回true,则返回true
filter()
, 对数组的每一项运行给定函数,返回该函数会返回true的项组成的数组
forEach()
,对数组的每一项运行给定函数,则这个没有返回值,参照我的另一篇文章
map()
, 对数组的每一项运行给定函数,返回每次函数调用的结果组成的数组
some()
,对数组的每一项运行给定函数,如果该函数对任一项返回true,则返回true,不再继续
以上函数不会修改原数组包含的值
let arr = [1,2,3,4,5,6,3]
console.log(arr.every(function(item,index,array){
return (item >2)
}))//false
console.log(arr.some(function(item,index,array){
return (item >2)
}))//true
console.log(arr.filter(function(item,index,array){
return (item >2)
}))//[ 3, 4, 5, 6, 3 ]
console.log(arr.map(function(item,index,array){
return (item * 2)
}))//[ 2, 4, 6, 8, 10, 12, 6 ]
归并方法
reduce()
和reduceRight()
都会迭代数组的所有项,然后构造一个最终返回的值。区别在于reduce()
是从数组第一项,reduceRight()
是从数组最后一项,向前遍历。
接收两个参数:一个在每一项是调用的函数和(可选的)作为归并基础的初始值
传给这两个方法的函数接受四个参数:前一个值,当前值,项的索引,数组对象
这个函数返回的任何值都会作为第一个参数自动传给下一项,第一次迭代发生在数组第二项上,因此第一个参数是数组的第一项,第二个参数是数组的第二项
let arr = [1,2,3,4,5,6,3]
let sum1 = arr.reduce(function(pre,cur,index,array){
console.log("pre:"+pre+",cur:"+cur)
return pre + cur
})
console.log(sum1)//24
let sum2 = arr.reduceRight(function(pre,cur,index,array){
console.log("pre:"+pre+",cur:"+cur)
return pre + cur
})
console.log(sum2)//24
5.3 Date类型
Date基本方法
Date.parse()
,Date.UTC()
,Date.now()
Date.parse()
会接受一个表示日期的字符串,然后尝试根据这个字符串返回相应日期的毫秒数。
console.log(new Date(Date.parse("Jan 23,2020")))
//Date Thu Jan 23 2020 00:00:00 GMT+0800 (中国标准时间)
console.log(new Date("Jan 23,2020"))
//Date Thu Jan 23 2020 00:00:00 GMT+0800 (中国标准时间)
Date
构造函数会在后台调用Date,parse()
,所以上面两种写法是相同的
当输入的字符串不能表示日期,谷歌和火狐会输出Invalid Date,(运行结果与书上不同,书上说是NaN或者其他奇怪的结果)
console.log(new Date("Jan 32,2020"))//Invalid Date
Date.UTC()
接受的参数年份,基于0的月份,月中的哪一天(1到31),小时数(0到23),分钟,秒以及毫秒数,这些参数只有前两个参数(年和月)是必需的。其他参数统统假设为0。
var utc = Date.UTC(y,m,d,h,M,s);
//这里,y、m、d、h、M、s分别代表步骤2中获取的年、月、日、时、分、秒数值。
UTC + 时区差 = 本地时间
- 时区差格式为 符号+ 24小时制数字 + 分钟,如:北京与UTC时差记为+0800
- 时区差东为正,西为负。
整个地球分为二十四时区,每个时区都有自己的本地时间。在国际无线电通信场合,为了统一起见,使用一个统一的时间,称为通用协调时(UTC, Universal Time Coordinated)。UTC与格林尼治平均时(GMT, Greenwich Mean Time)一样,都与英国伦敦的本地时相同。
看个例子:
console.log(new Date(Date.UTC(2020,0,23,9,55,55)))
//Thu Jan 23 2020 17:55:55 GMT+0800 (中国标准时间)
注意:
- 月份输入会比输出-1,因为月是基于0 的,所以输入0输出Jan
- UTC = 本地时间 - 0800 = 1755-0800 = 0155 中国位于伦敦以东,为正,所以减去对应时区差,求出UTC时间,与运行结果一致
(这一部分书上讲得很少,几乎都是自己理解+参考别人博客)
Date.now()
返回表示调用这个方法时的日期和时间的毫秒数,在不支持这写法可以使用下面第二种写法获取时间戳,结果相同;一般用于计算运行速度
let now = Date.now()
console.log(now)//1579781768327
console.log(+new Date())//1579781768327
doSome() //执行某些函数
let result = +new Date() - now
继承方法
Date类型重写了toLocaleString()
,toString()
,valueOf()
,具体结果依据浏览器不同而不同,valueOf()
一般用来比较日期值
这里以火狐和谷歌为例:(两者相同)
console.log(new Date(2020,0,23).toString())
//Thu Jan 23 2020 00:00:00 GMT+0800 (中国标准时间)
console.log(new Date(2020,0,23).toLocaleString())
//2020/1/23 上午12:00:00
let a = new Date(2020,0,23).valueOf()
console.log(a)
//1579708800000
let b = new Date(2020,1,23).valueOf()
console.log(b)
//1582387200000
console.log(a < b)
//true
日期格式化方法
toDateString()
–以特定于实现的格式显示星期几、月、日和年
toTimeString()
–以特定于实现的格式显示时,分,秒,时区
toLocaleDateString()
–以特定于地区的格式显示星期几、月、日和年
toLocaleTimeString()
–以特定于地区的格式显示时,分,秒
toUTCString()
–以特定于实现的格式完整的UTC日期
console.log(new Date(2020,0,23,20,55,55).toDateString())
//Thu Jan 23 2020
console.log(new Date(2020,0,23,20,55,55).toTimeString())
//20:55:55 GMT+0800 (中国标准时间)
console.log(new Date(2020,0,23,20,55,55).toLocaleDateString())
//2020/1/23
console.log(new Date(2020,0,23,20,55,55).toLocaleTimeString())
//下午8:55:55
console.log(new Date(2020,0,23,20,55,55).toUTCString())
//Thu, 23 Jan 2020 12:55:55 GMT
日期/时间组件方法
getTime()
–返回日期的毫秒数,于valueOf()
方法返回的值相同
getFullYear()
--取4位数的年份(2020)
getMonth()
–返回日期的月份,0表示1月份
getDate()
–返回日期的天数,(1-31)
getDay()
–返回日期中星期的星期几(0表示星期日,6表示星期六)
getHours()
–返回日期的小时数(0-23)
getMinutes()
–返回日期的分钟数(0-59)
getSeconds()
–返回日期的秒数(0-59)
console.log(new Date(2020,0,23,20,55,55).getTime())
//1579784155000
console.log(new Date(2020,0,23,20,55,55).getFullYear())
//2020
console.log(new Date(2020,0,23,20,55,55).getMonth())
//0
console.log(new Date(2020,0,23,20,55,55).getDate())
//23
console.log(new Date(2020,0,23,20,55,55).getDay())
//4
console.log(new Date(2020,0,23,20,55,55).getHours())
//20
console.log(new Date(2020,0,23,20,55,55).getMinutes())
//55
console.log(new Date(2020,0,23,20,55,55).getSeconds())
//55