Array.from() : 用于将两类对象转化为数组
let arr1 = {
'1':'a',
'2':'b',
'3':'c',
length:3
}
let arr2 = Array.from(arr1)
arr2 ---- ['a','b','c']
Array.from() 还可以将对象中只有长度属性的转换成数组,得到的数组是多少长度的undefined的值
如果浏览器不支持这个写法,可以使用 Array.prototype.slice代替
const toArray = (() =>
Array.from ? Array.from : obj => [].slice.call(obj)
)();
Array.from()还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组
Array.from([1,2,3],(x) => x * x)
// 1 4 9
获取dom节点的文本内容
let span = document.querySelectorAll('span name')
let name = Array.from(span, s => s.textContent )
布尔值
Array.from( [1,,2,,3],(n) => n || 0 )
[1,0,2,0,3]
返回各种数据类型
function typeOf() {
return Array.from(arguments,value => typeof value )
}
typeOf( null, [] , NaN )
// [ 'object' , 'object' , 'number']
Array.from() 还有一个应用就是可以将 字符串 转化成 数组, 然后返回字符串的长度,
因为它能正确处理各种unicode字符
function countSymbols(string) {
return Array.from(string).length
}
---------------------------------------------------------------------------------------------------------------------------------------
扩展运算符(...)
使用扩展运算符也可以将对象转换成数组,
解构赋值的拷贝是浅拷贝,即如果一个键的值是复合类型的值( 数组,对象,函数) ,那么解构赋值拷贝的是这个值的引用,而不是这个值的副本
扩展运算符的应用:
1: 合并数组
var arr1 = ['a', 'b'];
var arr2 = ['c'];
var arr3 = ['d', 'e'];
// ES5的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]
// ES6的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
2: 与解构赋值结合,生成数组
// ES5
a = list[0], rest = list.slice(1)
// ES6
[a, ...rest] = list
如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报
对象的结构 赋值用于从一个对象取值,相当于将所有可遍历的,但尚未被读取的属性,分配到指定的对象上面.
所有的键和 他们的值,都会被拷贝到新对象上面
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
由于结构赋值要求等号右边是一个对象,所有如果等号右边是undefined和null,就会报错,因为他们无法转化成对象
let { x, y, ...z } = null; // 运行时错误
let { x, y, ...z } = undefined; // 运行时错误
解构赋值不会拷贝继承自原型对象的属性
let o1 = { a: 1 };
let o2 = { b: 2 };
o2.__proto__ = o1;
let o3 = { ...o2 };
o3 // { b: 2 }
解构赋值的一个用处,是扩展某个函数的参数,引入其他操作
function baseFunction({ a, b }) {
// ...
}
function wrapperFunction({ x, y, ...restConfig }) {
// 使用x和y参数进行操作
// 其余参数传给原始函数
return baseFunction(restConfig);
}
用于取出参数对象的所有可遍历属性,拷贝到当前对象之中
let z = { a: 3, b: 4 };
let n = { ...z };
n // { a: 3, b: 4 }
//等同于
let clone = Object.assign({},a)
合并两个对象
let ab = { ...a, ...b };
// 等同于
let ab = Object.assign({}, a, b);
如果用户自定义的属性,放在扩展运算符后面,则扩展运算符内部的同名属性会被覆盖
如果用户自定义的属性,放在扩展运算符前面,则变成设置新对象的默认值属性值
let aWithOverrides = { ...a, x: 1, y: 2 };
// 等同于
let aWithOverrides = { ...a, ...{ x: 1, y: 2 } };
// 等同于
let x = 1, y = 2, aWithOverrides = { ...a, x, y };
// 等同于
let aWithOverrides = Object.assign({}, a, { x: 1, y: 2 });
let aWithDefaults = { x: 1, y: 2, ...a };
// 等同于
let aWithDefaults = Object.assign({}, { x: 1, y: 2 }, a);
// 等同于
let aWithDefaults = Object.assign({ x: 1, y: 2 }, a);
扩展运算符的参数对象之中,如果有取值函数get
,这个函数是会执行的。
// 并不会抛出错误,因为x属性只是被定义,但没执行
let aWithXGetter = {
...a,
get x() {
throws new Error('not thrown yet');
}
};
// 会抛出错误,因为x属性被执行了
let runtimeError = {
...a,
...{
get x() {
throws new Error('thrown now');
}
}
};
如果扩展运算符的参数是null
或undefined
,这个两个值会被忽略,不会报错。
let emptyObject = { ...null, ...undefined }; // 不报错
3: 函数的返回值 如果函数需要返回多个值,就可以使用到扩展运算符
var dateFields = readDateFields(database);
var d = new Date(...dateFields);
4: 字符串 将字符串转换成真正的数组
[...'hello']
// [ "h", "e", "l", "l", "o" ]
5: 实现了Iterator接口的对象
var nodeList = document.querySelectorAll('div');
var array = [...nodeList];
6: Map, Set结构,Generator函数 扩展运算符内部调用的是数据结构的Iterator接口,因此只要有Iterator接口的对象都可以使用
Array.of() 用于将一组 值 转化成 数组
Array.of() [ ]
Array.of(undefined) undefined
Array.of(3,2,1) ===> [3,2,1]
Array.of(3) ====> [3]
Array.of(2,1).length ===> 2
Array.of() 总是把参数值组成数组,如果没有参数,则返回一个空数组
Array() 后面可以接数组,也可以什么都不接,什么都不接代表空数组,一个数代表长度,数值为空,多个数表示一个数组
copyWithin() 再当前数组内部,将指定位置的成员复制到其他位置上(原本数据会被覆盖)
Array.prototype.copyWithin( target , start = 0 , end = this.length )
target 必填 从该位置开始替换数据
start 可选 从该位置开始读取数据,默认值为0 ,如果为负数,表示倒数
end 可选 到该位置停止读取数据,默认等于数组长度,如果为负数,表示倒数
这三个参数都是数组,如果不是数组会自动转换成数值
find() findIndex()
find() 用于找出 第一个 符合条件的数组成员,它的参数是一个回调函数,所有数组
成员依次执行该回调函数,直到找出第一个返回值,返回该返回值,如果没有找到则
返回undefined
find() 的回调函数可以接受三个参数, 第一个为当前的值, 第二个为 当前值的位置
第三个是原数组
[ 1,2,3,10].find( (n) => n >9 )
// 10
[ 1,2,3,10].find( ( value , index , arr ) => return value)
//
findIndex() 返回第一个符合条件的数组成员的位置,如果没有成员符合条件,则返回-1
findIndex() 可以借助Object.is()来识别数组的NaN成员
fill() 给定值,填充数组
将数组中的元素全部抹去
['a', 'b', 'c'].fill(7)
// [7, 7, 7]
new Array(3).fill(7)
// [7, 7, 7]
fill() 还可以接受三个参数,第二个参数表示填充的起始位置, 第三个表示填充的结束位置
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']
entries() keys() values()
entries() 对键值对进行遍历
keys() 对键名进行遍历
values() 对键值进行遍历
三者可以是使用for ...of进行遍历
for ( let index of ['a],'b'].keys()) {
console.log(index) //0 //1
}
for ( let el of ['c','d'].values()){
console.log(el) //c //d
}
for ( let [index,value] of ['a','v'].entries()){
console.log(index,value) // 0 "a" // 1 "v"
}
如果不适用for ..of 循环,可以手动调用遍历器对象的next方法,进行遍历
let arr = ['1','2','3']
let entries = arr.entries()
console.log(entries.next().value) //[0.'1']
console.log(entries.next().value); // [1, '2']
console.log(entries.next().value); // [2, '3']
includes() 表示某个数组是否包含给定的值,与字符串的includes方法类似 返回一个布尔值
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
[1, 2, NaN].includes(NaN); // true
includes(n,m) m表示搜索的起始位置,如果值为负数表示倒数的位置,如果位置大于长度会重置为0
n表示搜索的数值
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
下面代码用来检查当前环境是否支持该方法,如果不支持,部署一个简易的替代版本。
const contains = (() =>
Array.prototype.includes
? (arr, value) => arr.includes(value)
: (arr, value) => arr.some(el => el === value)
)();
contains(["foo", "bar"], "baz"); // => false
数组的空位 空位指的是数组中的某个值为空,也就是没有任何值
注意 空位并不是Undefined , 一个位置的值是undefined,依然是有值的
es6明确将空位转为undefined, 空位不能忽略
Array.from() 方法将数组的空位转化为undefined,
扩展运算符(...) 也会将空位转化为undefined
copyWithin() 会连空位一个复制过去
fill() 将空位视为正常的数组位置
for ...or 循环的时候会连空位也一起循环遍历
entries() keys() values() find() findIndex() 都将空位视为undefined
由于空位的处理规则非常不统一,请避免出现空位