6、数组扩展
6.1 扩展运算符(...)
{
// 复制数组
let list1 = [1,2,3];
let list2 = [...list1];
list2.push(4)
console.log(list1);
console.log(list2);
}
{
// 分割数组
let list1 = [1,2,3,'a','b','c'];
let [,,,...list2] = list1; // 通过,进行占位
console.log(list1);
console.log(list2);
}
{
// 展开数组,给方法传参
function func(x,y){
return x+y;
}
let list = [1,2];
console.log(func(...list));
}
6.2 扩展函数
{
// fill 填充数组,常用于初始化
let list1 = [1,2,3,4];
let list2 = [...list1].fill('a'); // 数据全部填充成a
let list3 = [...list1].fill('a',1,3); // 数据从下标1,到下标3之前,填充
console.log(list2);
console.log(list3);
}
{
let personList = [
{id:'1',name:'张三',sex:1},
{id:'2',name:'李四',sex:0},
{id:'3',name:'张三',sex:1},
];
// find 查找,查找数组中第一个满足条件的元素
let person = personList.find(function(item){
return item.name=='张三'
})
// findIndex 查找,查找数组中第一个满足条件的元素的下标
let personIndex = personList.findIndex(function(item){
return item.name=='张三'
})
// some 判断是否存在符合条件的元素
let isFind = personList.some(function(item){
return item.name=='张三';
});
console.log(person);
console.log(isFind);
console.log(personIndex);
}
{
// includes判断数组中是否包涵指定的值,一般对简单数据类型进行判断
let list1 = [1,2,3,4];
console.log(list1.includes(6));
}
{
// flat 展开数组,如果数组中还有数组,可以通过flat张开数组,合并成一层数组
let list1 = [1,2,3,[11,22,33,[111,222,333]]];
let list2 = list1.flat(2); // 参数2是展开的层级,默认是1
console.log(list2)
}
{
// filter 过滤。过滤出数组中所有符合要求的元素
let personList = [
{id:'1',name:'张三',sex:1},
{id:'2',name:'李四',sex:0},
{id:'3',name:'张三',sex:0},
];
let personList2 = personList.filter(function(item){
return item.name == '张三'
})
console.log(personList2);
}
6.2 filter
{
// filter 过滤。过滤出数组中所有符合要求的元素
let personList = [
{id:'1',name:'张三',sex:1},
{id:'2',name:'李四',sex:0},
{id:'3',name:'张三',sex:0},
];
let personList2 = personList.filter(function(item){
return item.name == '张三'
})
console.log(personList2);
}
// filter() 去掉空字符串、undefined、null
let arr = ['','1','2',undefined,'3.jpg',undefined]
let newArr = arr.filter(item => item)
console.log(newArr)
// filter() 数组去重
let arr = [1, 2, 2, 3, 4, 5, 5, 6];
let newArr = arr.filter((x, index,self)=>self.indexOf(x)===index)
console.log(newArr)
// 去重复还是推荐set去重
let arr = [1, 2, 2, 3, 4, 5, 5, 6];
let newArr =Array.from(new Set(arr))
console.log(newArr)
6.3 map
map是返回一个新的被改变过后的数组。需要return.
{
// map 常用于数据的映射
let personList = [
{id:'1',name:'张三',sex:1},
{id:'2',name:'李四',sex:0},
{id:'3',name:'张三',sex:1},
];
let newPersonList1 = personList.map(function(item){
return {
id:item.id,
name:item.name,
sex:item.sex ? '男' : '女'
}
})
// 如果只想改变数组中的特定属性
let newPersonList2 = personList.map(function(item){
let obj={};
Object.assign(obj,item);
obj.sex = item.sex ? '男' : '女';
return obj;
})
console.log(personList)
console.log(newPersonList1)
console.log(newPersonList2)
}
6.4 reduce
{
/**
* reduce 是对数组中的每个元素进行回调,升序执行后,将回调的值进行汇总
*/
let str = 'abcdasegsa';
let result = str.split('').reduce(function(acc,cur){
// acc 是一个初始化的值,cur是循环中的元素
acc[cur] ? acc[cur]++ : acc[cur]=1;
return acc;
},{});
console.log(result);
}
7、箭头函数
{
const func1 = (x)=>{
console.log('箭头函数');
}
func1('1');
const func2 = x => x*2;
console.log(func2(1))
}
特点:使用简洁。不绑定this。
{
let person = {
name:'张三',
age:18,
showName1:function(){
setTimeout(function(){
// 这里的this是window
console.log(this.name,this);
},1000);
},
showName2:function(){
setTimeout(()=>{
// 这里的this是person
console.log(this.name,this);
},1000);
}
}
person.showName1();
person.showName2();
}
8、ES6中的类
8.1 声明
本质上ES5和ES6中类的使用是一样的。ES6中的class可以理解为构造函数的语法糖
{
// ES5中声明类的常用方式
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function(){
console.log(`你好,我是${this.name}`)
}
let p1 = new Person('张三',18);
p1.sayHello();
console.log(p1);
}
{
// ES6中声明类 本质上整个Person就是构造函数
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
sayHello(){
console.log(`你好,我是${this.name}`)
}
}
let p1 = new Person('张三',18);
p1.sayHello();
console.log(p1)
}
8.2 继承
{
// ES5中声明类的常用方式
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function(){
console.log(`你好,我是${this.name}`)
}
let p1 = new Person('张三',18);
p1.sayHello();
console.log(p1);
}
{
// ES6中声明类 本质上整个Person就是构造函数
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
sayHello(){
console.log(`你好,我是${this.name}`)
}
}
let p1 = new Person('张三',18);
p1.sayHello();
console.log(p1)
}
{
// es5继承
function Person(name){
this.name = name;
}
Person.prototype.sayHello = function(){
console.log("person",this.name)
}
function Man(name,age){
this.age = age;
Person.call(this,name);
}
Man.prototype = new Person();
Man.prototype.showAge = function(){
console.log("man",this.age,this.name)
}
var man = new Man("张三",17);
man.showAge();
console.log(man);
}
{
// ES6中的实现
class Person{
constructor(name){
this.name = name;
}
sayHello(){
console.log("person",this.name)
}
}
class Man extends Person{
constructor(name,age){
// 必须调用super 才能使用this
super(name);
this.name = name;
this.age =age
}
showAge(){
console.log("man",this.age,this.name)
}
}
var man = new Man("张三",17);
man.showAge();
console.log(man);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Js Class extends</title>
<style>
* {
margin-top: 20px;
}
h5 {
color: red;
}
span {
color: blue;
}
</style>
</head>
<body>
<h5>Js 类继承 extends</h5>
<div>继承类声明 使用关键字 extends</div>
<div>如果子类中存在构造函数 constructor(),则需要在使用“this”之前调用 super() 代替父类构造函数</div>
<div>
<span>js 输出: </span>
<span id="idconsole"></span>
<!-- 显示时间 -->
<div></div>
</div>
</body>
<script>
// 父类
class Animal {
constructor(name) {
this.name = name;// 类属性声明不须要var声明 , var parrent = '';是声明普通变量
}
// 成员方法
speak() {
console.log(this.name + ' makes a noise.'); //仿问类属性要使用 this.
}
}
// 子类 继承自 Animal
class Dog extends Animal {
master = ''; // Dog 比父类Animal 多了新属性master
constructor(name, master) {
super(name); // 调用 super() 代替父类构造函数,初始化与父类共同的属性name
this.master = master; // 初始化子类新属性master
}
// 重载父类成员方法 speak
speak() {
let logstr = this.name + ' is a Dog, ' + 'has master from ' + this.master + ' .';
let logelement = document.getElementById('idconsole');
logelement.innerHTML = logstr;
logelement.nextElementSibling.innerHTML = 'time: ' + new Date().toLocaleString();
}
}
var d = new Dog('Wangwang', 'People'); // 构造新实例 Dog
d.speak(); // 调用Dog成员方法
</script>
</html>
9、export和import
module1.js
// export 分别导出 变量、方法和类。
// 声明和导出在一起
export let a = 18;
export function func(){
console.log('hello')
}
export class Person{
sayHello(){
console.log('person');
}
}
module2.js
// 先声明
let a = 12;
function func(){
console.log('hello')
}
class Person{
sayHello(){
console.log('person');
}
}
// 后导出(推荐)
export default{
a,
func,
Person
}
导入
<script type="module">
// 第一种导入 按需导入的名称要和exprot 中对应
import {a,func, Person} from './js/module1.js';
console.log(a);
console.log(func);
console.log(Person);
// 第二种导入 一次性导入所有的export。
import * as module1 from './js/module1.js';
console.log(module1.a);
console.log(module1.func);
console.log(module1.Person);
//第三中导入 (推荐)配合export default
import module2 from './js/module2.js';
console.log(module2.a);
console.log(module2.func);
console.log(module2.Person);
</script>
10、异步编程
1. 什么是同步
当⼀一个"调用"发出时,在没有得到结果之前,这个"调用"就会阻塞后面代码的执行, 得到结果的时候才会返回。换句话说,"调⽤者"要主动等待代码的执行结果,得到返回结果 后,程序才会继续运行
2.什么是异步
"调用"发出的时候,就直接返回了,对应的结果会通过状态、通知来告诉"调用者"或通 过回调函数处理这个调用。异步调用发出后,不会阻塞后面的代码。
3.JavaScript中为什么要引入异步这个概念
JavaScript是单线程的
同步代码会阻塞后面的代码
异步不会阻塞程序的运⾏
4.JavaScript中异步的实现
回调函数
// ⼀层的回调函数
$.get('http://api.xxx.com/xxx', callback)
/**
* 请求后台类型列列表,根据类型名称获取要请求的列列表id,再根据id获取列表详细内容
* 难以维护,这就是回调地狱了
**/
$.ajax({
url: "type",
data:1,
success: function (a) {
$.ajax({
url: "list",
data:a,
success: function (b) {
$.ajax({
url: "content",
data:b,
success: function (c) {
console.log(c)
}
})
}
})
}
})
setInterval和setTimeout
Promise
Generator
async
10.1 promise
{
function func1(resolve,reject){
var timeOut = Math.random() * 2;
setTimeout(()=>{
console.log('任务1',timeOut);
if(timeOut<1){
resolve("执行结果"); // 调用promise的then中的方法
}else{
reject("执行报错"); // // 调用promise的catch中的方法
}
},1000);
}
let p1 = new Promise(func1);
let p2 = p1.then(function(response){
console.log("执行完了"+response)
});
let p3 = p2.catch(function(error){
console.log("执行出错了"+error);
})
}
{
// ajax1 ajax2 ajax3 都是Promise对象
function ajax1(num){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log("任务1",num+1);
resolve(num+1);
},1000)
});
}
function ajax2(num){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log("任务2",num+2);
resolve(num+2);
},1000)
});
}
function ajax3(num){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log("任务3",num+3);
resolve(num+3);
},1000)
});
}
ajax1(1).then(ajax2).then(ajax3);
}
Promise.all()方法
{
// 定义Promise方法,传入要相加的数字
function getNum(num){
return new Promise((resolve,reject)=>{
resolve(num);
});
}
function sum(nums){
let result = 0;
nums.forEach(num=>{
result = result + num;
});
console.log(result);
}
// 使用Promise.all 方法,此方法传入多个Promise方法,保证这些方法都全部完成,才执行then
// Promise.all()返回的也是一个Promise实例。then方法传入的参数是前面多个方法中resolve的参数数组
Promise.all([getNum(1),getNum(2),getNum(9)]).then(sum);
}
Promise.race() 方法
{
// 定义Promise方法,传入要相加的数字
function getNum(num){
return new Promise((resolve,reject)=>{
resolve(num);
});
}
function showNum(num){
console.log(num);
}
// Promise.race方法 用于希望多个方法,率先返回的结果就是整个Promise的结果
Promise.race([getNum(11),getNum(2),getNum(9)]).then(showNum);
}