主要讲解ES6中的一些新扩展的内容(与ES5/ES3对比),主要包括字符串的扩展、正则的扩展、数值的扩展、函数的扩展,对象的扩展,以及数组的扩展等。
一.字符串扩展
1.模板字符串
模板字符串:` string `;
字符串拼接:` strings....... ${ this.str } strings......`
${........}内还可以嵌套模板字符串:` strings....... ${ `strings....${ this.str }` } strings......`
const xiaoming = {
name: "xiaoming",
age: 14,
say1: function () {
console.log(
"我叫" + this.name.toUpperCase() + ",我今年" + this.age + "岁!"
);
},
say2: function () {
// console.log(`我叫`+this.name+`,我今年`+this.age+`岁!`);
console.log(`我叫${this.name.toUpperCase()},我今年${this.age}岁!`);
console.log(
`我叫${`Mr.${this.name.toUpperCase()}`},我今年${this.age}岁!`
);
},
};
xiaoming.say1();
xiaoming.say2();
实例:
const getImoocCourseList=function(){
//ajax
return {
status:true,
msg:'获取成功',
data:[{
id:1,
title:'Vue 入门',
date:'xxxx-01-09'
},{
id:2,
title:'ES6 入门',
date:'xxxx-01-10'
},{
id:3,
title:'React 入门',
date:'xxxx-01-11'
}]
}
};
const {data:listData,status,msg}=getImoocCourseList();
function foo(val){
return val.replace('xxxx','xoxo');
}
if(status){
let arr=[];
listData.forEach(function({date,title}){
// arr.push(
// '<li>\
// <span>'+title+'</span>'+
// '<span>'+date+'</span>\
// </li>'
// );
//可替换为,更方便
arr.push(
`
<li>
<span>${ `课程名:${title} `}</span>
<span>${ foo(date).toUpperCase() }</span>
</li>
`
);
});
let ul=document.createElement('ul');
ul.innerHTML=arr.join('');
document.body.appendChild(ul);
}else{
alert(msg);
}
2.字符串相关的部分新方法
(1)padStart padEnd:字符串补全
str1.padStart(length, string );
str1.padEnd (length, string );
{
let str = 'i';
let str1 = str.padStart(5,'mooc');//mooci
// let str1 = str.padStart(9,'mooc');//moocmooci
console.log(str1);
let str2 = str.padEnd(5,'mooc');//imooc
// let str2 = str.padEnd(9,'mooc');//imoocmooc
console.log(str2);
}
(2)repeat:重复字符串
str.repeat(num); num >=0,向下取整( -1~0之间取0 );
str:重复的字符串,num:重复的遍数。
{
console.log('i'.repeat(10));//不能是负数,小数取整
function repeat(str,num){
return new Array(num+1).join(str);
}
console.log(repeat('s',3));
}
(3)startsWith endsWith:是否以字符串开头/结尾;
{
const str='dasuiahduiahdua';
console.log(str.startsWith('d'));//true
console.log(str.startsWith('a'));//false
console.log(str.endsWith('a'));//true
console.log(str.endsWith('s'));//false
}
(4)includes:是否包含字符串
str.includes(str);
{
const str='A promise is a promise';
console.log(str.includes('a promise'));//true
console.log(str.includes('ppp'));//false
}
3.for-of遍历方式
(1)ES6之前遍历字符串的方式
①使用for循环:
let str='PROMISE';
for(var i=0,len=str.length;i<len;i++){
console.log(str[i]);
console.log(str.charAt(i));
}
②转成数组后遍历:
转成数组的方法(4种):
var oStr = Array.prototype.slice.call(str);
var oStr = str.split('');
const oStr = [...str];
const [...oStr] = str;
let str='PROMISE';
// var oStr = Array.prototype.slice.call(str);
var oStr = str.split('');
// const oStr = [...str];
//const [...oStr] = str;
console.log(oStr);
oStr.forEach(function(word){
console.log(word);
});
(2)有时候遍历是为了操作字符串
例如:对全是英文字符串中的大写字符加密 A->100 B->99......
let str='PROMISE';
var oStr = str.split('');
const map={A:'100',B:'99',E:'96',I:'92',M:'88',O:'86',P:'85',R:'83',S:'82'};
const words='ABCDEFGHIGKLMNOPQRSTYVWXYZ';
oStr.forEach(function(word,index){
if(words.includes(word)){
oStr[index]=map[word];
}
});
console.log(oStr.join(''));//85838688928296
(3)使用for- of遍历字符串
let str='PROMISE';
for(let word of str){
console.log(word);
}
同样是加密,更简单的写法:
let str='PROMISE';
const map={A:'100',B:'99',E:'96',I:'92',M:'88',O:'86',P:'85',R:'83',S:'82'};
const words='ABCDEFGHIGKLMNOPQRSTYVWXYZ';
let newStr='';
for(let word of str){
if(words.includes(word)){
newStr+=map[word];
}
}
console.log(newStr);//85838688928296
4.新的Unicode表示法
unicode:是一项标准,包括字符集,编码方案等,通过统一编号去识别字。
它是为了解决传统的字符编码方案的局限而产生的,为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
JS解析器一般只能解析\u码点后面的四位数,所以ES6里面提供在code码外面加一个花括号,例子请见截图
如:`\u{1f436}`
(1)codePointAt()
获取字符串中对应字符的一个码点,结果一般要转换16进制.toString(16)
(2)at()
根据下标取字符,Chrome浏览器不支持。(虽然不支持,但是可以通过工具编译代码,把编译代码编译 成ES5或ES3)
二.正则扩展
1.正则构造函数的变化:
new RegExp(/a/g , 'i');
这种形式在ES6之前是会报错的,但是在ES6中,后声明的修饰符‘i’会覆盖前面的修饰符‘g’。不论有多少个修饰符,后面的都会覆盖前面的。
const regexp1=/^a/g;//^a开头为的字符串
const regexp2=new RegExp('^a','g');
const regexp3=new RegExp(/a/g);
const regexp4=new RegExp(/a/);
console.log('aabbcc'.match(regexp1));//['a']
console.log('babbcc'.match(regexp1));//null
console.log('aabbccaabb'.match(regexp3));//['a','a','a','a']
console.log('aabbccaabb'.match(regexp4));//['a']
//构造函数的变化
const regexp5=new RegExp(/a/giuy,'ig');
2.u修饰符:表示unicode字符
0x开头表示十六进制。十六进制的0000相当于二进制的16个零,十六进制的FFFF就相当于二进制的16个1。
一个字节等于8位,所以d83d是十六为是2个字节。\ud83d\udc36是四个字节。
而这两个都是一个字符。这里字节与字符无法成比例计算,所以可以理解为一个整个是一个字符。
console.log(/^\ud83d/.test('\ud83d\udc36'));
console.log(/^\ud83d/u.test('\ud83d\udc36'));
3.y:粘连修饰符(sticky)
y和g一样,会把字符串中所有满足条件的都匹配出来。
不同在于y要保证从上一个匹配结果的索引开始就满足匹配条件,这样才会进行下一次的匹配,否则匹配结束。
这里的r1会匹配出3个“imooc”,r2会匹配出2个“imooc”。
const r1 = /imooc/g;
const r2 = /imooc/y;
const str = 'imoocimooc-imooc';
console.log(r1.exec(str));
console.log(r1.exec(str));
console.log(r1.exec(str));
console.log(r1.exec(str));
console.log('----------------------------------');
console.log(r2.exec(str));
console.log(r2.exec(str));
console.log(r2.exec(str));
三.数值扩展
1.新的进制表示法
0o 0O octonary 八进制
0b 0B binary 二进制
console.log(0o16);//14
console.log(0b1111);//15
2.新的方法与安全数
(1)Number.parseInt Number.parseFloat
ES6中:parseInt()和parseFloat()方法从window上挂载到了Number上,其它没有太多区别。
//window可带可不带
console.log(window.parseInt('1.23'));//1
console.log(parseFloat('1.23'));//1.23
//--ES6中:
console.log(Number.parseInt('1.23'));//1
console.log(Number.parseFloat('1.23'));//1.23
(2)Number.parseInt Number.parseFloat
ES6中:isNaN()和isFinite()也是挂载到了Number上。
因为NaN有一个特性:NaN是不等于NaN的,我们可以利用这个特性来判断一个值是不是NaN。
return value !== value;
console.log(Number.isNaN(NaN));//true
console.log(Number.isNaN(-NaN));//true
console.log(Number.isNaN(1));//false
console.log(Number.isNaN('1'));//false
console.log(Number.isNaN(true));//false
function isNaN(value){
return value!==value;
}
console.log(isNaN(NaN));//true
console.log(isNaN(-NaN));//true
console.log(isNaN(1));//false
console.log(isNaN('1'));//false
console.log(isNaN(true));//false
isFinite()判断一个值是不是有限的。
console.log(Number.isFinite(Infinity));//false
console.log(Number.isFinite(2/0));//false
console.log(Number.isFinite(2/4));//true
console.log(Number.isFinite(1234));//true
console.log(Number.isFinite('1234'));//false
console.log(Number.isFinite(true));//false
console.log(Number.isFinite(NaN));//false
(3)Number.isSafeInteger()
isSafeInteger()方法判断数值是否处在JS能够精确表示的范围之内。(判断整数)
范围在Math.pow(2,53)-1和Math.pow(22,53)-1之内,这两个值在ES6中分别放在了MAX_SAFE_INTEGER和MIN_SAFE_INTEGER这两个常量上。
2的53次方-1和-2的53次方-1
Number.MAX_SAFE_INTEGER Number.MIN_SAFE_INTEGER
console.log(Number.MAX_SAFE_INTEGER);//9007199254740991
console.log(Number.MIN_SAFE_INTEGER);//-9007199254740991
console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER-1));//true
console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER+1));//false
(4)幂运算:新的运算符 **
不是新的方法,是新的运算符。
let a=2**10;//1024
console.log(a);
let b = 2 ** 10 ** 0;
console.log(b);//2
幂运算的运算规则是右结合的(从右往左计算),所以想要按从左到右的顺序,必须得在前面加括号运算。
let a = 2 ** 10 ** 0;//返回结果是2,因为是右结合的,从右往左计算。
let a = (2 ** 10)** 0;//返回结果1,加上括号后,从左往右计算。
ES6对Math对象进行扩展,有一些新的方法。(自主学习)
四.函数扩展
1.默认参数
除了函数传参解构赋值的时候可以给默认值,函数的参数也可以直接给默认值。
在默认值中还可以给一个简单的表达式。但是要注意表达式中不能出现后面声明的变量,只能是前面已经出现的变量,并且也不能是被赋值的变量本身。
function add(a,b=999+a,c=1){
//涉及到的参数只能是出现在前面的,否则会报错。例如:b=999+b,b=999+c都会报错
console.log(a,b,c);
}
add(3);//3 1002 1
可以把函数参数的默认值和解构赋值结合起来使用。
使用参数默认值时,函数不能有同名参数,否则就报错.
function People({name,age=28}={name:1}){
console.log(name,age);
};
People({name:'小明'});//'小明' 28
2.与扩展运算符的结合(剩余参数…)
以前当函数的参数不固定时,我们需要使用arguments。
使用Array.prototype.slice.call(obj)方法可以将一个类数组对象转换成数组。
function sum(){
let args=Array.prototype.slice.call(arguments);
// let args=[...arguments];
// let [...args]=arguments;
console.log(args);
}
sum(1,2,34,56,78,'hrr');//[1,2,34,56,78,'hrr]
虽然形式上都是三个点,但是剩余参数是做聚合的,扩展运算符是做展开的。
function sum(...args){
console.log(args);
}
sum(1,2,34,56,78,'hrr');
剩余参数必须要写在最后一个,实际应用中可以根据前面的参数不同,对后面的剩余参数做不同的操作,比如各种不同类型的运算。
function op(type,b,...nums){
console.log(type);
console.log(b);
console.log(nums);
}
op('sum',1,2,45,86,321,546,89);
//sum
//1
//[2, 45, 86, 321, 546, 89]
reduce()方法接收两个参数。
第一个是回调函数,回调函数也有两个参数a、b。a是表示的是回调函数上一次return的值,b就是当前遍历到的项。
第二个参数是第一次遍历时a的值。
function sum(...numbers) {
return numbers.reduce(function (a,b) {
return a+b;
},0);
}
console.log(sum(1,4,2,5));//12
Rest 解构赋值不会拷贝继承自原型对象的属性。
3.箭头函数(=>)
(1)箭头函数和普通函数对比
函数的参数如果只有一个,可以把括号去掉;
箭头后面的表达式虽然没写return但是会直接return值;
如果函数体内要有多条执行语句,可以使用大括号,但是要记住用return返回值。
const add1 = (a,b)=>{
a+=1;
return a+b;
};
const add2=function(a,b){
a+=1;
return a+b;
}
console.log(add1(2,4));//7
console.log(add2(2,4));//7
当我们不需要返回值,但是语句只有一条的时候,不想用大括号来写。
有个小技巧:在语句前面加void这个关键字就不会返回值,打印为undefined。
const pop1=arr => arr.pop();
const pop2=arr => void arr.pop();
console.log(pop1([1,2,3]));//3
console.log(pop2([1,2,3]));//undefined
(2)箭头函数和普通函数的区别:
①箭头函数没有arguments这个参数,需要用扩展运算符拿到所有的值。
②箭头函数没有自己的this。this是在函数定义的时候所处的环境当中的this。
const log1=()=>{
console.log(arguments);
}
// log1(1,2,3);//报错
const log2=(...args)=>{
console.log(args);
}
log2(1,2,3);//[1,2,3]
const xiaoming={
name:'小明',
say1:function(){
console.log(this);
},
say2:()=>{
console.log(this);
}
}
xiaoming.say1();//指向xiaoming
xiaoming.say2();//指向window,当前环境是xiaoming,xiaoming是window的
(3)方便的点
如下:因为setTimeout定时器是window下的自执行方法,所以this指向的是window,
如果想要访问到xiaoming{……}中的age,需要让this指向当前作用域,方法是在setTimeout之前将this保存一下。
const xiaoming1={
name:'xiaoming',
age:null,
getAge:function(){
let _this_=this;
//ajax
setTimeout(function(){
_this_.age=66;
console.log(this);//指向window
console.log(_this_);//指向xiaoming1
},1000);
}
};
xiaoming1.getAge();
页面中单独有定时器的时候,打开页面就可以被调用,可以理解为是window调用的定时器,所以定时器中的this指向的是window。
在这里对象中也是一样的,虽然定时器在getAge方法中,但是还是window调用的,所以输出this指向的是window。
如果想this指向对象,需要在定时器前面接收this,然后在定时器中使用。记住这样使用就可以。
const xiaoming={
name:'xiaoming',
age:null,
getAge:function(){
//ajax
setTimeout(()=>{
this.age=14;
console.log(this);//指向xiaoming,当前环境是getAge(),getAge()是xiaoming的
},1000);
}
};
xiaoming.getAge();
五.对象扩展
1.简洁表示法与属性名表达式
(1)简洁表示法
ES6中对象的写法非常简洁,直接通过变量名去查找同名变量并且拿到它的值,方法可以省去:function。
const getUserInfo = (id=1)=>{
//ajax...
const name='小明';
const age=10;
return {
// name:name,
// age:age,
// say:function(){
// console.log(this.name+this.age);
// }
//可简化为:
name,
age,
say(){
console.log(this.name+this.age);
}
};
};
const xiaoming=getUserInfo();
console.log(xiaoming);//{name: "小明", age: 10, say: ƒ}
(2)属性名表达式
属性名可以是常量、变量,也可以是表达式,还可以是模板字符串,但是都要用[]括起来。
属性名表达式与简洁表示法,不能同时使用,会报错。
const obj={
a:1,
$abc:2,
'FDASHgyaub$#$%^$*^%$':3 //取用时不能用obj. 必须是obj[]
};
const key='age';
const sum='sum';
const xiaoming={
name:'xiaoming',
[key]:14,
[`${sum}123`]:50
};
console.log(xiaoming);//{name: "xiaoming", age: 14, sum123: 50}
2.部分新方法与扩展运算符
(1)复制对象
扩展运算符在复制对象的时候是浅拷贝的。
这里经过 cObj1.d.aa = 999; 之后,obj1.d.aa的值也改为999了,说明是浅拷贝,只是复制了对象的引用,没有复制到对象中的数据。
const obj1={
a:1,
b:2,
d:{
aa:1,
bb:2
}
};
const cObj1={...obj1};
console.log(cObj1.d.aa);//1
cObj1.d.aa =999;
console.log(cObj1.d.aa);//999
console.log(cObj1.d.aa);//999
(2)合并对象
合并对象时,相同属性名的值由最后的对象决定。
合并对象也是浅拷贝。
const obj1={
a:1,
b:2,
d:{
aa:1,
bb:2
}
};
const obj2={
c:3,
a:9
}
const newObj={
...obj1,
...obj2
}
console.log(newObj);
newObj.d.aa=22;
console.log(obj1);
(3)对象提供的新方法:
Object.is() 其实跟全等(===)差不多,严格等于。
接收两个参数,如果两个参数相等,返回true,否则false。
只有在判断NaN和NaN, +0和-0上有差别
console.log(Object.is(+0,-0));//false
console.log(+0 === -0);//true
console.log(Object.is(NaN,NaN))//true
console.log(NaN === NaN);//false
Object.assign() 在赋值或者合并对象的时候是很常用到的,也是浅拷贝。
const obj2 = Object.assign({a:1},{b:2},{c:3},{d:4,e:5});//{a: 1, b: 2, c: 3, d: 4, e: 5}
const obj={
a:1,
b:{
c:2
}
};
let newObj=Object.assign({a:3},obj);
console.log(newObj.b.c);//2
newObj.b.c=100;
console.log(obj.b.c);//100
Object.keys(obj) 返回对象自身属性名组成的数组。
Object.values(obj) 返回对象自身属性值组成的数组。
Object.entries(obj) 返回对象自身每一对可枚举的key和value所组成的数组的数组。
const obj={
a:1,
b:2,
c:3,
d:4
};
console.log(Object.keys(obj));//["a", "b", "c", "d"]
console.log(Object.values(obj));//[1, 2, 3, 4]
console.log(Object.entries(obj));//[["a", 1],["b", 2], ["c", 3],["d", 4]]
0: (2) ["a", 1]
1: (2) ["b", 2]
2: (2) ["c", 3]
3: (2) ["d", 4]
3.新的方法
(1)proto
__proto__ 这个属性代表当前对象的原型,实际开发中尽量不要用到,调试的时候看看即可。
(2)Object.setPrototypeOf(obj , obj2)
用来修改对象的原型,obj :想要修改的对象,obj2:作为新的原型的对象
这个方法的性能不好,建议不要使用。
const obj1={
a:1
};
const obj2={
b:1
};
const obj=Object.create(obj1);
console.log(obj.__proto__);//{a: 1}
Object.setPrototypeOf(obj,obj2);
console.log(obj.__proto__);//{b: 1}
(3)Object.getPrototypeOf(obj)
拿到对象的原型对象。
const obj1={a:1};
const obj=Object.create(obj1);
console.log(obj.__proto__);//{a:1}
console.log(Object.getPrototypeOf(obj));//{a:1}
console.log(obj.__proto__===Object.getPrototypeOf(obj));//true
(4)super
super 不是一个方法,是一个关键字,可以访问当前对象的原型,指向的是当前对象(this指向的对象)的原型对象。
const obj={name:'xiaoming'};
const cObj={
say(){
console.log(`My name is ${super.name}`);
}
}
Object.setPrototypeOf(cObj,obj);
cObj.say();//My name is xiaoming
但是要注意这里是say函数用普通的写法和箭头函数的写法都是不能让super起作用,只能用对象的直接表示法去声明这个say方法才能调用super。
六.数组扩展
1.和扩展运算符结合
(1)通过扩展运算符去展开数组,作为函数的参数。
function foo(a,b,c){
console.log(a);
console.log(b);
console.log(c);
}
foo(...[1,3,2]);//1 3 2
之前都是使用apply来实现把数组作为函数参数传入,基本上所有的函数都可以调用apply。
推荐使用扩展运算符的方式。
const user=['小明',14,['唱歌','打游戏'],'我上六年级了'];
function say(name, age, hobby,desc) {
console.log(`我叫${ name },我今年${ age }岁了,我喜欢${ hobby.join('和') },${ desc }`);
}
// say(user[0],user[1],user[2],user[3]);
say(...user);
say.apply(null,user);
console.log(Math.max(...arr);
console.log(Math.max.apply(null,arr);
(2)通过扩展运算符去复制或者合并数组
const arr1=[1,2,3,4];
const arr2=[4,3,2,5];
const arr3=[2.2,'123',false];
const cArr1=[1,2,3,...arr3];//合并
const cArr2=[...arr1];//复制
const [...cArr3] = arr3;//复制
const cArr4=[...arr1,...arr2,...arr3];//合并
(3)扩展运算符可以将生成器函数传出来的值作为数组对象形成数组
关于生成器,参考教辅《生成器函数》。
生成器函数可以通过yield关键字就可以暂停函数的执行。
function *g(){
console.log(1);
yield 'hi~';
console.log(2);
yield 'imooc~';
}
const arr=[...g()];//arr=["hi~", "imooc~"]
const gg=g();
gg.next();
setTimeout(function(){
gg.next();
},1000);
(4)ES6提供的新的数据结构set
就是集合,它也可以使用扩展运算符把它转成一个数组。
set有一个特性,它里面的元素是不能重复的。
通过set可以完成去重,然后转换成数组。
let set=new Set([1,2,2,5]);
console.log(set);//Set(3) {1, 2, 5}
console.log([...set]);//[1, 2, 5]
2.新的方法
(1)Array.from:将类数组对象转换成数组。
from()方法的作用是将一个ArrayLike对象或者Iterable对象转换为一个Array.
该类数组对象的属性名必须为数值型或字符串型的数字。
length:2决定了最后转换的数组长度,会根据长度去取舍类数组对象的属性。
该方法还可以有第2个参数,第2个参数是回调,可以对类数组的每一项进行一些操作。比如这里就是对类数组每一项的值乘以2。
const obj = {
0:1,
1:'22',
2:false,
length:2
};
console.log(Array.from(obj));//[1, "22"],因为length:2,根据长度取舍,只有前两个
console.log(Array.from(obj, item => item*2));//[2, 44]
类数组对象的属性名必须为数值型或字符串型的数字,要将一个类数组对象转换为一个真正的数组,必须具备以下条件:
①该类数组对象必须具有length属性,用于指定数组的长度。如果没有length属性,那么转换后的数组是一个空数组。
②该类数组对象的属性名必须为数值型或字符串型的数字。
该类数组对象的属性名可以加引号,也可以不加引号。
还有其它的将类数组对象转成数组的方式:
Array.prototype.slice.call();
[].slice.call();
[...obj]
但是只有Array.from方法可以通过第2个参数对数组项进行操作。
(2)Array.of:把传进去的参数合成数组再返回。
console.log(Array.of(1,2,'123',false));//[1, 2, "123", false]
(3)Array#fill:填充数组并指定范围
Array#fill:非静态方法,可以填充数组并指定范围。
let arr = new Array(10).fill(1,0,3);
fill方法的后两个参数用来指定填充范围。这里指定从0到3下标的数组项(3不算),也就是0、1、2的数组项用1填充。
注意:如果数组中本来就有值,通过fill填充后,会把原来对应的所有值都覆盖掉。
let arr= new Array(10).fill(1,0,3);
console.log(arr);//[1, 1, 1, empty × 7]
console.log([1,2,3].fill(0));//[0,0,0]
new Array这个构造函数会根据参数进行重载,只有一个参数时表示数组的长度,有多个参数就会作为数组的成员。我们无法在调用构造函数的时候有很好的方式填充默认值,所以现在有fill方法就会很方便地指定数组的所有参数的默认值。
(4)Array.includes:检测数组中是否包含某一项
跟字符串的includes很像,检测数组中是否包含某一项。有为true,没有是false。
var arr=[1,2,3,4];
console.log(arr.includes(1));//true
console.log(arr.includes(55));//false
(5)keys、values、entries
keys:拿到数组的索引值。
values:拿到数组的每一项值。
entries:跟Object.entries()很类似,得到数组每一项下标和下标对应值组成的数组。
const arr=[1,27,6];
//keys
console.log(arr.keys());//Array Iterator {} 迭代器
for(let i of arr.keys()){
console.log(i); //0 1 2
}
//values
for(let j of arr.values()){
console.log(j); //1 27 6
}
//entries
for(let k of arr.entries()){
console.log(k); //[0,1] [1,27] [2,6]
}
(6)find:根据条件(回调函数)按顺序遍历数组,当回调返回true时就返回当前遍历到的值。
const res=[1,7,6,3].find((value,index,arr)=> value%2===0);//value是值,index是下标
//等同于
/*
const res=[1,7,6,3].find(function(value,index,arr){
return value%2===0;
};
*/
console.log(res);//6
(7)findIndex:根据条件(回调)按顺序遍历数组,当回调返回true时就返回当前遍历到的下标。
和find类似,只不过find返回的是值,findIndex返回的是下标。
const res=[1,7,6,3].findIndex((value,index,arr)=> value%2===0);
console.log(res);//2
indexOf()不能判断NaN,但是findIndex可以。
const res=[1,7,6,3,NaN].findIndex((value,index,arr)=> Number.isNaN(value));
console.log(res);//4
关于数组的新方法,可以参考教辅《新方法总结》。