引用数据类型
- `引用数据类型`(对象类型)统称为Object
- Object
- Array
- Array构建
- Array方法与属性
- `length`
- `constructor`
- `prototype`
- `Array.from()和Array.of()`
- 判断一个对象是不是数组
- `keys(),values(),entries()`,迭代器方法(返回迭代器),使用时需要用from转换为数组
- `fill(),copyWithin()`复制和填充数组方法,`修改原数组`
- `toString()、valueOf()、toLocaleString()`转换方法,不改变原数组
- `join()`方法,使用`不同的分隔符`来转换数组
- `push()、pop() `栈方法,`改变原数组`
- `shift()、unshift()`队列方法,`改变原数组`
- `sort()、reverse()`排序方法,`修改原数组`
- `concat()、flat()`,`不改变原数组`
- `slice()` 操作`不影响原数组`
- `splice()`改变原数组`,从xx位置,删除xx个元素,插入xx,`返回值就是删除的值`;即要删除的第一个元素的位置,要删除元素的数量,要插入的元素,在第xx位置之前插入
- `indexOf(),lastIndexOf(),includes(),find(),findIndex()`搜索和定位
- `every()、filter()`、forEach()、`map()、some()`五个迭代方法。这些方法都`不改变原数组`
- `reduce()`,reduceRight()归并方法
引用数据类型
(对象类型)统称为Object
对象被认为是某个特定引用类型的实例
,新对象通过使用new操作符
后跟一个构造函数
来创建,构造函数
就是用来创建新对象
的函数
原生的引用类型细分有下面几种:基本引用类型:RegExp、Date、单例内置对象、原始值包装类型;;集合引用类型:Object、Array、定型数组、Set、Map、WeakMap、WeakSet等
Object
注:但是这些对象的行为不一定适用于JS中的其他对象,比如浏览器环境中的BOM和DOM对象,都是由宿主环境定义和提供的
Object创建
对象通过new操作符
后跟对象类型名称
来创建。Object类型
是派生其他对象的基类
,Object类型的所有属性和方法
在派生的对象上
同样存在。
- 对象字面量创建,注意数值属性名会自动转换为字符串,不会调用Object构造函数
let obj = {};
- new操作符和Object构造函数
let obj = new Object()
- 属性的访问可以使用
点语法
或者中括号
,使用中括号的优势
是可以通过变量来访问属性
Object实例都有如下属性和方法
constructor属性
,指向用于创建当前对象的函数
,前面的例子这个属性的值就是Object()函数,即指向构造函数,这个属性源自于原型当中的constructor属性。hasOwnProperty(propertyName)
:用于判断当前对象实例
(不是原型)上是否存在给定属性
,属性名必须是字符串isPrototypeOf(object)
:用于判断当前对象
是否是另一个对象的原型
propertyIsEnumerable(propertyName)
:用于判断给定的属性
是否可以使用for-in语句枚举
,属性名需要时字符串toLocaleString()
:返回对象的字符串表示,该字符串反映了对象所在的本地化
执行环境toString()
返回对象的字符串表示valueOf()
返回对象对应的字符串、数值或布尔值
表示,通常与toString()的返回值相同
Array
Array构建
js的Array中的每个槽位
可以存储任意类型
的数据,可以动态增长
字面量
构建,字面创建的时候不会调用Array构造函数
let arr = [];
构造函数
,可以省略new操作符,不建议使用
let arr = new Array();
let arrays = Array(2);
Array方法与属性
length
数组的长度是可变
的,所以引用
了超过
长度的下标不会报错
,未初始化
的都是undefined
,数组的length属性不是只读
的,可以修改length属性来从数组末尾删除或者增加元素。
constructor
构造函数、返回创建Array对象原型的函数
prototype
允许向数组添加属性和方法
Array.from()和Array.of()
ES6新增
两个用于创建数组的静态方法,from()和of().
- from()用于将
类数组结构
(任何可迭代结构,或者有一个length属性和可索引元素结构)转换为数组实例
console.log("下面测试Array.from()")
//字符串转
console.log(Array.from("sdfa"));//[ 's', 'd', 'f', 'a' ]
//map转
let newmap = new Map();
newmap.set(1,2);
newmap.set(3,4);
console.log(newmap);//Map(2) { 1 => 2, 3 => 4 }
console.log(Array.from(newmap));//[ [ 1, 2 ], [ 3, 4 ] ]
//set转
let newSet = new Set();
newSet.add(4);
newSet.add("23")
console.log(newSet);//Set(2) { 4, '23' }
console.log(Array.from(newSet));//[ 4, '23' ]
//对现有数组进行复制,返回一个新的数组
let Arrat = [5,4,2,1,5];
let fromArrat = Array.from(Arrat);
fromArrat[2] = 8;
console.log(Arrat);//[ 5, 4, 2, 1, 5 ]
console.log(fromArrat);//[ 5, 4, 8, 1, 5 ]
//对函数的arguments转换为数组
function getArguments(){
return Array.from(arguments);
}
console.log(getArguments(2,3,1,"",4));//[ 2, 3, 1, '', 4 ]
- of()用于将一组参数转换为数组实例
console.log(Array.of(1,2,3,4))//[1,2,3,4]
判断一个对象是不是数组
instanceof
判断一个对象是不是数组。在只有一个网页的情况下(只有一个全局作用域),用instanceof就够了。- 如果网页里有多个框架可能涉及多个上下文,就需要用
Array.isArray()
来检测,这个方法就是确定一个值是否为数组,而不用管是哪个全局上下文中创建的 - Array.isArray()是ES5规范,不支持旧版本浏览器,可以自己写一个方法,
function isArray(arr){
return arr.constructor.toString().indexOf("Array");
}
- 使用对象原型上的方法:Object.prototype.toString.call(array),返回[object Array]。
keys(),values(),entries()
,迭代器方法(返回迭代器),使用时需要用from转换为数组
ES6中Array
的原型上暴露了三个用于检索数组内容的方法,就像把数组看成了map,keys包含其键,即下标;values包含其值;entries就是键值对
可以利用ES6的解构在循环中拆分键值对
const array = ["a","b","c","d"];
console.log(array.keys());//Object [Array Iterator] {}
console.log(array.values());//Object [Array Iterator] {}
console.log(array.entries());//Object [Array Iterator] {}
console.log(Array.from(array.keys()));//[ 0, 1, 2, 3 ]
console.log(Array.from(array.values()));//[ 'a', 'b', 'c', 'd' ]
console.log(Array.from(array.entries()));//[ [ 0, 'a' ], [ 1, 'b' ], [ 2, 'c' ], [ 3, 'd' ] ]
for(let [key,value] of array.entries()){
console.log(key);
console.log(value);
}
fill(),copyWithin()
复制和填充数组方法,修改原数组
ES6新增
两个方法,批量复制以及填充数组,需要指定已有数组实例上的一个范围,不包括结束索引。他们会忽略超出数组的范围。
console.log("下面开始测试复制和填充数组");
let arrarNumber = [0,0,0,0,0];
console.log(arrarNumber);//[ 0, 0, 0, 0, 0 ]
arrarNumber.fill(5);//填充整个数组
console.log(arrarNumber);//[ 5, 5, 5, 5, 5 ]
arrarNumber.fill(4,2);//用4填充索引大于等于2的元素
console.log(arrarNumber);//[ 5, 5, 4, 4, 4 ]
arrarNumber.fill(3,1,4);//用3填充大于等于1,小于4的元素
console.log(arrarNumber);//[ 5, 3, 3, 3, 4 ]
toString()、valueOf()、toLocaleString()
转换方法,不改变原数组
所有对象都有这三种方法
- toString()方法返回有数组中的
每个值的字符串
拼接而成的逗号分隔
的字符串,即对于数组中的每个值都会调用toString()
- valueOf()返回
数组本身
- toLocaleString()会对每个值调用toLocaleString()
console.log("下面开始测试转换方法")
console.log([1,2,3,[4,5,[6,7]]].toString());
// 1,2,3,4,5,6,7
console.log(arrarNumber.toString());//5,3,3,3,4
console.log(arrarNumber.toLocaleString());//5,3,3,3,4
console.log(arrarNumber.valueOf());//[ 5, 3, 3, 3, 4 ]
const diffrentArray = [new Date(), new RegExp('/at'), new Array(5)]
console.log(diffrentArray.toString());//Mon Apr 18 2022 16:51:14 GMT+0800 (中国标准时间),/\/at/,,,,,
console.log(diffrentArray.toLocaleString());//2022/4/18 下午4:51:14,/\/at/,,,,,
console.log(diffrentArray.valueOf());//[ 2022-04-18T08:51:14.398Z, /\/at/, [ <5 empty items> ] ]
join()
方法,使用不同的分隔符
来转换数组
类似于toString()
,就是可选分隔符。它接收一个参数,即字符串的分隔符
。如果数组中某一项为null或者undefined,则会用空字符串表示
console.log("下面开始测试join方法");
console.log(arrarNumber.join("|||"));// 5|||3|||3|||3|||4
console.log([1,2,3,[4,5,[6,7]]].join(","));
// 1,2,3,4,5,6,7
push()、pop()
栈方法,改变原数组
- push()接收任意数量的参数,并加到数组末尾,
返回数组的最新长度
- pop()
删除数组的最后一项
,减少length值
,并返回pop出去的元素;如果数组是空的,那么返回undefined并且不再修改数组;
console.log("下面开始测试栈方法")
let newlength = arrarNumber.push(4,3,2);
console.log(newlength);// 8
console.log(arrarNumber);//[ 5, 3, 3, 3, 4, 4, 3, 2]
let popond = arrarNumber.pop()
console.log(arrarNumber.length);// 7
console.log(arrarNumber);//[ 5, 3, 3, 3, 4, 4, 3]
console.log(popond);//2
shift()、unshift()
队列方法,改变原数组
- shift()方法删除数组的第一个元素,并返回,修改数组长度
- unshift()方法在数组前面插入一个或多个元素,返回数组的新长度
console.log("下面开始测试队列方法")
let newlength2 = arrarNumber.unshift(4,3,2);
console.log(newlength2);// 10
console.log(arrarNumber);//[ 4,3,2,5, 3, 3, 3, 4, 4, 3]
let shift = arrarNumber.shift()
console.log(arrarNumber.length);//9
console.log(arrarNumber);//[ 3,2,5, 3, 3, 3, 4, 4, 3]
console.log(shift);//4
sort()、reverse()
排序方法,修改原数组
- sort()默认会
升序
来重新排列数组元素,在每一项上调用String()转型函数
,然后比较字符串
来决定顺序,即使数组元素都是数值
,也会把数组转换为字符串再来比较。由于这个问题,所以sort接收一个比较函数
用来判断哪个值排在前面,比较函数接收两个参数,如果第一个值应该排在第二个值前面,就返回负数,否则返回正数. - reverse()
翻转
数组的顺序。 - sort和reverse都返回调用他们的数组的应用
- sort()接收一个conpare函数来进行比较
console.log("下面测试排序数组")
let sortArray = [12,3,2,5,1,32,5,6,7]
console.log(sortArray);//[12,3,2,5,1,32,5,6,7]
let sortdArray = sortArray.sort();
console.log(sortArray);//[1, 12, 2, 3, 32, 5, 5, 6, 7]
console.log(sortdArray);//[1, 12, 2, 3, 32, 5, 5, 6, 7]指向同一个
console.log(sortdArray.reverse());//[7,6,5,5,32,3,2,12,1]反转
console.log(sortdArray.sort((a,b) => {
if(a > b){
return 1;
}
if(a === b){
return 0;
}
if(a < b){
return -1;
}
}))//[1, 2, 3, 5, 5, 6, 7, 12, 32 ]
concat()、flat()
,不改变原数组
- concat()在现有数组全部元素的基础上
创建一个新数组
,先创建当前数组的副本,再把参数加到末尾,如果参数是数组,则concat会把这些数组的每一项
都添加到数组
,如果参数不是数组,则直接添加到结果末尾;原数组保持不变
flat()
打平数组,可以指定打平的层数
console.log("下面测试concat")
let concat1 = [1,2,3,4,5];
let concat2 = [1,[2,[3,4]]];
let concatString = "aaa";
console.log(concat1.concat(concat2));//[ 1, 2, 3, 4, 5, 1, [ 2, [ 3, 4 ] ] ]
console.log(concat2.concat(concat1));//[ 1, [ 2, [ 3, 4 ] ], 1, 2, 3, 4, 5 ]
console.log(concat2.concat(concatString))//[ 1, [ 2, [ 3, 4 ] ], 'aaa' ]
// [Symbol.isConcatSpreadable]//可以设置强制不打平
console.log(concat2.flat(1));//[ 1, 2, [ 3, 4 ] ]
console.log(concat2.flat(Infinity));//[ 1, 2, 3, 4 ]
slice()
操作不影响原数组
- slice()用于
创建一个包含原有数组中一个或多个元素的新数组
,接收一个或者两个参数,元素的开始索引
和结束索引
- 有
负值
则用数值加上数组长度,如果结束位置小于开始位置
,则返回空数组
let sliceArray = [1,2,3,4,5,6,7,8];
console.log(sliceArray.slice());//12345678
console.log(sliceArray.slice(4));//5678
console.log(sliceArray.slice(2,5));//345
console.log(sliceArray.slice(-5));//45678
console.log(sliceArray.slice(-5,-2));//456不能反过来
splice()
改变原数组,从xx位置,删除xx个元素,插入xx,
返回值就是删除的值`;即要删除的第一个元素的位置,要删除元素的数量,要插入的元素,在第xx位置之前插入
- splice(0,2)删除从下标0开始的两个元素
- splice(2,0,“red”,“blue”),在从2位置开始插入red、blue
- splice(2,3,“red”,"blue),从2开始删除3个元素,再插入red、blue
console.log("开始测试splice")
console.log(sliceArray);//12345678
console.log(sliceArray.splice(0,2));//12
console.log(sliceArray);//345678
console.log(sliceArray.splice(2,0,"red","blue"));//[]
console.log(sliceArray);34"red""blue"5678
console.log(sliceArray.splice(2,3,"red1","blue1"));//redblue5
console.log(sliceArray);34"red1""blue1"678
indexOf(),lastIndexOf(),includes(),find(),findIndex()
搜索和定位
- 三个严格相等的搜索方法:indexOf()、lastIndexOf()、includes()(es7)。接收两个参数,要查找的元素和一个可选的起始搜索位置。
- indexOf()和lastIndexOf()都要返回查找的元素在数组中的位置,找不到就-1
- includes()返回布尔值
- 比较第一个参数根数组每一项时,用全等(===)比较,即必须严格相等
- 断言函数,接收三个参数,元素、索引和数组本身
- find()
- findIndex()
every()、filter()
、forEach()、map()、some()
五个迭代方法。这些方法都不改变原数组
上面五个函数,每个函数都接收两个参数
每一项要执行的函数
,(即对数组的每一项都执行这个函数),该函数接收三个参数,数组元素,元素索引,数组本身
- 可选的作为函数运行
上下文的作用域对象
,影响this值
every()与some()
,传入函数,对数组的每一项都运行传入的函数,如果每一项函数都是true
则every()返回true,如果有一项返回true则some()返回truefilter()
对数组的每一项都运行传入的函数,函数返回true的项会组成数组
之后返回forEach()
,对数组每一项都运行传入的函数,没有返回值map()
,对数组的每一项都运行传入的函数,返回由每次函数调用的结果构成的数组
。
console.log("开始测试迭代方法")
let numbers = [1,2,3,4,3,2,1,4,2,3,1]
let everyResult = numbers.every((item,index,numbers) =>{
return item > 2;
})
console.log(numbers);//[1,2,3,4,3,2,1,4,2,3,1]
console.log(everyResult);// false
let someResult = numbers.some((item,index,numbers) =>{
return item > 2;
})
console.log(numbers);[1,2,3,4,3,2,1,4,2,3,1]
console.log(someResult);// true
let filterResult = numbers.filter((item,index,numbers) =>{
return item > 2;
})
console.log(numbers);[1,2,3,4,3,2,1,4,2,3,1]
console.log(filterResult);//[ 3, 4, 3, 4, 3 ]
let mapResult = numbers.map((item,index,numbers) =>{
return item + 2;
})
console.log(numbers);[1,2,3,4,3,2,1,4,2,3,1]
console.log(mapResult);//[3, 4, 5, 6, 5, 4, 3, 6, 4, 5, 3]
let forEachResult = numbers.forEach((item,index,numbers) =>{
return item + 2;
})
console.log(numbers);[1,2,3,4,3,2,1,4,2,3,1]
console.log(forEachResult);// undefined
reduce()
,reduceRight()归并方法
- 迭代数组的所有项,并在此基础上构建一个最终返回值。reduce从第一项开始遍历到最后一项,reduceRight逆过来。
- 接收
两个参数
- 对
每一项
都会运行的归并函数
,接收四个参数
,上一个归并值,当前项,当前项的索引,数组本身
。函数返回的任何值都会作为下一次调用同一个函数的第一个参数 可选的归并起点
,如果没有指定的话,第一次迭代将从数组的第二项开始,因此传给归并函数的第一个参数是数组的第一项
- 对
let numbers = [1,2,3,4,3,2,1,4,2,3,1]
console.log("开始测试归并函数")
//求和
let reduceResult = numbers.reduce((pre,cur,curIndex,numbers) => {
return pre + cur;
})
console.log(reduceResult);//26
// 计算重复字母的次数
let stringnumber = "asfacsaswcasxacrvzq";
let stringArray = Array.from(stringnumber);
let resultObject = stringArray.reduce((pre,cur,index,stringArray) => {
if(cur in pre){
pre[cur] =pre[cur]+1;
}else{
pre[cur] = 1;
}
return pre;
},{})
console.log(resultObject);//{ a: 5, s: 4, f: 1, c: 3, w: 1, x: 1, r: 1, v: 1, z: 1, q: 1 }
let resultArray = stringArray.reduce((pre,cur,index,stringArray) => {
if(!pre.includes(cur)){
pre.push(cur);
}
return pre;
},[])
console.log(resultArray);
// [
// 'a', 's', 'f', 'c',
// 'w', 'x', 'r', 'v',
// 'z', 'q'
// ]