玩转数组高级应用

批量制造数据

fill + map

function createData(){
	return new Array(1000).fill(null)
		.map((v,i) => ({name: `name ${i + 1}`}))
}
const data = createData();

Array.from

function createData() {
	return Array.from({length: 1000}, (v,i) => 
		{ name: `name${i + 1}`}
	)
}
const data = createData()

数组去重

set

  • 对象不能去重
const arr1 = [1, 2, 3];
const arr2 = [3, 4, 5];

console.log(new Set([...arr1, ...arr2]));

非set

  • 不能对NaN去重
function mergeArray(arr1, arr2){
	// 克隆
	var arr = arr1.slice(0);
	var v;
	for(let i = 0; i < arr2.length; i++){
		v = arr2[i];
		if(~arr.indexOf(v)){
			continue;
		}	
		arr.push(v);
	}
	return arr;
}

类数组

  • 数组对象字面量
  • new Array
  • Array.from(ES6)
  • Array.of(ES6)
  • Array.prototype.slice
  • Array.prototype.concat

类数组:是有一个length属性和从零开始索引的属性,但是没有Array的内置方法,比如forEach()和map()等一种特殊对象

  • 普通对象
  • 必须有length属性,可以有非负整数索引
  • 本身不具备数组所具备的方法

常见的类数组 - arguments
常见的类数组 - DOM相关:NodeList, HTMLCollection,DOMTokenList
字符串:具备类数组的所有特性,但是类数组一般是指对象

数组类数组
自带方法多个方法
length
instanceofArrayObject
constructor[Function: Array][Function: Object]
Array.isArraytruefalse
// 严格判断类数组
function isArrayLikeObject(arr){
	if(arr == null || typeof arr !== 'object')
	return false;
	const lengthMaxValue = Math.pow(2, 53) -1;
	if(!Object.prototype.hasOwnProperty.call(arr, 'length'))
	return false;
	if(typeof arr.length != 'number') return false;
	if(!isFinite(arr.length)) return false;
	if(Array === arr.constructor) return false;
	
	if(arr.length >= 0 && arr.length < lengthMaxValue){
		return true
	}else{
		return false
	}
}

类数组如何转化为数组

  • slice,concat等
  • Array.from
  • Array.apply
  • 复制遍历

数组注意事项

数据长度与空元素

// 末尾的逗号表示可添加
const arr1 = [1,];
const arr2 = [1, ,]
const arr3 = new Array('10')
const arr4 = new Array(10)

console.log(arr1.length) // 1
console.log(arr2.length) // 2
console.log(arr3.length) // 1
console.log(arr4.length) // 10

数组空元素:empty 数组的空位,指数组的某一个位置上没有任何值。简单来说,就是数组上没有对应的属性
一般的遍历,自动跳过空位,forEach,reduce等

  • Join和toString 空位 视为空字符串

稀疏数组: 有空元素的数组,就是稀疏数组

如何避免创建稀疏数组

  • Array.apply(null, Array(3))
  • […new Array(3)]
  • Array.from(Array(3))

数组不会自动添加分号
( [ + - / 作为一行代码的开头,很可能产生意外的情况,所以没事代码最后写个分号,准保没错

indexOf 与 includes

方法返回值能否查找NaN[ , , ]undefined
indexOfnumber
includesboolean

数组可变长度问题

  • length 代表数组中元素个数,数组额外附加属性不计算在内
  • length 可写,可以通过修改length改变数组的长度
  • 数组操作不存在越界,找不到下标,返回undefined

数组查找或者过滤

方法返回结果类型返回短路操作是否全部满足遍历空元素
someboolean
findundefined
findIndexnumber
everyboolean
filterarray

数组操作非线形存储问题

  • 数组默认存储为线形存储
  • 存储结构改变必然产生不必要代价,我们尽量线性递增

数组高级用法

万能数据生成器

const createValues = (creator, length = 10) => Array.from({length}, creator)

随机数生成器

const createRandomValues = (len) => createValues(Math.random, len);

序列生成器

const createRange = (start. stop, step) =>
createValues((_, i) => start + (i * step), (stop - start)/ step + 1)

数据生成器

function createUser(v, index){
	return {
		name: `user-${index}`,
		age: Math.random() * 100 >> 0
	}
}

清空数组

  • Array.prototype.slice(0)
  • Array.prototype.length = 0

数组去重

  • Array.from(new Set(arr)) 问题:对于属性键和属性值都相同的对象没有作用
  • Array.prototype.filter + key 唯一 问题:如何确保key唯一

求交集

  • Array.prototype.filter + includes 判断 问题:1.引用类型相同的判断 2.性能问题
function intersectSet(arr1, arr2){
	return [..new Set(arr1)].filter(item => arr2.includes(item))
}
  • 引用数据:Array.prototype,forEach + Map + key 唯一
  • 基础数据:Array.prototype.forEach + Map + filter
// 引用类型
function intersect(arr1, arr2, key){
	const map = new Map();
	arr1.forEach(val => map.set(val[key]))

	return arr2.filter(val =>{
		return map.has(val[key]);
	})
}

// 原始类型
function intersectBase()(arr1, arr2){
	const map = new Map();
	arr1.forEach(val => map.set(val))

	return arr2.filter(val =>{
		return map.has(val);
	})
}

从数组中删除虚值

  • Array.prototype.filter(Boolean)

获取数组中最大值和最小值

  • Math.max.apply(Math, numArray)
  • Math.min.apply(Math, numArray)

queryString

  • 作用:页面传递参数
  • 规律:地址url问号拼接的键值对
    现代Web API查询queryString: URLSearchParams、URL
const urlSP = new URLSearchParams(location.search);
function getQueryString(key){
	return urlSP.get(key)
}
const urlObj = location.search.slice(1)
	.split("&")
	.filter(Boolean)
	.reduce(function(obj, cur){
		var arr = cur.split("=");
		if(arr.length != 2){
			return obj;
		}
		obj[decodeURLComponent(arr[0])] = decodeURLComponent(arr[1]);
		return obj;
	},{})

compose封装

function compose(...funcs){
	if(funcs.length === 0){
		return arg => arg
	}
	return funcs.reduce((a,b) => (...args) => a(b(...args)))
}

runPromises封装

function runPromises(promiseCreators, initData){
	return promiseCreators
	.reduce(function(promise,next){
		return promise.then((data) => next(data))
	}, Promise.resolve(initData))
}

手写数组方法

Array.isArray

Array.isArray = function(obj){
	return Object.prototype.toString.call(obj) === '[object Array]';
}

Array.prototype.entries

  • 作用:返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对, 可以用next 和 let of 遍历
Array.prototype.entries = function() {
	const O = Object(this);
	let index = 0;
	const length = O.length;
	function next(){
		if(index < length){
			return { value: [index, O[index++], done: false]}
		}
		return { value: undefined, done: true }
	}
	
	return {
		next,
		[Symbol.iterator](){
			return{
				next
			}
		}
	} 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值