# JS 小知识点
# reduce
# 用法
语法:arr.reduce(callback,[initialValue])
参数为:
callback (执行数组中每个值的函数,包含四个参数)
1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
2、currentValue (数组中当前被处理的元素)
3、index (当前元素在数组中的索引)
4、array (调用 reduce 的数组)
initialValue (作为第一次调用 callback 的第一个参数。)
看一遍就知道怎么用了
var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
console.log(prev, cur, index);
return prev + cur;
});
console.log(arr, sum);
打印结果
由于没有设置返回值,reduce遍历的index从1开始
1,2,1
3,3,2
6,4,3
[1,2,3,4] 10
再看一下加了初始值的情况
var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
console.log(prev, cur, index);
return prev + cur;
}, 0);
console.log(arr, sum);
打印结果
由于加了初始值,遍历的index从0开始,pre的初始值等于initValue
0,1,0
1,2,1
3,3,2
6,4,3
[1,2,3,4] 10
# 应用
- 求和,求乘积
var arr = [1, 2, 3, 4];
var sum = arr.reduce((x, y) => x + y);
var mul = arr.reduce((x, y) => x * y);
console.log(sum); //求和,10
console.log(mul); //求乘积,24
- 计算数组元素出现的次数
let names = ["alice", "bob", "xiaoming"];
let nameNum = names.reduce((pre, cur) => {
if (cur in pre) {
pre[cur]++;
} else {
pre[cur] = 1;
}
return pre;
}, {});
- 数组去重
let arr = [1, 2, 3, 4, 5, 4];
function unique(arr) {
arr.reduce((pre, cur) => {
// 没出现过
if (!pre.includes(cur)) {
return pre.concat(cur);
} else {
return pre;
}
}, []);
}
console.log(unique(arr));
- 数组降维
let arr = [1, 2, [1, 2, 3, [1, 2, 3, 4, 45]]];
function flatern(arr) {
return arr.reduce((pre, cur) => pre.concat(Array.isArray(cur) ? flatern(cur) : cur), []);
}
# 剩余/扩展运算符
剩余/扩展运算符同样也是 ES6 一个非常重要的语法,使用 3 个点(...),后面跟着一个含有 iterator 接口的数据结构.
# 扩展运算符(存放数组 连接)
- 存放一个数组,然后展开。以数组为例,使用扩展运算符使得可以"展开"这个数组,可以这么理解,数组是存放元素集合的一个容器,而使用扩展运算符可以将这个容器拆开,这样就只剩下元素集合,你可以把这些元素集合放到另外一个数组里面
let arr = [1, 2, 3, 4, 5, 6];
let arr2 = [...arr, 6, 7, 8]; //[1,2,3,4,5,6,7,8]
- 代替 concat 方法
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
console.log([...arr1, ...arr2]); //[1,2,3,4,5,6]
# 剩余运算符(解构 代替 arguments)
- 代替了以前的 arguments(参数类数组)
function fun(a, b, c) {
console.log(arguments[0], arguments[1], arguments[2]);
}
func(1, 2, 3);
//es6
function fun1(...rest) {
consloe.log(rest); //[1,2,3]
}
fun1(1, 2, 3);
- 和数组解构赋值一起使用,但必须放最后一位
let [first, ...arr] = [1, 2, 3, 4, 5];
//first 1
// arr [2,3,4,5]
- 代替
Object.assign()
,合并对象
# object.assign
多个对象合并
let target = {};
let obj = Object.assign(target, { a: 1 }, { b: 2 });
obj; // {a:1,b:2}
# js 基本 api
# 数组添加元素(unshift push shift pop)
- unshift 数组头部添加元素
- push 数组尾部添加元素
- pop 删除尾部元素
- shift 删除第一个元素
let arr = [1, 2, 3, 4, 5];
arr.push(6); //[1,2,3,4,5,6]
arr.unshift(0); //[0,1,2,3,4,5,6]
arr.shift(); //[1,2,3,4,5,6,]
arr.pop(); // [1,2,3,4,5]
# 类型转换(显示转换 字符串数组转换)
# 显式转换
radix
(除了 undifined 或 null),mix
- 转换为数值型类型 :Nmuber(mix),parseInt(String,radix),parseFloat(String)
- 转换为字符串类型:toString(radix),String(mix)
- 转换为布尔类型:Boolean(mix)
# api 转换
经常需要将数组转换为字符串,或字符串转换为数组
join 数组转为字符串
let arr = [1, 2, 3, 4, 5]; arr.join("");
split 字符串转换为数组
let str = "1_2_3_4_5_6"; str.split("_"); // ['1','2','3','4','5','6']
# 数组相关操作(splice 下标 连接)
# splice
删除指定下标元素 arr.splice(index,num)
let arr = [1, 2, 3, 4, 5]; arr.splice(1, 1); // [1,3,4,5]
指定下标插入元素 arr.splice(start,num,'x','y') 删除元素为零个,向下标为 2 的前面插入元素
arr.splice(2, 0, 1, 1); //[1,2,1,1,3,4,5]
替换指定的下标元素 arr.splice(start,num,'x','y') start 开始,替换 num 各元素
arr.splice(1, 2, 1, 1); // [1,1,1,4,5]
# 寻找下标
arr.indexOf(key) - 返回 key 下标值,第一次出现,如果没有返回-1
findIndex(arr,key) - 返回 key 在 arr 的下标值
indexOf()
for (let i in this.cities) { this.cities[i].forEach(value => { if (value.pell.indexOf(this.keyword) > -1 || value.name.indexOf(this.keyword) > -1) { result.push(value); } }); }
findIndex()
let currentIndex = findIndex(item => { return item.id === song.id; }); //return 符合条件的index
# 连接数组
concat()
let arr = [1, 2, 3, 4, 5]; let arr1 = [6, 7, 8]; arr.concat(arr1); // [1,2,3,4,5,6,7,8]
...arr
[...ar, ...arr1];
扩展
- slice()
var a = [1, 2, 3];
console.log(a.slice(1)); // [2,3]
console.log(a.slice(0, 1)); //[1]
触底刷新
往往做下拉刷新的时候需要用到连接 concat()这个 api
searchMore () { this.showMore = true this.page++ getsearchSongs(this.query,this.page).then((res)=>{ let list = res.data.result.songs let ret = [] list.forEach((item)=>{ ret.push(ceateRecommendSong(item)) }) <!-- 关键步骤 --> this.songs.push(...ret)//this.songs.concat(ret) }) }
将数组改成自己想要的格式,重排
需求分析:将下面的返回的 artists 转换为一个数组分为一个 hot 区(前二十名歌手)和一个 singers 区(字母排序)
首先我们向把每个数组元素的item.name
的首字母提取出来,然后写一个方法传入 list,创建 map 对象,里面有hot对象
,遍历数组,当下标小于 20,向 hot 数组的 items 里面插入 new 的歌手对象。
const pinyin = require('pinyin')
getSingers().then((res)=>{
let s = res.data.list.artists
// name转为首字母
s.map((item)=>{
let py = pinyin(item.name[0]),{
style:pinyin.STYLE_FIRST_LETTER
}
}
item.initial = py[0][0].toUpperCase
)
})
然后就是map[key]
对象,先设置 key 为一开始提炼出来的首字母,然后同样创建map[key]
对象,向对象的 items 里面 push 歌手对象。
最后将 map 对象的 抽成出两个数组 ,一个 hot 一个 singers(需要对字符串进行排序)
_normalliaze(list){
let map ={
hot:{
title:'热门',
items:[]
}
}
// 热门中插入数据
list.forEach((item,index)=>{
if(index < 20) {
map.hot.items.push(new Singer({
...
}))
}
// map[key]插入数据
const key = item.initial
if(!map[key]){
map[key] = {
title:key,
items:[]
}
map[key].items.push(new Singer({...}))
}
})
// 抽成两个数组并排序
let hot= []
let singers = []
for(let key in map) {
let value = map[key]
if(value.title.match(/[a-zA-Z]/)){
singer.push(value)
}else{
hot.push(value)
}
}
singers.sort(a,b){
// 默认对字符串进行排序
return a.title.chartCodeAt(0) - b.title.charCodeAt(0)
}
return [...hot,...singers]
}
再来看一个经典案例
一维数组转为多维数组(行列自定义)
分析:要把数组转为多维数组,首先要设置行列数,然后行数除以列数就是多维数组的元素个数,将一维数组截断slice(0,col*row)
然后写核心算法,设置一个 row 初始为 0,当 row 小于行数时,返回的数组截断(row*this.col
,row*this.col
+this.col
)
computed(){
let arr = arr.slice(this.col*this.row)
let ret = []
let _row = 0
while(_row < this.row) {
ret.push(arr.slice(_row*this.col,_row*this.col + this.col))
_row ++
return ret
}else{
return []
}
}
# 类型判断(typeof Object.prototype.toString)
# typeof
通过typeof
操作符来判断一个值属于哪种基本类型
typeof "se";
typeof true;
typeof {};
typeof null; // 'object'
let a = [];
typepf(a); // 'object'
typeof {}; // 'object'
WARNING
typeof
判断会有误差,比如null
,array
,操作对象类型除了函数()都会得到object
的结果
# Object.prototype.toString() 推荐使用
js 判断数据类型的无敌解决办法
Object.prototype.toString.call({}); // '[object Object]'
Object.prototype.toString.call([]); // '[object Array]'
Object.prototype.toString.call(1); // '[Object Number]'
通常使用这个 API 要进行简单的封装
type(data){
let toString = Object.prototype.toString
let dataType = toString.call(data).replace(/\[object\s(.+)\]/,'$1').toLowerCase()
return dataType
}
type(1) //number
type([]) //array
...
# 空值判断
# 空数组判断
arr.length > 0
# 空对象判断
使用
Object.getOwnPropertyNames()
返回属性名组成的数组let obj = {}; Object.getOwnPropertyNames(obj).length === 0;
json 对象转为字符串
let obj = {}; Json.stringify(obj) === "{}"; //true
Object.keys()
类似返回属性名数组; Obejct.keyys(obj).length === 0;
直接使用对象属性判断
# 循环遍历操作数组(for forof forin forEach map)
- for 循环
//for
for (let i = 0; i < arr.length; i++) {
// arr[i]
}
//for in
for (let i in arr) {
// arr[i]
}
//for of
for (let i of arr) {
// i
}
for
循环就不用多说了,for in
循环遍历常常用来遍历对象如下例,for of
循环使用了迭代器,直接可打印出各个元素
区别:
- for 循环和 for of 循环不能遍历到非数字属性。
- for in 循环可以取到数组中的空元素,for 循环 for of 循环不会跳过,会打印出 undefined
for (let i in map) {
map[i]; //拿到对象的每个值
}
- map filter forEach
- forEach 遍历可以拿到
item
,index
,然后进行操作,基本上遍历数组都是用 forEach
let arr = [1, 2, 3, 4, 5];
arr.forEach((item, index) => {
item; // 1,2,3,4,5
index; // 0,1,2,3,4
});
- map 返回一个经过操作的新数组
let arr = [1,2,3,4,5]
arr.map((item)=>{
return item+1;
})
// arr [2,3,4,5,6]
filter(music){
let name =[]
name = music.map((item)=>{
return item.name
})
return name.join('/')
}
filter 返回一个符合条件的数组,也是新数组
let arr = [1, 2, 3, 4, 5]; arr.filter(item => { return item > 3; }); //arr [4,5]
# 字符串截断(slice substr substring)
slice() substr() substring() 他们之前的区别
总结的说:
slice(start,end) 正数截取 start 到 end 之间的数,前闭后开
特殊情况:
- 负数的话,会将其作为倒数几个进行截取
- 第一个数大于第二个参数,返回 ''
substr(start,num) 从 start 位置截取 num 个字符
特殊情况:
start
为负数,会倒过正向截取 len 个数len
为负数,返回""
substring(start,end) 正数截取 start 到 end 之间的数,前闭后开
特殊情况:
- 第一个参数大于第二个参数,将参数交换进行截取
- 参数有负数,转为 0
var str = "1m2mgfdgfdgfgdggerererwe";
str.substr(3, 3); //"mgf"
str.substr(3, -3); //""
str.substr(-3, 3); //"rwe"
str.substring(3, 4); //"m"
str.substring(3, -4); //"1m2"
str.substring(-3, -4); //""
str.substring(-3, 4); //"1m2m"
str.slice(-3, 4); //""
str.slice(3, 6); //"mgf"
str.slice(6, 3); //""
str.slice(3, -6); //"mgfdgfdgfgdgger"