六、数组热闹的循环
新增方法有:arr.forEach() 、arr.map() 、arr.filter()、arr.some()、arr.every() 、arr.reduce()、arr.reduceRight()、for...of循环
注意:arr.forEach() 、arr.map() 、arr.filter()、arr.some()、arr.every()的回调函数接收参数一致,都是(val,index,arr),但是她们整体可以接收两个参数,如下格式
arr.forEach/map...(循环回调函数,this指向)
//这里this指向的是window对象,这个方法一般不用
let arr = ['apple','banana','orange','tomato'];
arr.forEach(function(val,index,arr){
console.log(this,val,index,arr);
},window);
arr.reduce()、arr.reduceRight()回调函数参数:(prev,cur,index,arr)
1、arr.forEach()
代替普通的for循环
arr.forEach(function(val,index,arr){
console.log(val,index,arr)
});
2、arr.map()
概念:非常有用,做数据交互,映射,正常情况下,需要配合return,返回是一个新的数组,若是没有return,相对于forEach
注意:平时只要用map,一定是要有return,若是没有,就相对于forEach
//例1
let arr = [
{title:'aaaa',read:100,hot:true},
{title:'bbbb',read:100,hot:true},
{title:'cccc',read:100,hot:true},
{title:'dddd',read:100,hot:true}
]
arr.map((item,index,arr)=>{
console.log(item,index);
})
//例2
//重新整理数据结构
let arr = [
{title:'aaaa',read:100,hot:true},
{title:'bbbb',read:100,hot:true},
{title:'cccc',read:100,hot:true},
{title:'dddd',read:100,hot:true}
]
let newArr = arr.map((item,index,arr)=>{
// 下面可以整理返回的数据
let json = {};
json.t = `^_^${item.title}`;
json.r = `数据${item.read}`
json.hot = item.hot == true && '真棒';
return json;
})
console.log(newArr)
3、arr.filter()
过滤,过滤不合格的元素,如果回调函数返回true,则元素留下
let arr = [
{title:'aaaa',read:100,hot:true},
{title:'bbbb',read:100,hot:false},
{title:'cccc',read:100,hot:true},
{title:'dddd',read:100,hot:true}
]
let newArr = arr.filter((item,index,arr)=>{
return item.hot==true;
})
console.log(newArr)
4、arr.some()
类似查找,数组里面某一个元素符合条件,则返回true
let arr = ['apple','banana','orange'];
let b = arr.some((val,index,arr)=>{
return val == 'apple'
})
console.log(b)
//封装一个函数(查找是否存在某一项值)
let arr = ['apple','banana','orange'];
function findInArray(arr,item){
return arr.some((val,index,arr)=>{
return val == item;
})
}
console.log(findInArray(arr,'orange'));
5、arr.every()
数组里面所有的元素都要符合条件,则返回true。
let arr = [1,3,5,7,9];
let b = arr.every((val,index,arr)=>{
return val%2 == 1;
})
console.log(b);
6、arr.reduce()
求数组的和/阶乘
注意:它和arr.reduceRight()的回调函数参数都为(prev,cur,index,arr)
//求数组的和
let arr = [1,2,3,4,5,6,7,8,9,10]
let res = arr.reduce((prev,cur,index,arr)=>{
return prev+cur;
});
console.log(res);
//求阶乘
let arr = [2,3,4]
let res = arr.reduce((prev,cur,index,arr)=>{
return Math.pow(prev,cur);
});
console.log(res);
注意:ES2017新增一个运算符,幂,**
Math.pow(2,3) 和 2**3是相等的
7、arr.reduceRight()
和arr.reduce()相同,求数组的和/阶乘,只不过是从右往左
8、for...of
循环,类似于IOS中的for...in
arr 数组的每一项值
arr.keys() 数组下标
arr.entries() 数组每一项,包括下标和值
let arr = ['apple','banana','tomato'];
// 循环值
for(let val of arr){
console.log(val);
}
//循环index
for(let index of arr.keys()){
console.log(index);
}
// 循环值和index,打印出来的每一项是个数组
for(let item of arr.entries()){
console.log(item);
}
// 循环值和index,打印出来每一项是个单独的值和index
for(let [key,val] of arr.entries()){
console.log(key,val);
}
七、数组新增东西
1、Array.from
作用:把类数组(获取一组元素、arguments...)对象转成数组
<body>
<script>
window.onload = function(){
let aLi = document.querySelectorAll('ul li');
console.log(aLi); //打印出来的NodeList,不能进行数组操作
// 要进行数组操作需要将他转成数组,有三种方式
// 方式1,用...
let new1 = [...aLi];
new1.pop();
console.log(new1);
// 方式2,用Array.from
let new2 = Array.from(aLi); //ES6方法
new2.pop();
console.log(new2);
// 方式3,用[].slice.call(aLi)
let new3 = [].slice.call(aLi); //ES5之前方法
console.log(new3);
}
</script>
<ul>
<li>11</li>
<li>22</li>
<li>33</li>
<li>44</li>
</ul>
</body>
某个观点:具备length这个东西,就靠谱,就能用form
let json = {
0:'apple',
1:'banana',
2:'orange',
length:3
}
let arr = Array.from(json);
//这里能输出arr,但是没有json里面没有length,这里输出[]
console.log(arr);
2、Array.of()
把一组值,转成数组
let arr2 = Array.of('apple1','banana1','orange1');
console.log(arr2); //输出 ["apple1", "banana1", "orange1"]
3、arr.find()
查找,找出第一个符合条件的数组成员,如果没有找到,返回undefined
let arr3 = [23,90,101,80,100];
let res = arr3.find((val,index,arr)=>{
return val>100;
})
console.log(res); // 输出 101
4、arr.findIndex()
查找,找的是位置,没找到返回-1
5、arr.fill()
填充
arr.fill(填充的东西,开始位置,结束位置);
arr.fill(填充的东西) 填充整个数组
let arr4 = new Array(10);
console.log(arr4);
arr4.fill('默认值',0,3);
arr4.fill('默认值2'); //会覆盖之前填充的
其他:
在ES2016里面新增:
arr.indexOf()
arr.includes()
八、对象简洁语法以及对象新增
1、对象简洁语法
把原来的写法简化了
格式:
let json = {
a,
b,
showA(){ //注意:一定不要用箭头函数,因为用了之后,使用的不是对象的变 //量,而是全局的
},
showB(){
}
}
//例1
let x = 10;
let y = 20;
function show({x,y}){
console.log(x,y);
}
show({x,y});
//例2
let name = 'Strive';
let age = 18;
// 以前的写法
let json = {
name:name,
age:age,
showN:function(){
return this.name;
},
showA:function(){
return this.age;
}
}
// 现在的写法
let json2 = {
name,
age,
showA(){
return this.age;
},
showN(){
return this.name
}
}
console.log(json.name,json.age,json.showA(),json.showN()); console.log(json2.name,json2.age,json2.showA(),json2.showN());
注意:里面的函数一定不能用箭头函数!!!
2、对象新增
(1)Object.is()
作用:比较两值相等,(看起来相等的)
比较两值相等方法:==、===、Object.is(a,b)
console.log(NaN == NaN); //false
console.log(Number.isNaN(NaN)); //true
console.log(isNaN(NaN)); //true
let b = Object.is(NaN,NaN);
console.log(b); //true
console.log(+0 == -0); //true
console.log(Object.is(+0,-0)); //false
(2)Object.assign()
作用:1、用来合并/复制对象 2、合并参数
格式:let 新的对象 = Object.assign(目标对象,source1,source2....)
注意:有相同的时候,后面会覆盖前面的
let arr = ['apple','banana','orange'];
let arr2 = Object.assign([],arr);
arr2.push('tomato');
console.log(arr2); //['apple','banana','orange','tomato']
console.log(arr); //['apple','banana','orange']
注意:ES2017引入
Object.keys()
Object.entries()
Object.values()
(3)Object.keys()
(4)Object.values()
(5)Object.entries()
let {keys,values,entries} = Object;
let json = {
a:1,
b:2,
c:3
};
// Object.keys()
for(let key of Object.keys(json)){
console.log(key); //显示为单独的a,b,c
}
// keys()是简写,因为上面用了解构赋值将Object将keys,values和entries对应起来了
for(let key of keys(json)){
console.log(key); //显示为单独的a,b,c
}
for(let val of values(json)){
console.log(val); //显示为单独的1,2,3
}
for(let [key,val] of entries(json)){
console.log(key,val); //显示为a 1 b 2 c 3
}
(6)对象身上用...
注意:在ES2018引入
// 用作剩余和赋值
let {x,y,...z} = {x:1,y:2,a:3,b:4};
console.log(x,y,z); //输出为 1 2 {a: 3, b: 4}
//用作赋值
let json = {a:3,b:4};
let json2 = {...json};
delete json2.b;
console.log(json); //输出为 {a: 3, b: 4}
console.log(json2); //输出为 {a: 3}
九、Promise
1、作用:解决异步回调问题
传统方式,大部分用回调函数,事件:
ajax(url,{ //获取token
ajax(url, () = >{ //获取用户信息
ajax(url,() => {
//获取用户相关新闻
}
}
}//这样操作不简洁,引入promise
2、语法
let promise = new Promise(function(resolve,reject){
//resolve 成功调用
//reject 失败调用
});
promise.then(res=>{
// 这里写成功的
},err=>{
// 这里写失败的
})
//promise例子
let a = 1;
let promise = new Promise(function(resolve,reject){
//resolve 成功调用
//reject 失败调用
if(a==10){
resolve('成功啦,开心');
}else{
reject('失败啦');
}
});
// promise.then(success,fail);
promise.then(res => {
// 这里成功就输出 resolve里面的文字
// 这里失败则输出 Uncaught (in promise) 失败啦
console.log(res);
},err=>{
console.log(err); //这里输出 reject 里面的文字
})
注意:还可以用promise.catch来抓错误
某些人的用法:上面的 res.......逗号err 可以换成 res.......结束之后点catch err
结构:
new Promise().then(res=>{
}).catch(err = >{
})
promise.then(res=>{
console.log(res);
}).catch(err=>{
console.log(err); //这里输出 reject 里面的文字
});
3、Promise.resolve()
作用:将现有的东西,转成一个promise对象,resolve状态,成功状态
eg:
Promise.resolve('aa'); 和下面等价
new Promise(resolve => {
resolve('aa');
}
// Promise.resolve
let p1 = Promise.resolve('aaa');
p1.then(res => {
console.log(res); // 输出 aaa
})
4、Promise.reject()
作用:Promise.reject('aaa'):将现有的东西,转成一个promise对象,reject状态,失败状态
Promise.reject('aa'); 和下面等价
new Promise((resolve,reject) =>{
reject('aa');
})
//Promise.reject
let p2 = Promise.reject('aaaaaaaa');
p2.then(res=>{
console.log(res);
}).catch(err=>{
console.log(err); // 输出 aaaaaaaa
})
5、Promise.all()
Promise.all([p1,p2,p3]) :把promise打包,扔到一个数组里面,打包完还是一个promise对象
注意:必须确保,所有的promise对象,都是resolve状态,都是成功状态
let p1 = Promise.resolve('aaa');
let p2 = Promise.resolve('bbb');
let p3 = Promise.resolve('ccc');
// 注意:必须确保,所有的promise对象,都是resolve状态,都是成功状态
Promise.all([p1,p2,p3]).then(res=>{
console.log(res); // 输出 ["aaa", "bbb", "ccc"]
let [res1,res2,res3] = res;
console.log(res1,res2,res3); //输出 aaa bbb ccc
})
6、Promise.race()
Promise.race([p1,p2,p3]):只要有一个成功,就返回
let p1 = Promise.reject('aaa');
let p2 = Promise.reject('bbb');
let p3 = Promise.resolve('ccc');
Promise.race([p1,p2,p3]).then(res=>{
console.log(res);
}).catch(err=>{
console.log(err); // 输出 aaa
})
7、模拟案例
使用promise模拟用户登录 -> 用户信息
let status = 1;
let userLogin = (resolve,reject)=>{
setTimeout(()=>{
if(status==1){
resolve({data:'登录成功',msg:'xxx',token:'cdvmdie'});
}else{
reject('失败啦');
}
},2000);
};
let getUserInfo = (resolve,reject)=>{
setTimeout(()=>{
if(status==1){
resolve({data:'获取用户成功',msg:'xxx',token:'cdvmdie'});
}else{
reject('失败啦');
}
},1000);
};
new Promise(userLogin).then(res=>{
console.log('用户登录成功');
return new Promise(getUserInfo);
}).then(res=>{
console.log('获取用户信息成功');
console.log(res);
})
十、模块化
在ES6之前,社区制定一套模块规范:
Commonjs 主要服务端 nodeJs require('http')
AMD requireJs,curlJs
CMD seaJs
ES6出来,统一服务端和客户端模块规范:
import {xx} ddd
1、模块化
注意:需要放到服务器环境。
如何去定义模块? export东西
export{
a as aaa;
}
如何使用? <script type="module">import 模块</script>
2、import特点
(a) import 可以是相对路径,也可以是绝对路径
(b) import 模块只会导入一次,无论你引入多少次
(c) import '../modules/1.js'; 如果这么用,相当于引文件,也可以引入网上的文件
(d) 有提升效果,import会自动提升到顶部,首先执行
(e) 导出去模块内容,如果里面有定时器修改,外面也会改动,不像common规范缓存
//方法1
//模块
console.log('模块加载了');
export const a = 12;
export const b = 24;
export const c = 100;
//引入
<script type="module">
import {a,b,c} from '../modules/1.js';
console.log(a,b,c);
</script>
//方法2
//模块
console.log('模块加载了');
const a = 12;
const b = 24;
const c = 100;
export {
a,b,c
}
//引入
<script type="module">
import {a,b,c} from '../modules/1.js';
console.log(a,b,c);
</script>
//提升效果
console.log(a,b); //能够输出
import {a,b} from '../modules/1.js'; //会自动提升到顶部
//导出去模块内容,如果里面有定时器修改,外面也会改动,不像common规范缓存
//模块
let a = 1;
let b = 2;
setTimeout(()=>{
a = 3;
b = 4;
},2000);
export {
a,b
}
//引入
<script type="module">
import {a,b} from '../modules/1.js';
console.log(a,b); //输出 1 2
setTimeout(()=>{
console.log(a,b); //输出 3 4
},3000);
</script>
3、取别名
as (模块和引入都可以取别名)
//1
<script type="module">
import {a as aa,b as bb,c as cc} from '../modules/1.js';
console.log(aa,bb,cc);
</script>
//2
<script type="module">
import * as mode from '../modules/1.js';
console.log(mode.a,mode.b,mode.c);
</script>
4、export和export default
注意**:export 出来的 需要加{} ,export default 出来的东西import时不需要加{}
//例1
//模块
const a = 12;
export default a;
export const cc = 24;
export const dd = 5;
//引入
<script type="module">
import a,{cc,dd} from '../modules/1.js';
console.log(a,cc,dd); //输出 12 24 5
</script>
//例2
//模块
const a = 23;
const b = 5;
const sum = ()=>{
console.log(a+b);
return a+b;
}
const show = ()=>{
console.log('执行了show');
return 1;
}
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
showName(){
return `我的名字是${this.name}`;
}
}
export {
a,b,sum,show
}
export default{
Person
}
//引入
<script type="module">
import mod,{a,b,show,sum} from '../modules/1.js';
let p1 = new mod.Person('张三');
console.log(p1.showName()); //输出 我的名字是张三
show(); // 输出 执行了show
sum(); // 输出 28
console.log(a,b); // 输出 23 5
</script>
5、两个模块之间相互导入
//模块1
import {a,b} from './2.js';
//模块2
export const a = 101;
export const b = 4;
6、动态加载
import 类似于node里面的require ,可以动态引入,默认import 语法不能写到if之类里面,采用的是Promise规范,可以用相对的,绝对的路径
//格式:
import ('./modules/1.js').then(res=>{
console.log(res);
});
优点:1、按需加载
2、可以写在if中
3、路径也可以动态
// 动态加载案例1
function config(sign){
switch(sign){
case 1:
return './modules/1.js';
break;
case 2:
return './modules/2.js';
break;
}
}
import (config(1)).then(res=>{
console.log(res);
});
// 动态加载案例2
// 因为采用的是promise规范,所以也可以使用Promise.all([])动态加载
Promise.all([
import ('./modules/1.js'),
import ('./modules/2.js')
]).then(([mod1,mod2])=>{
console.log(mod1);
console.log(mod2);
})
// 动态加载案例3 es2017加 async await
<script type="module">
async function main(){
// 第一种
const mod1 = await import('./modules/1.js');
const mod2 = await import('./modules/2.js');
console.log(mod1,mod2);
// 第二种
const [m1,m2] = await Promise.all([
import('./modules/1.js'),
import('./modules/2.js')
]);
console.log(m1,m2);
}
main();
</script>
注意:模块化采用的就是严格模式。