You辉编程_JavaScript高级程序

ES6
初始ES5
1. ES6简介
1.1 ES6是什么
基本数据类型:数字、字符串、布尔值、undefined、null
引用数据类型:对象、函数
ES6=ECMAScript这们语言的第6代标准,ECMA是标准。
1.2 ECMAScript是什么
它规定标准具体是语法和API
语法:var name = 'Alex';
function add(x,y){
    retrue x + y;
}
API:就是方法和函数。
ECMAScript==语法+API(规定了语法格式和函数方法)
1.3 ECMAScript的命名方式
1.4 ECMAScript与JavaScript的关系
JavaScript = ECMAScript(语法+API)+DOM+BOM
1.5 ES6的兼容性
主流浏览器的最新版本几乎全部支持ES6。
IE老版本可以用Babel转码。
2. let和const
2.1 let和const是什么
let代替var声明变量,const声明常量。
变量:可以重新赋值。
常量:不可以重新赋值。
eg:const sex = 'male';
sex = 'female';//此时会报错。
2.2 const
-cosnt的注意事项
声明和初始化一气呵成。
允许在在不重新赋值(即以:常量名 = 改变的值 的方式)的情况下修改它的值。比如应用类型就可以。
eg:const person = {username:Alex};
person.username = 'ZhanSan';
-什么时候用const,什么时候用let
当初始化后不想被改变的值用const,
2.3 let、const与var的区别
-重复声明:已经存在的变量或常量(包括函数中的参数),又声明了一遍
var 允许重复声明,let,const不允许。
eg:var a = 1;
var a = 2;
cosole.log(a);//后会覆盖前的
funciton fun(a){
    let a = 1;
}
console.log(a);//重复报错。
-变量提升
var会提升变量的声明但不包括变量值的提升:
eg:console.log(a);//undefined
var a = 1;
let,const不存在变量提升
console.log(a);//直接报错
let a = 1;
所以要先声明后使用。
-暂时性死区:只要在函数内部用let,const声明与全局作用域声明相同的变量名,就不会往外找,直接报错。
let a = 2;//全局作用域 
function fun(){
    console.log(a);//直接报错,如果是var当函数内部没有找到变量的值会往外找但是函数内部有let,const就不会这就是暂时性死区。
    let a = 1;
}
fun();
-window对象的属性和方法(全局作用域中)
全局作用域中,var声明的变量,通过function声明的函数,会自动变成window对象的属性和方法。let和const不会。
var age = 18;
function add(){

}
console.log(window.age);//18
console.log(window === add);//true
-块级作用域:函数{}内部区域
什么是块级作用域:
var 没有块级作用域
for(var i = 0;i < 3;i++){
    console.log(i);//0,1,2
}
console.log(i);
let,const有块级作用域
var 没有块级作用域
for(let i = 0;i < 3;i++){
    console.log(i);//0,1,2
}
console.log(i);//直接报错,因为let有块级作用域,超出函数{}就不起作用了。
作用域链:常量查找形成作用域链:块级作用域-->函数作用域-->全局作用域。 
有哪些块级作用域:
{}
for(){}
while(){}
do{}while(){}
if(){}
switch(){}
注:function(){}是函数作用域,Object()不是跨级作用域。
2.4 let和const的应用
示例代码:
<style>
        body{
            padding:50px 0 0 150px;
        }
        .btn{
            width: 100px;
            height: 100px;
            margin-right:20px;
            font-size:80px;
            cursor:oninter;
        }
    </style>
</head>
<body>
    <button class="btn">0</button>
    <button class="btn">1</button>
    <button class="btn">2</button>

    <script>
        /*实现点击哪个按钮,就输出哪个按钮的值*/
        // var btns = document.querySelectorAll('.btn');
        // for(var i = 1;i < btns.length;i ++){
        //     btns[i].addEventListener('click',function(){
        //         console.log(i);//3,不能实现
        //     },false);
        // }

        //2.闭包:能实现
        // var btns = document.querySelectorAll('.btn');
        // for(var i = 1;i < btns.length;i ++){
        //     (function(index){
        //     btns[i].addEventListener('click',function(){
        //         console.log(i);
        //     },false);
        //     })(i);
        //   }
          //3.现在不用使用闭包了:let,const利用它有块级作用域的特点
         let btns = document.querySelectorAll('.btn');
         for(let i = 1;i < btns.length;i ++){
            btns[i].addEventListener('click',function(){
                console.log(i);
            },false);
        }
    </script>
--------------------------------------------------------------------------------------------
模板字符串与箭头函数
1. 模板字符串是什么
-模板字符串与一般字符串的区别(主要体现在输出)
const person = {
    username:'xiaoming',
    age:18,
    sex:'male'
}
const info = '名字'+person.username+'性别'+person.sex;
console.log(info);
//模板字符输出
const info = `姓名:${person.username},性别:${person.sex}`;
console.log(info);
2. 模板字符串的注意事项
-输出多行字符串
模板字符串可以换行,怎么写就怎么输出。
-输出`和\等特殊字符
const info = `\``;
console.log(info);//`
const info = `\\`;
console.log(info);// \
const info = `""`;
console.log(info);// ""
-模板字符串的注入
const username = 'alex';
const person{age:18,sex:'male'};
const getSex = function(sex){
    retrue sex === 'male'?'男':'女';
};
const info = `${username},${person.age+2},${getSex(person.sex}`;
console.log(info);
补充:只要最终可以得出一个值的就可以通过${}注入到模板字符串中。
3. 模板字符串的应用
动态把数据添加到li中,示例代码:
<p>学生列表</p>
    <ul id="list">
        <li style="list-style:none;">信息加载中……</li>
    </ul>
    <script>
        //数据
        const students = [
            {
                username:'xiaoming',
                age:18,
                sex:'male'
            },
            {
                username:'zhansan',
                age:19,
                sex:'male'
            },
            {
                username:'Lisi',
                age:17,
                sex:'female'
            }
        ];
        const list = document.getElementById('list');
        let html = '';
        for(let i = 0;i < students.length; i++){
            html  += `<li>我的名字是:${students[i].username},
                ,${students[i].sex},${students[i].age}</li>`
        }
        list.innerHTML = html;
    </script>
4. 箭头函数是什么
-认识箭头函数
格式:() => {}
const add = (x,y) => {
    retrue x + y;
};
console.log(add(1,2));
-箭头函数的结构
参数 => 函数体:是一个匿名函数,是不能起名字的,需要赋值给一个变量或产量,才能被调用。
eg:const/let 函数名 = 参数 => 函数体 
-如何将一般函数改写成箭头函数
一般函数:
function add(){};
const add = function(){};
转变后
const add = () => {};
5. 箭头函数的注意事项
-单个参数:可以省略圆括号
无参数或多个参数不能省略圆括号。
const add = (x) => {
    retrue x + 1;
}
可以简写为:const add = x => {
    retrue x + 1;
}
-单行函数:可以省略{}和return
const add = (x,y) => {
    retrue x + y;
};
可以简写为:const add = (x,y) => x + y;
-单行对象
const add = (x,y) => {
    retrue{
        value:x+y
    };
}
可以简写为:
const add = (x,y) => ({
    value:x+y;
})
6. this指向
-全局作用域中的this指向
console.log(this);//指向window全局对象
-一般函数(非箭头函数)中的this指向
一般函数,只有被调用的时候this指向才确定,不调用的时候,不知道指向谁。
this指向和和函数在哪儿调用没关系,只和谁在调用有关系。
function add(){
    console.log(this)
}
const calc = {
    add:add
}
calc.add();//calc调用,this就指向calc(出构造函数外,有构造函数指向构造函数)
-箭头函数没有自己的this指向
const calc = {
    add:() => {
        console.log(this);
    }
};
calc.add();//window
7.不适用箭头函数的场景
-作为构造函数的时候
-需要this指向调用对象的时候(事件绑定的时候)
document.onclick = function(){};
document.addEventListener('click',funciton(),false);
-需要使用arguments(不确定参数计算)的时候
function add(){
    console.log(arguments);
}
add(1,2,3,4,5);
8.箭头函数的应用:this会逐一往上一层找直到找到。
示例代码:
<button id="btn">开始</button>
    <span id="result">0</span>
    <script>
        const btn = document.getElementById('btn');
        const result = document.getElementById('result');
        
        const timer = {
            time:0,

            start:function(){

                btn.addEventListener('click',() => {
                    setInterval(() => {
                        console.log(this);
                        this.time ++;
                        result.innerHTML = this.time;
                    },1000);

                },false);

            }
        }
        timer.start();
----------------------------------------------------------------
解构赋值
1. 数组的解构赋值
-认识解构赋值
const arr = [1,2,3];
const a = arr[0];
const b = arr[1];
const c = arr[2];
console.log(a,b,c);//这样获取数组非常麻烦,解构赋值就是用来解决这个问题的。

const[a,b,c] = [1,2,3];
console.log(a,b,c);
-解构赋值:解析某一数据的解构,将我们想要的东西提取出来,赋值给变量或常量。
-解构赋值的原理:
.模式(结构)匹配:[] = []
.索引值相同的完成赋值:[a,b,c] = [1,2,3]
-数组解构赋值的默认值
.默认值的基本用法
const[a=1,b=2]=[];
console.log(a,b);//1,2
.默认值的生效条件:只有当一个数组成员严格等于(===)undefined时,对应的默认值才会生效
.默认值表达:如果默认值是表达式,默认值表达式时惰性求值
const fun = ()=>{
    console.log('我被执行');
    return 2;
};
const[x=fun()] = [1];
console.log(x);//1
只有被用到时才会被执行:
const[x=fun()] = [];
console.log(x);//我被执行
-数组解构赋值的应用
.常见的类数组的解构赋值
//arguments
function fun(){
    const[a,b]=arguments;
    cosnole.log(a,b);
}
fun(a,b);
//NodeList:节点列表
<p>123</p>
<p>456</p>
<p>789</p>
const [p1,p2,p3]=doucment.querySelectorAll('p');
console.log(p1,p2,p3);
-函数解构性赋值
const array = [1,1];
const add = ([x,y]) => x+y;
consolt.log(add(array));
-交换变量的值
let x = 1;
let y = 2;
[x,y]=[y,x]
console.logS(x,y);
2. 对象的解构赋值
-对象解构赋值的原理
.模式(结构)匹配:{}={}
.属性名相同的完成赋值
const {username:username,age:age}={username:'xiaoming',age:10};
console.log(age,uarname);
-对象解构赋值的注意事项
.对象解构赋值的默认值
.将一个已经声明的变量用于解构赋值
let x = 2;
({x}={x:1})
.可以取到继承的属性
const {toString} = {};
console.log(toString);
-对象解构赋值的应用
.函数参数的解构赋值
cosnt logPersonInfo = ({username,age}) => console.log(uasername,age);
logPersonInfo({username:'xiaoming',age:18});
.复杂的嵌套
const obj = {
    x:1,
    y:[1,2,3],
    z:{
        a:5,
        b:6
    }
};
const{x,y,z}=obj;
console.log(x,y,z);
//取y的2
const{
    y:[,y1],
}=obj;
console.log(y1);
3. 其他类型的解构赋值
-字符串的结构赋值
.字符串按照数组的解构赋值
const [a,b,,,c]='hello';
console.log(a,b,c);//heo 
.按对象形式解构赋值
const{0:a,1:b}='hello';
console.log(a,b);//he 
-数值和布尔值的解构赋值
//先将等号右边的值转为对象
const {a = 1,toString} = 123;
console.log(a,toString);
//布尔值
const{b = 2,toString}=true;
console.log(b,toString);
-undefined和null的解构赋值
-------------------------------------------------------------
对象字面量的增强与函数参数的默认值
1.对象字面量的增强 
-属性和方法的简洁表示法
.对象字面量是什么:是对象的一种写法(两种)
实例化构造函数生成对象:
const person = new Object();
person.age = 18;
person.speak = funciton(){};
//对象字面量 
const person = {
    age:18;
    apeak:funciton(){}
};
.属性的简洁表示法:键名和变量(或常量)名一样的时候,可以只写一个 
const age = 18;
cosnt person = {
    //age:age;//可以简写为age
    age
};
console.log(person);//{age:18}
.方法的简洁表示法:可以省略冒号和function关键字
const person = {
    //speak:funciton(){};//可以简写为 
    speak(){}
}
console.log(person);
2.方括号语法的增强
-方括号语法的用法:方括号语法可以写写在对象字面量中
const prop = 'age';
//cosnt person = {};
//person[prop] = 18;
const person = {
    [prop]:18
};
console.log(person);
-方括号中可以放什么:[值或通过计算可以得到值的(表达式)]
const prop = 'age';
const fun = () => 'age';
const person = {
    //[prop]:18
    [fun()]:18
}
console.log(person);//{age:18}
-方括号语法和点语法的区别
点语法是方括号语法的特殊形式
const person = {};
person.age 等价于 person['age'];
3.函数参数的默认值
-函数参数的默认值是什么
调用函数的时候传参了,就用传递的参数;如果没传参,就用默认值
-函数参数默认值的基本用法
const multiply = (x,y)=>{
    if(typeof y === 'undefined'){
        y = 1;
    }
    return x * y;
};
console.log(3,3);
//可以简写为 
consot multiply = (x,y=1)=>x*y;
console.log(3);
-函数参数默认值的注意事项
不传参数,或者明确的传递undefined作为参数,只有这两种情况下,默认值才会生效。
const multiply = (x,y=1)=>x*y;
console.log(multiply(2));//2
console.log(multiply(2,undefined));
-默认值表达式 
如果默认值是表达式,默认值表达式时惰性求值的
-设置默认值的小技巧
函数参数的默认值,最好从参数列表右边开始设置
const multiply = (x,y=3)=>x*y;
-函数参数默认值的应用
//1.函数接受多个参数的时候
        // const logUser=(username='zhansen',age=0,sex='male')=>{
        //     console.log(username,age,sex);
        // }
        // logUser('Lili',16,'女');
        //logUser();//显示默认值,不会报错

        //2.接受一个对象作为参数
        const logUser = ({username='zhansna',age=0,sex='male'}) => 
        console.log(username,age,sex);
        logUser({username:'Lili'});
------------------------------------------------------------------
剩余参数与展开运算符
1.剩余参数 
-剩余参数是什么
.认识剩余参数
const add = (x,y,z,...args) => {};
.剩余参数的本质
const add = (x,y,...args)=>{
    console.log(x,y,args);//剩余参数在使用时不用加...
}
add(1,2,3,4,5);
剩余参数永远是个数组,即使没有值,也是空数组。
-剩余参数的注意事项
.箭头函数的剩余参数
箭头函数的参数部分即使只有一个剩余参数,也不能省略圆括号
const add = (...args) => {};
.使用剩余参数替代arguments获取实际参数
之前用arguments获取参数,是不能使用箭头函数的
const add = function(){
    console.log(arguments);
};
add(1,2,3);
现在用剩余参数替代,并且可以使用箭头函数
const add = (...args) => {
    console.log(args);
}
add(1,2,3);
.剩余参数的位置
剩余参数只能是最后一个参数,之后不能再有其他参数,否则会报错
-剩余参数的应用
示例代码:
// const add = (...args) => {
        //     let sum = 0;

        //     for(let i = 0;i <args.length; i++){
        //         sum += args[i];
        //     }

        //     return sum;
        // }
        // console.log(add(1,2,4));//7

        //1.剩余参数与解构赋值结合使用
        //剩余参数不一定非要作为函数参数的使用
        // const [num,...args] = [1,2,3,4];
        // console.log(num,args);

        //2.与对象结合
        const {x,y,...z}={a:1,x:2,y:3,z:4};
        console.log(x,y,z);
2.数组的展开运算符(...)
-数组展开运算符的基本用法
.认识展开运算符
把数组转换成数列:[1,2,3]->1,2,3
.数组展开运算符的基本用法
console.log(Math.min(...[1,2,3]));
-区分剩余参数和展开运算符
.根本区别
剩余参数:1,2,3->[1,2,3]
展开运算符:[1,2,3]->1,2,3
-数组展开运算符的应用
//复制数组
const a = [1,2];
const c = [...a];
//合并数组
const a = [1,2];
const b = [3];
const c = [4,5];
console.log([...a,...b,...c]);
//字符串转为数组
//字符串可以按照数组的形式展开
console.log(...'hello');//h e l l o
console.log([...'hello'])//转为数组
3.对象的展开运算符号
-基本用法
.展开对象
const apple = {
    color:'红色',
    shape:'球形',
    taste:'甜'
};
console.log({...apple});
//对象的展开:把属性罗列出来,用逗号分隔,放到一个{}中,构成一个新的对象

//合并对象
const apple = {
    color:'红色',
    shape:'球形',
    taste:'甜'
};
const pen = {
    color:'黑色',
    shape:'柱形',
    use:'写字'
};
console.log({...apple,...pen});
-注意事项
.空对象的展开
空对象展开后没有任效果
console.log({...{}});
.非对象的展开
如果展开的不是对象,则会自动将其转化为对象,再将其属性罗列出来
console.log({...1});//{}
console.log({...undefined});//{}
.对象中对象属性的展开:不会展开对象中的对象属性
const apple = {
    feature:{
        taste:'甜'
    }
};
const pen = {
    feature:{
        color:'黑色',
        shape:'圆柱形'
    },
    use:'写字'
};
console.log({...apple});
-应用
//复制对象
const a = {x:1,y:2};
const c = {...a};
console.log(c);
console.log(c === a);//false,实现了深克隆

//用户参数和默认参数
const logUser = userParam => {//用户参数
    const morenParam = {//默认参数
        username:'Lisi',
        age:0,
        sex:'male'
    };
const {username,age,age} = {...morenParam,...userParam};
console.log(username,age,sex);
};
logUser();

-------------------------------------------------------------------
Set和Map
1. Set (集合)
-Set是什么
数组是一系列有序(指的是下标)的数据集合
Set是一系列无序、没有重复值的数据集合
Set的创建
const s = new Set();//通过它的add()属性添加元素
s.add(1);
s.add(2);
console.log(s);//{1,2}

注:Set没有下标取标示每一个值,所以Set是无序的,也不能像数组那样通过下标去访问Set成员
-Set实例的方法和属性
.add()方法 
const s = new Set();
s.add(1).add(2);
console.log(s);
.has()方法:用来检测集合里有没有某个属性
console.log(s.has(1));//true

.delete()方法:用来删除指定元素
s.delete(1);
.clear()方法:清除全部元素

.forEach()方法:一个一个遍历,不能提取某一个
s.forEach(function(value,key,set){
    //value=key
    console.log(value,key,set===s);//1,2,true
},documnet);

.属性 
.size()用来获取Set集合的长度。
console.log(s.size);
-Set构造函数的参数
.数组 
const s = new Set([1,2,3]);
console.log(s);
.字符串、arguments、NodeList、Set等。
console.log(new Set('hi'));
//arguments只有在一般函数中才能获取到
funciton fun(){
    console.log(new Set(arguments));
}
fun(1,2,3);
//NodeList:
<p>1</p>
<p>2</p>
<p>3</p>
console.log(new Set(document.querySelectorAll('p')));


const s = new Set([1,2,3]);
console.log(new Set(s));
conosle.log(s);
-Set的注意事项
.判断重复的方式
Set对重复值的判断基本遵循严格相等(===),但对NaN除外,Set中的NaN等于NaN
.什么时候使用Set
对数组或字符串去重的时候;
不需要通过下标访问,只需遍历的时候;
为了使用Set提供的方法和属性是(add,delete,clear,has,forEach,size等)。
-Set的应用
示例代码:
<p>0</p>
    <p>1</p>
    <p>2</p>
    <script>
        //1.数组的去重:直接将数组放到Set中;
        //[1,2,4,2,4,2]
        const s = new Set([1,2,4,2,4,2]);
        console.log(s);

        //2.字符串去重
        //'aavbbbcc'
        const s1 = new Set('aavbbbcc');
        console.log(s);
        console.log([...s].join(''));
        conosle.log(s);

        //3.存放DOM元素
        //console.log(document.querySelectorAll('p'))
        const s2 = new Set(document.querySelectorAll('p'));
        console.log(s);
        s.forEach(function(elem){
            //console.log(elem);
            elem.style.color = 'red';
            elem.style.background = 'yellow';
        });
    </script>
2. Map
-Map是什么
.认识Map(映射)
Map和对象都是键值对的集合
补充:
const person={
    'name':'Lisi';//对象中的键键名其实是字符串,只是平时省略了单引号。
}
const m = new Map();
m.set('name','Lisi');
m.set('age',18);
cosole.log(m);
.Map和对象的区别
对象一般用字符串当作键
const obj = {
    name:'Lisi',
    true:'true'
}

基本数据类型:数字,字符串,布尔值,undefined,null;
引用数据类型:对象,([],{},函数,Set,Map等)
以上都可以作为Map的键
const m = new Map();
m.set('name','Lisi');
m.set(true,'true');
m.set({},'object');
m.set(new Set(1,2),'set');
m.set(undefined,'undefined');
console.log(m);

-Map的实例和方法
.方法 
set():使用set添加的新成员,键如果已经存在,后添加的键值对覆盖以有的
const m = new Map();
m.set('age',18).set(true,'true').set('age',20);

.get():获取指定成员,通过键名获取
console.log(m.get('age'));
cosnole.log(m.get('true));

.has():用来检验Map集合里是否存在某个键
console.log(m.has('age'));//true 

.delete():通过键名删除键值对
console.log(m.delete('age'));

.clear():清除所有的键值对

.forEach():遍历
m.forEach(function(value,key,map){
    conosle.log(value,key,map);
},document);//参数document改变this指向
m.clear();
.属性 
size():用来查看Map里有几个成员
console.log(m.size);
-Map构造函数的参数
.数组 
只能传二维数组,而且必须体现出键和值
console.log(new Map([
    ['name','Lisi'],
    ['age',18]
]));
.Set和Map 
Set中也要体现出键和值
const s = new Set([
    ['name','Lisi'],
    ['age',18]
])
console.log(new Map(s));
console.log(s);

//Map 
const m1 = new Map([
    ['name','Lisi'],
    ['age',18]
])
const m2 = new Map(m1);
console.log(m2)
console.log(m2 == m1);//false
-Map的注意事项
.判断键名是否相同的方式
基本遵循严格相等(===),但Map中的NaN等于NaN
.什么时候使用Map
如果只是需要key->value的结构,或者需要字符串以外的值做键,使用Map更合适;
只有模拟现实世界的实体时,才使用对象;
-Map的应用
示例代码:
<p>1</p>
    <p>2</p>
    <p>2</p>
    <script>
        const [p1,p2,p3] = document.querySelectorAll('p');
        //const m = new Map();
        // m.set(p1,'red');
        // m.set(p2,'green');
        // m.set(p3,'blue');
        //也可以
        const m = new Map([
            [p1,{
                color:'red',
                backgroundColor:'yellow',
                fontSize:'40px'
            }],
            [p2,{
                color:'green',
                backgroundColor:'pink',
                fontSize:'40px'
            }],
            [p3,{
                color:'blue',
                backgroundColor:'pink',
                fontSize:'40px'
            }]
        ]);

        m.forEach((propObj,elem)=>{
            for(const p in propObj){
                elem.style[p]=propObj[p];
            }
        });
    </script>

-----------------------------------------------------------------------------
Iterator遍历器与for...of循环
1. Iterator (遍历器)一个一个遍历
-lterator的作用
-寻找Iterrator
console.log([1,2][Symbol.iterator]());//是一个对象
const it = [1,2][Symbol.iterator]();
-使用Iterator
 const it = [1,2][Symbol.iterator]();
 console.log(it.next());//{value:1,done:false}
 conosle.log(it.next());//{value:1,done:false}
 cosnole.log(it.next());//{value:1,done:true}
-什么是Iterator:是一个这样的过程
Symbol.iterator(可遍历对象的生成方法)->it(可遍历对象)->it.next->...(直到done为true)

2. Iterator解惑
-为什么需要Iterator遍历器
//遍历数组:for循环,forEach方法
//遍历对象:for in 循环
//Iterrator遍历器是一种的统一的遍历方式
-如何更方便的使用Iterator
//我们一般不会直接使用Iterator去遍历,因为已经封装成for...of了
3. for...of的用法
-认识for...of 
const arr = [1,2,3];
const it = arr[Symbol.iterator]();//获取iterator
let next = it.next();
console.log(next);
while(!next.done){
    console.log(next.value);
    next = it.next();
    console.log(next);
}
以上过程可以用for...of来完成(都封装在了for of里了)
for(const item of arr){
    console.log(itme)
}
补充:for...of只会遍历出那些done是false时,对应的value值
-与break,continue一起使用
const arr = [1,2,3];
for(const item of arr){
    //当遍历到2时跳出循环
    if(item === 2){
        //break;
        continue;
    }
    console.log(item);
}
-在for...of中取得数组的索引 keys()方法
const arr = [1,2,3];
console.log(arr.keys());
for(const key of arr.keys()){
    console.log(key);
}

//values()方法得到的是值得可遍历对象,可以遍历出值
for(const value of arr){
    console.log(vlaue);
}

//entries()得到的是索引+值组成的数组的可遍历对象
for(const entries of arr.entries()){
    console.log(entries);
}
结合结构赋值
for(cosnt[index,value] of arr.entries()){
    console.log(index,value);
}
4. 原生可遍历与非原生可遍历
-什么是可遍历
//只要有Symbol.iterator方法,并且这个方法可以生成可遍历对象,就是可遍历的
//只要是可遍历的,就可以使用for...of循环来统一遍历
-原生可遍历的有哪些
数组、字符串、Set、Map、arguments、NodeList
for(const item of [1,2,4]){
    console.log
}
for(const item of 'hi'){
    console.log(item);
}
for(const item of new Set([1,2])){
    console.log(item);
}
 
-非原生可遍历有哪些
//一般对象
//for in 
person[Symbol.iterator] = () => {
    let index = 0;
    return{
        next(){
            next ++;
            if(index == 1){
                retrue{
                value:person.age,
                done:false
            };
            }else if(index === 2){
                return{
                    value:person.sex,
                    done:false
                };
            }else{
                return {
                    done:ture
                };
            }
            
        }
    }
}
8. 使用了Iterator的场合
-数组的展开运算符
console.log(...[1,2,3]);
console.log(...'str');
console.log(...new Set([1,2,4]));
-数组的解构赋值
const [a,b] = [2,3]; 
const[a,b]=[...new Set(3,5)];
-Set和Map的构造函数
new Set(iteretor);
new Map(iterator);

--------------------------------------------------------------
ES6新增方法
1. 字符串的新增方法
-includes():判断字符中是否包含某些字符
//基本用法 
console.log('abc'.includes('a'));//true
//第二个参数:表示搜索位置,默认是0
console.log('abc'.includes('a',1));//false
//应用
示例代码:
<script>
        let url = 'https://www.imooc.com/course/list';
        const addURLParam = (url,name,value) => {
            url+=url.includes('?')?'&':'?';
            return;
            url+=`${name}=${value}`;
        };
        url = addURLParam(url,'c','fe');
        conosle.log(url);
        url=addURLParam(url,'sort','pop');
        conosle.log(url);
    </script>
-padStart()和padEnd()
padStart()从头部开始填充;padEnd()从尾部开始填充
//补全字符串的长度
//1.基本用法 
console.log('x'.padStart(5,'ab'));//从头部开始补,长度为5:ababx
console.log('x'.padEnd(5,'ab'));// xabab

//2.注意事项 
原字符串的长度,等于或大于最大长度,不会消减原字符串,字符串补全不生效,返回原来字符串
console.log('xxx'.padStart(2,'ab'));//xxx

//3.应用:现实日期
//2022-10-10
console.log('10'.padStart(2,0));//10
-trimStart()和trimEnd()
trimStart()去除头部的空格,trimEnd()去除尾部的空格(字符串),中间的空格不会去除
//1.基本用法 
const s = ' a b c ';
console.log(s.trimStart());
//头尾一次性去除
console.log(s.trim());

//2.应用:
示例代码:
 <input type="text" id="username">
    <input type="text" id="btn" value="提交">
    <script>
        const usernameInput = document.getElementById('username');
        const btn = document.getElementById('btn');
        btn.addEventListener('click',() => {
            //验证
            if(usernameInput.value.trim() != ''){
                //可以提交
            }else{
                //不能提交
            }
        },false);
    </script>
2. 数组的新增方法
-includes()用来判断数组中是否含有某个成员
console.log([1,2,3].includes(2));//true
//第二个参数 
console.log([1,2,3].includes(2,2));//false

//应用:数组去重
//[1,2,1]
const arr = [];
for(const item of [1,2,1]){
    if(!arr.includes(item)){
        arr.push(item);
    }
}
console.log(arr);
-Array.from():将其他类型转换成数组
//基本用法 
console.log(Array.from('str'));//['s','t','r'];

//哪些可以通过Array.from()转换成数组
//所有可遍历的:数组,字符串,Set,Map,NodeList,arguments 
console.log(Array.from(new Set([1,2,1])));
-find()和findIndex()
find()寻找某个值,找到了满足条件的第一个就立即返回
findIndex()寻找某个值对应的索引,找到满足条件的第一个就立即返回其索引
//基本用法 
const fd = [1,5,10,15].find((value,index,arr) => {
    return value > 9;
})
const fdIndex = [1,5,10,15].findIndex((value,index,arr) => {
    return value > 9;
})
console.log(fdIndex);

//应用
const students = [
    {
        name:'张三',
        sex:'男',
        age:22
    },
    {
        name:'李四',
        sex:'女',
        age:20
    },
    {
        name:'王五',
        sex:'男',
        age:23
    },
];
const s = students.find(value) => value.sex === '女');
console.log(s);
3. 对象的新增方法
-Object.assign()用来合并对象
const apper = {
    color:'红色',
    shape:'圆形',
    taste:'甜'
};
const pen = {
    color:'黑色',
    shape:'圆柱形',
    use:'写字'
};
const result = Object.assign(apper,pen);
console.log(result);
const result1 = Object.assign({},apple,pen);//pen与apple对象合并后放到第一个对象中。
console.log(result1);

//注意事项
基本数据类型作为源对象
Object.assign(目标对象,源对象1,源对象2...);
与对象的展开类似,先转换成对象,再合并
console.log(Object.assign({},undefined));

//同名属性性的替换
//后面的直接覆盖前面的

//应用 
//合并默认参数和用户参数
const logUser = (userPtions) => {
    const DEFAULTS = {
        username:'Zhansan',
        age:0,
        sex:'male'
    };
    const options = Object.assign({},DEFAULTS,userOptions);
    console.log(options);
};
logUser();
-Object.keys()获取键、Object.values()获取键的值、Object.entries()获取键和值
//1.基本用法: 
const person = {
    name:'Lisi',
    age:23,
};
console.log(Object.keys(person));//['name','age']
console.log(Object.value(person));//['Lisi',23]
console.log(Object.entries(person));//['name','Lisi'] ['age',18]

//使用for...of循环遍历对象
const person = {
    name:'Lisi',
    age:23,
};
for(const key of Object.keys(person)){
    console.log(key);
}
for(const value of Object.value(person)){
    console.log(value);
}
for(const entries of Object.entries(person)){
    console.log(entries);
}
for(const[key,value] of Object.entries(person)){
    console.log(key,value);
}

-----------------------------------------------------------------
ES6之Promise与Clss类
Promise:用来解决过多回调函数嵌套的问题
1.初始Promis
-Promise是什么
//1.Promise是异步操作的一种解决方案
//之前是用回调函数
document.addEventListener('click',() => {
    console.log('这里是异步');
},false);
console.log('这里是异步');

//2.什么时候用Promise
//Promise一般用来解决:层层嵌套的回调函数的问题
*{
            margin:0;
            padding:0;
        }
        #box{
            width: 300px;
            height: 300px;
            background-color: red;
            transition:all 0.5s;
        }
    </style>
</head>
<body>
    <div id="box"></div>
    <script>
        const move = (el,{x=0,y=0} = {},end=() => {}) => {
            el.style.transform = `translate3d(${x}px,${y}px,0)`;

            el.addEventListener('transitionend',() => {
                end();
            },false);
        };
        
        const boxEl = document.getElementById('box');
        // document.addEventListener('click',() => {
        //     move(boxEl,{x:150},() => {
        //         move(boxEl,{x:150,y:150},() => {
        //             move(boxEl,{y:150},() => {
        //                 move(boxEl,{x:0,y:0});
        //             })
        //         })
        //     })
        // },false);

        //以上嵌套一旦多了就会变得很复杂,Promise就是用来解决这个问题的
        const movePromise = (el,point) => {
            return new Promise((reslove) => {
                move(el,point,() => {
                    resolve();
                });
            });
        }; 
        document.addEventListener('click',() => {
            movePromise(boxEl,{x:150}).then(() => {
               return movePromise(boxEl,{x:150,y:150});
            }).then(() => {
                return movePromise(boxEl,{y:150});
            }).then(() => {
                return movePromise(boxEl,{x:0,y:0});
            });
        },false);
    </script>
-Promise的基本用法
//实例化构造函数生成实例对象来使用
const p = new Promise(() => {});
//Promise的状态
const p = new Promise((resolve,reject) => {
//pROMISE用3种状态,一开始是pending(未完成),执行resolve,变成fulfilled(resolved),已成功
    //resolve();//成功  pending->fulfilled
    rsolve();//pending->rejected 已失败
});
console.log(p);//v
//then()方法 接受resolve 和 reject传的参数
p.them(() => {
    console.log('success');
},() => {
    console.log('error');
});
//resolve和reject函数传参
const p = new Promise((resolve,reject) => {
    //resolve(usernaem:'Lisi');
    reject('reason');
});
p.then((date) => {
    console.log('success',date);
},(err) =>{
    console.log('error',err);
})
2.Promise的实例方法
.then()
//什么时候执行
//pending->fulfilled(成功的时候),执行then的第一个回调函数
//pending->rejected(失败的时候),执行then的第二个回调函数
//执行后的返回值:返回一个新的Promise对象
cosnt p = new Promise((resolve,reject) => {
    //resolve();
    reject();
});
const p2 = p.then(() => {
    //如果成功执行第一个回调
},() => {
    //如果失败执行第二个回调
}).then().then;//可以接着调用then()方法 
console.log(p === p2);//true


//then方法返回的Promise对象的状态改变
const p = new Promise((resolve,reject) => {
    resolve();
    //reject();
});
const p2 = p.then(() => {

},() => {

}).then(() => {

},() => {

});
.catch()是then()的特例
//1.有什么用
then((data)=>{},(err)=>{});
then((data)=>{});
catch 专门用来处理rejected状态
//2.基本用法
new Promise((resolve,reject)=>{
    //resolve(123);
    reject('reason');
}).then((data)=>{
    console.log(data);
}).catch((err) => {
    console.log(err);
});

//catch()可以捕获它前面的错误
//一般总是建议,Promise对象后面要跟catch方法,这样可以处理Promise内部发生的错误。
.finally()本质:是then()的特例
//1.什么时候执行 
当Promise状态发生变化时,不论如何变化都会执行,不变化不执行
new Promise((resolve,reject) =>{
    //resolve(123);
    reject('reason');//是错误在后面要用catch来捕捉
}).finally((data)=>{
    console.log(data);
}).catch((data)=>{
    //捕获错误就不会报错
});
//finally()理解
new Promise((resolve,reject) => {
    reject('reason');
}).finally((data) => {
    console.log(data);
}).catch((err) =>{})
//等同于 
new Promise((resolve,reject) => {
    reject('reason');
}).then((result) => {
    //会直接返回结果
    retrue result;
},err => {
    return new Promise((resolve,reject) => {
        reject(err);
    })
}).then((data)=>{
    console.log(data);
}).catch((err) => {
    console.log(err);
});
3.Promist的构造函数方法
-Promise.resolve()和Promise.reject()
//本质 
Promise.resolve()是成功状态Pormise的一种简写形式
new Promise((resolve) => {
    resolve('foo');
})
//可以简写为 
Promise.resolve('foo');
//参数
//一般参数
Promise.resolve('foo').then((data) => {
    console.log(data);
})
//Promise作为参数
const  p1 = new Promise((resolve) => {
    setTimeout(() => {
        resolve('我被执行了');
    });
});
Promise.resolve(p1).then((data) => {
    console.log(data);
});
当resolve函数接受的是Pormise对象时,后面的then会根据出传递的Promise对象的状态执行哪一个回调
//在then方法中的应用
const thenable = {
    then(resolve,reject){
        console.log('then);
        resolve('data');
    }
};
Promise.resolve(thenable).then{
    data => console.log(data),
    err => console.log(err)
};
console.log(Promise.resolve(thenable));
//Promise.reject():失败状态的一种简写形式
//new Promise((resolve,reject) => {
    reject('reason');
});
等价于
Promise.reject('reason');
//参数 
//不管什么参数,都会原封不动的向后传递,作为后续方法的参数
const p1 = new Promise((resolve) => {
    setTimeout(resolve,1000,'我执行了');
});
Promise.reject(p1).catch(err => console.log(err));

new Promise((resolve,reject) => {
    resolve(123);
}).then((data) => {
    //return data;
    return Promise.reject('reason')'
}).then((data) => {
    console.log(data);
}).catch((err) => {
    console.log(err);
});


-Promise.all()
//有什么用 :关注多个Promise对象的状态变化

//基本用法 
const delay = (ms)=>{
    retrun new Promise(resolve =>{
        setTimeout(resolve,ms);
    });
};

cosnt p1 = delay(1000).then(() => {
    console.log('p1完成了');
    retrue 'p1';
});
cosnt p2 = delay(2000).then(() => {
    console.log('p2完成了');
    retrue 'p2';
});
cosnt p = Promise.all([p1,p2]);
p.then((data) => {
    console.log(data);
},(err) => {
    conosle.log(err);
});
-Promise.race()和Promise.allSettled()
//用什么用:都是关注多个Promise对象的状态变化
//基本用法
const recePromise = Promise.race([p1,p2]);
racePromise.then((data) => {
    console.log(data);
},(err) => {
    console.log(data);
})

//2.Promise.allSettled()
cosnt allSettledPromise = Promise.allSettled([p1,p2]);
allSettledPromise.then((data) => {
    console.log(data);
},(err) => {
    console.log(err);
})
4.Promise的注意事项和应用
-Promise的注意事项
//1.resolve或reject执行后的代码
new Promise((resolve,reject) => {
    resolve(123);
    //reject('reason');
    console.log('hi');//hi 还是会执行之后的代码
})
//2.Promise.all/race/allSettled的参数问题
参数如果不是Promise数组,会将不是Promise的数组元素转变成Promise对象

Promise.all([1,2,3]).then(datas =>{
    console.log(datas);[1,2,3]
});
//等价于
Promise.all([
    Promise.resolve(1),
    Promise.resolve(2),
    Promise.resolve(3)
]).then(datas =>{
    console.log(datas);
});

//不只是数组,任何可遍历的都可以作为参数传过来
即 数组,字符串,Set,Map,NodeList,arguments 
Promise.all(new Set([1,2,3]).then((datas) => {
    cosole.log(datas);
}))

//3.Promise.all/race/allSettled的错误处理
cost delay = (ms) => {
    return new Promise((resolve) => {
        setTimeout(resolve,ms);
    });
};
const p1 = delay(1000).then(() =>{
    console.log('p1完成了');
    return 'p1';
});
const p2 = delay(2000).then(() =>{
    console.log('p2完成了');
    return 'p2';
});
const allPromise = Promise.all([p1,p2]);
allPromise.then((datas) => {
    console.log(datas);
}).catch((err) => {
    console.log(err);
})
-Promise的应用 
示例代码: 
<img
     src="https://img.mukewang.com/5e6af63d00011da31872.764.jpg" alt="" id="img">
     <script>
         //异步加载图片
         const loadImgAsync = (url) =>{
            return new Promise((resolve,reject) => {
                const img = new Image();
                //当图片加载成功后出发
                img.onload = () => {
                    resolve(img);
                };
                img.onerror = () =>{
                    reject(new Error(`Could not load Image at ${url}`));
                };
                img.src = url;
            });
         };

         const imgDOM = document.getElementById('img');
         loadImgAsync('https://img.mukewang.com/5e6af63d00011da31872.764.jpg').then(
             (img) =>{
                console.log(img);
             }
         ).catch((err) =>{
             console.log(err);
         });
     </script>

---------------------------------------------------------------------
Class类
1.初始Class
- Class是什么
/认识Class
人类:类
具体的人:实例、对象
/Class的基本用法:使用Class要先声明
class Person{
    //所有的类里里面必须有构造方法
    constructor(name,age){
        //console.log('实例化时执行构造方法');
        this.name = name;
        this.age = age;//this指向的时实例化的对象
        //一般在构造方法中定义属性,方法不再构造方法中定义,会占用很多内存
        //this.speak = () => {}
    }
    //定义方法要在构造方法的外面
    //speak(){};
}
//类在使用时必须时new + 类名
const zs = new Person('Zs',18);
const ls = new Person('Lisi',17);
console.log(zs.name);
console.log(zs.age);
console.log(zs.speak());
console.log(ls.name);
console.log(ls.age);
console.log(ls.speak());
cosole.log(zs.speak() === ls.speak());//false 说明并不是同一个方法
/Class与构造函数
class Person{
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    speak(){
        console.log('speak');
    }
}

//构造函数的写法
function Person(name,age){
    this.name = name;
    this.age = age;
}
//构造函数的方法是定义在它的原型上的
Person.prototype.speak = function(){};
- Class的两种定义形式
/声明形式:class Person{
    constructor(){};
    speak(){}
}
/表达式形式:
const Person = class{
    constructor(){};
    speak(){
        console.log('方法执行了');
    };
};
new Person();
2.Class的属性和方法
-实例属性,静态方法和静态属性
class Person{
    constructor(name){
        this.name = name;//这就是实例化属性
    }
}
const p = new Person('xiaohong');
console.log(p.name);

/静态方法:就是类的方只是在类之前加static
class Person{
    constructor(name,sex){
        this.name = name;
        this.sex = sex;
    }
    static speak(){
        console.log('人类可以说话');
    }
}
const p = new Person('Lisi');
Person.speak();//静态方法就是类的方法直接用类名调用即可

/静态属性
class Person{
    constructor(name){
        this.name = name;
    }
    //静态属性的写法
    static getVersion(){
        return '1.0';
    }
}
console.log(Person.getVersion());
-私有属性和方法 私有属性:就是类里面的属性和方法只能在类里使用,不能在类外部使用
/为什么需要私有属性和方法
/模拟私有属性和方法:ES6目前还不支持私有属性
//_开头表示私有
class Person{
    constructor(name){
        this._name = name;//表示私有,正常方法是使用不到了
    }
}
//模拟方法2:将私有属性和方法移出类
(function(){
    let username = '';
    class Person{
    constructor(name){
        //this.name = name;
        username = name;
    }
    getName(){
      return this.name;
    }
}
})()
3.Class继承
-extends
/子类继承父类
class Person{
    constructor(){
        this.name = name;
        this.sex = sex;
        this.say = function(){
            console.log('hello);
        }
    }
    speak(){
        console.log('普通方法');
    };
    static speak(){
        console.log('静态方法');
    };
}
Person.version = '1.0';

//子类继承父类
class Programmer extends Person{
    constructor(name,sex){
        super(name,sex);//子类要用super关键字来调用父类的属性
    }
}
const zs = new Programmer('zs','男');
console.log(zs.name);
console.log(zs.sex);
zs.say();
zs.speak();
Programmer.speak();
console.log(Programmer.version);
/改写继承的属性和方法
//采用同名覆盖
-super:只能用在子类的构造方法中,用在其他地方就会报错
/可以作为函数调用
class Person{
    constructor(){
        this.name = name;
    }
}

class Programmer extends Person{
    constructor(name,sex){
        super(name,sex);
    }
}
/可以作为对象使用
//在构造方法中使用
//super代表父类的原型对象Person.prototype
class Persion{
    constructor(name){
        this.name = name;
    }
    speak(){
        console.log('hello');
    }

    static speak(){
        console.log('Persion speak');
    }
}

class Programmer extends Person{
    constrctor(name,sex){
        super(name,sex);

        super.speak();
    }
}

//在静态方法的使用 super的指向父类,而不是父类的原型
static speak(){
    super.speak();//不会覆盖父类方法,可以在子类新加方法
    console.log('Programmer speak');
}
Programmer.speak();
/注意事项
使用super的时候,必须显示指定是作为函数函数作为对象使用,否则会报错。
console.log(super());//作为函数 
console.log(suuper.speak);//作为对象
4.Class的应用
-幻灯片

-----------------------------------------------------------------
ES6之Module模块与Babel编译
Module模块系统
1.初始Module
-Module是什么
/什么是模块:模块就是一个一个的局部作用域的代码块
/什么是模块系统
模块系统需要解决的主要问题:
模块化的问题
消除全局变量
管理加载顺序
-Module的基本用法
/使用Module模块化之前的例子
/使用script标签加载模块
/分析Module解决问题
补充:只要你会用到import或export,在使用script标签加载的时候,就要加上type='module'

2.Module的导入和导出(导出就是暴露出去给别的使用,导入就是使用暴露出来的东西)

-export default导出 和 import导入
module.js 
const age = 18;
const sex = 'male';
export default age;
//一个模块只能有一个export default 
-export 导出和对应的import导入
/基本用法 
export声明或语句
export const age = 18;//导出 
const {age} from './module.js';//导入 

/多个导出
function fun(){};
class className{};
const age = 18;
export{fun,className,age};
//统一导入
import{fun,age,className}from './module.js';
/导出导入时起别名
import{fun as func,className as Person,age};
/整体导入
import * as obj from './module.js';
/同时导入
import age2,{fun,age,className}from './module';
3.Module的注意事项和应用
-Module的注意事项 
/模块顶层的this指向
模块中,顶层的this指向undefined
/import关键字和import()函数 
import命令具有提升效果,会提升效果,会提升到整个模块的头部,率先执行
console.log('沙发');
console.log('第二');
import './module.js';//即使是在最后也会最先执行。

//import()可以按条件导入
if(PC){
    import('pc.js').then().catch();
}else if(Mobile){
    import('mobile.js');
}
/导入导出的复合写法
export {age} from './module.js';
//等价于
import {age} from './module.js';
export {age} from './module.js';
-Module的应用 


--------------------------------------------------------------------
Babel与Webpack
1.Bable 
-Bable是什么(解决兼容性问题)
/认识Bable
官网:https://babeljs.io/
在线编译:https://babeljs.il/repl
babel是js的编译器
作用:就是使ES6的代码兼容到低版本的JS代码中和低版本的浏览器
/使用Babel
/解释编译结果
Babel本身可以编译ES6的大部分法,比如let,const,箭头函数,类,
但对于ES6新增的API,如:Set,Map,Promise等全局对象,以及一些定义全局对象上的放方法
(比如:Object.assign/Aray.from)都不能直接编译,需要借助其它的模块
Babel一般需要配合Webpack来编译模块语法。
-Babel的使用方式
/Babel有哪些使用方式
/在命令行工具中使用Babel

-使用Babel前的准备工作
/什么是Node.js和npm
Node.js是个平台或者工具
后端的JavaScript=ECMAScript+IO+File+...等服务端的操作
npm:是Node的包管理工具
/安装Node.js
中文官网:https://nodejs.org/zh-cn/
/初始化项目
/使用npm安装Babel需要的包
初始化项目:npm init
安装:npm install --save-dev @babel/core @babel/cli
安装特定版本的包:npm install --save-dev @babel/core@7.11.0 @babel/cli@7.10.5
npm install:会根据json文件记录的包名重新下载包
-使用Babel编译ES6代码
/编译的命令
npm run build;

"build": "babel src -d lib":通过babel这个命令将src这个目录下的d编译后输出到lib目录下
/Babel的配置文件
// 2.Babel 的配置文件
      // .babelrc

      // npm install @babel/preset-env@7.11.0 --save-dev

      // 创建配置文件 .babelrc,并配置
      // {
      //   "presets": ["@babel/preset-env"]
      // }
2.Webpack 入门
-Webpack是什么
/认识Webpack
webpack是静态模块打包器,当webpack处理应用程序时,会将所有这些模块打包成一个或多个文件
/到底什么是
模块:webpack可以处理js/css/图片,图标字体等单位
静态:开发过程中在于本地的js/css图片/图标等文件,就是静态
/理解Webpack
-Webpack初体验
/初始化项目 
npm init 
/安装webpack需要的包
npm install --save-dev webpack-cli@3.3.12 webpack@4.44.1
/配置webpack
webpack.config.js
const path = require('path');//require:是node的导入,path:是node的模块

module.exports = {
    entry:'./src/index.js',
    output:{
        path:path.resolve(_dirname,'dist'),
        filename:'bundle.js'
    }
}
/打包并测试
3.Webpack 的核心概念
-entry入口和output出口
entry:'./src/index.js':指定入口文件,从这里开始打包
指定多个入口文件的方式
entry:{
    main:'./src/index.js',
    search:'./src/search.js'
}
多个出口打包的方式
output:{
    path:path.resolve(_dirname,'dlist'),
    filename:'[name].js'
}
-loader
/什么是loader
webpack 可以处理js文件,但要处理css,图片等就需要loader
即loader让webpack能够取处理那些非JS文件模块的
/babel-loader:就是babel在webpack使用需要的一个接口
安装babel-loader包:
npm install --save-dev babel-loader@8.1.0 @babel/core@7.11.0 @babel/preset-env@7.11.0
babel-loader的配置:
新建:.babelrc:{"presets":@babel/preset-env}
/配置webpack
webpack.config.js
const path = require('path');

module.exports = {
    entry:'./src/index.js',
    output:{
        path:path.resolve(_dirname,'dist'),
        filename:'bundle.js'
    },
    module:{
        rules:[
           {
               test:/\.js$/
               exclude:/node_modules/    //排除node_module下的文件
               loader:'babel-loader'
           } 
        ]
    }
}
补充:其他的babel-loader配置可可参考:
https://www.webpackjs.com/loaders/

编译新增API
npm install --save-dev core-js@3.6.5
import "core-js/stable";

打包并测试
npm ru webpack 
-plugins(插件)
/什么是plugins
loader被用于帮助webpack处理各种模块,而plugins(插件)则可以用于执行更广泛的任务。
plugins:官网https://www.webpackjs.com/plugins
/html-webpack-plugin
安装插件:npm install --save-dev html-webpack-plugin@4.3.0

配置html-webpack-plugin插件
导入插件:在webpack.config.js:
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry:'./src/index.js',
    output:{
        path:path.resolve(_dirname,'dist'),
        filename:'bundle.js'
    },
    module:{
        rules:[
           {
               test:/\.js$/
               exclude:/node_modules/    //排除node_module下的文件
               loader:'babel-loader'
           } 
        ]
    },
    plugins:[{
        new HtmlWebpackPlug({
            template:'./dome.html'
        })
    }]
}

4.Webpack 的应用
-处理CSS文件
webpack总体项目流程:
初始化:npm init
配置:"scripts":{
    "webpack":"webpack"
}
安装webpack核心包:npm install --save-dev webpack-cli@3.3.12 webpack@4.44.1
创建webpack配置文件:webpack.config.js
const path = require('path');
//引入html-webpack-plugin用来使webpack可以处理css等非js文件,但还需要安装babel-loader
const path = require('path');
//引入html-webpack-plugin用来使webpack可以处理css等非js文件,但还需要安装babel-loader
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    module:'development',//导出的时候是开发模式,不会被压缩
    entry:'./src/index.js',//从这个路径下的文件开始打包
    output:{
        path:path.resolve(__dirname,'dist'),//目录的拼接
        filename:'[name].js',//打包后的名字使用原来的
    },
    //配置loader
    module:{
        rules:[
            {
                test:/\.css/,
                //loader:'css-loader'
                //use:['style-loader','css-loader'],//从右边往开始
                use:[MiniCssExtractPlugin.loader,'css-loader']
            }
        ]
    },
    //使用插件
    plugins:[
        //使用html-webpack-plugin插件要实例化
        new HtmlWebpackPlugin({
            template:'./index.html',
            filename:'index.html'
        }),
        new MiniCssExtractPlugin({
            filename:'css/[name].css'
        })
    ]
};
安装html-webpack-plugin插件:npm install --save-dev html-webpack-plugin@4.3.0
安装babel-loader辅助插件使webpack真正处理非js文件:npm install --save-dev css-loader@4.1.1
安装style-loader(通过style引入css):install --save-dev style-loader@1.2.1
安装min-css-loader(通过link引入css):npm install --save-dev mini-css-extract-plugin@0.9.0

-使用file-loader处理CSS中的图片
如果时外部的资源,是不需要考虑webpack的,只有本地图片才需要
安装file-loader:npm install --save-dev file-loader@6.0.0
file-loader:会把本地图片复制到发布目录里(lib),将其发布到服务器
-使用html-withimg-loader处理HTML中的图片 
安装html-withing-loader:npm install --save-dev html-withimg-loader@0.1.16 
-使用file-loader处理JS中的图片
-使用url-loader处理图片 
之前的file-loader:只是把图片复制到发布目录,改变图片原来的地址。
为了减少向服务端发送请求的次数,以后统一使用url-loader 
安装ulr-loader:npm install --save-dev url-loader@4.1.0

-使用webpack-dev-server搭建开发环境
之前每次修改代码之后都要手动执行npm run webpack命令进行重新打包,
搭建开发环境,就不用这么麻烦了。
安装webpack-dev-server:npm install --save-dev webpack-dev-server@3.11.0
"scripts": {
    "webpack": "webpack",
    //dev:只要执行一次即可
    "dev": "webpack-dev-server --open chrome"
  },
  dev-server的其他参数配置官网:https://www.webpackjs.com/configuration/dev-server/


-------------------------------------------------------------------------------------
前后端数据交互以HTTP协议
前后端通信
1.初识前后端通信
-前后端通信是什么
就是前端和后端数据的过程(即浏览器和服务器交互的过程)。
-后端向前端发送数据
场景:访问页面
-前端向后端发送数据
场景:用户注册
2.前后端通信的过程与概念解释
-前后端通信的过程 
在“请求<--->响应”中完成
-概念解释
前端:就是浏览器端
客户端:只要能和服务器通信的就叫客户端(所以客户端不仅仅是指前端)
后端:就是服务器端
3.前后端的通信方式
-使用浏览器访问页面就完成了前后端的通信
-HTML标签
浏览器在解析HTML标签的时候,遇到一些特殊的标签,会再次向服务器发送请求
还用一些标签,浏览器解析的时候,不会向服务器发送请求,但是用户可以使用他们向服务器发送请求
a,form
link,img,script,iframe
-Ajax和Fetch
前后端通信所要遵循的协议---->HTTP协议
1.初识HTTP
-HTTP是什么
HyperText Transfer Protocol:超文本传输协议
超文本:原先一个个单一的文本,通过超链接将其联系起来。由原先得单一文本变成了无限延申、扩展的超级文本。
HTML、JS、CSS、图片、字体、音频、视频等等文件,都是通过HTTP(超文本传输协议)在浏览器和服务器之间传输。
每一次前后端通信,前端需要主动向后端发出请求,后端接受到前端的请求后,可以给出响应。
-HTTP请求和响应的过程
2.HTTP报文(即前后端通信时互相交换的信息)
-HTTP报文是什么
浏览器向服务器发送请求时,请求本身就是信息,叫请求报文
服务器向浏览器发送响应时传输的而信息,叫响应报文
-HTTP报文格式
请求:
请求头:起始行+首部
请求体

响应:
响应头:起始行+首部
响应体
GET请求,没有请求体,数据通过请求头携带
POST请求,有请求体,数据通过请求携带
3.HTTP方法
注:浏览器发送请求时采用的方法,和响应无关
-常用的HTTP方法
GET获取数据:获取资源,
POST创建数据,如注册,
PUT更新数据,如修改个人信息,修改密码,
DELETE删除数据,如删除一条评论
用来定义对于资源(html,css,js等)采取什么样的操作的,各有语义,但具体使用哪个方法没有强制性

-RESTful接口设计:是一种接口设计风格,充分利用HTTP方法的语义
通过用户ID获取个人信息,使用GET方法
接口:https://www.imooc.com/api/http/getUser?id=1

注册新用户,使用POST方法
接口:https://www.imooc.com/api/http/addUser

修改一个用户,使用POST方法
接口:https://www.imooc.com/api/http/modifyUser

删除一个用户,使用POST方法
接口:https://www.imooc.com/api/http/deleteUser

restFul设计接口风格:
根据语义进行使用接口的请求方式
4.GET 和 POST方法的对比
-语义
GET通过地址在请求头中携带数据
能携带的数据量和地址的长度有关系,一般就几k

POST既可以通过地址在请求头中携带数据,也可以通过请求体携带数据
能携带的数据是无限的

所以,携带少量数据,可以使用GET请求,大量的数据可以使用POST请求

-缓存
GET可以被缓存,POST不会被缓存
-安全性
准确的来说:没有安全性可言,POST可以通过控制台看到数据
5.HTTP状态码
-HTTP状态码是什么
定义服务器对请求的处理结果,是服务器返回的
-HTTP状态码的语义
100-199消息:代表请求已经被接受,需要继续处理
websocket

200-299成功
200

300-399重定向(在原来方向的基础上重新指定一个方向)
http://www.imooc.com 请求这个地址,它还会重新给一个地址(https://www.imooc.com)
才是成功的

301 Moved Permanetly永久性移动

400-499 请求错误
404 Not Found 

500-599服务器错误
500 错误在服务器

--------------------------------------------------------------
本地存储:就是把数据存储在用户端而不是服务端
1.Cookie
-初始Cookie
/Cookie是什么
Cookie全称HTTP Cookie,简称Cookie
是浏览器存储数据的一种方式
因为存储在用户本地,而不是存储在服务器上,是本地存储
Cookie一般随浏览器每次请求发送到服务器端(比如第一次访问英文网站,改为中文后,下次打开还是中文的)

/Cookie有什么用
利用Cookie跟踪统计用户访问该网站的习惯,比如什么时间访问,访问了哪些页面,在每个网页停留的时间等。

/在浏览器中操作Cookie
不要在Cookie中保存密码等敏感信息,它可以通过document.cookie得到

-Cookie的基本用法
写入Cookie
document.cookie = 'username = zs';
document.cookie = 'age=18';
读取Cookie
console.log(document.cookie);

-Cookie的属性
Cookie的名称(Name)和值(Value)
Nmae,Value最重要的两个属性,创建Cookie时必须填写,其他属性使用默认
注:Cookie的名称或值如果包含非英文字母,则写入时需要使用encodeURIComponent()编码,
读取时使用decondeURLComponert()解码
document.cookie = `username=${encodeURIComponent('张三')}`;
doucment.cookie = `${encodeURLComponent('用户名')}=${encodeURLComponent('张三')}`;

失效(到期)时间
对于失效的Cookie,会被浏览器清除
如果没有设置失效时间,这样的Cookie称为Cookie
默认情况,它存放咋内存中,当会话结束,也就是浏览器关闭时,Cookie消失

想长时间存放,设置expires 或 max-age即可
expires:值为Date类型
doucment.cookie = `username=lise; expires=${new Date('2026-01-01 00:00:00')}`;

max-age 
值为数字,表示当前时间+多少秒后过期,单位是秒
document.cookie = 'username=lisi; max-age=5';


-Cookie的封装
封装Cookie
示例代码: 
/*把cookie封装成一个模块
*对外提供三个方法:set get remove
*/


//写入Cookie
const set = (name,value,{maxAge,domain,path,secure}={}) => {
    let cookieText = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;

    if(typeof maxAge === 'number'){
        cookieText += `; max-age=${maxAge}`;
    }
    if(domain){
        cookieText += `; domain=${domain}`;
    }
    if(path){
        cookieText += `; path=${path}`;
    }
    if(secure){
        cookieText += `; secure}`;
    }

    document.cookie = cookieText;
};


//通过name获取cookie的值
const get = name => {
    name = `${encodeURIComponent(name)}`;
    const cookies = document.cookie.split('; ');

    for(const item of cookies){
        const[cookieName, cookieValue] = item.split('=');


        if (cookieName === name) {
            return decodeURIComponent(cookieValue);
          }
    }
    return undefined;
};


//根据name,domain和path删除Cookie
const remove = (name,{domain,path} = {}) =>{
    set(name,{domain,path,maxAge:-1});
};
export{set,get,remove};

使用封装好的Cookie实现网站语言切换
-Cookie的注意事项
/前后端都可以写入和获取Cookie
前后端都可以创建Cookie

/Cookie有数量限制
每个域名下的Cookie数量有限
当超过单个域名限制之后,再设置Cookie,浏览器就会清除之前设置的Cookie

/Cookie有大小限制
每个Cookie的存储容量很小,最多只有4KB左右。

2.localStorage(key,value)--键值
-初识localStorage
/localStorage是什么
localStorage也是一种浏览器存储数据的方式(本地存储),它只是存储在本地,不会发送到服务器端。
单个域名下的localStorage总大小有限制。
/在浏览器中操作localStorage
/localStorage的基本用法
setItem方法
localStorage.setItem('username','lisi');
localStorage.setItem('age',18);

getItem()方法 
console.log(localStorage.getItem('username'));

removeItem()方法 
localStorage.removeItem('username);

clear()方法 
localStorage.clear();
/使用localStorage实现自动填充
const loginForm = document.getElementById('login');
const btn = document.getElementById('btn');

const username = localStorage.getItem('username');
if(username){
    loginForm.username.value = username;
}

btn.addEventListener('click',e=>{
    e.preventDefault();//阻止默认事件
    localStorage.setItem('username',loginForm.username.value);
    loginForm.submit();
},false);

-localStorage的注意事项
/localStorage的存储期限
localStorage是持久化的本地存储,除非手动清除(比如通过js删除,或者清除浏览器缓存),
否则数据是永远不会过期的。
/sessionStorage
当会话结束(比如关闭浏览器)的时候,sessionStorage中的数据会被清空。
sessiongStorage.setItem('username','lisi');
sessiongStorage.getItme();
sessiongStorage.removeItem();
sessiongStorage.clear();

localStorage键和值的类型
localStorage存储的键和值只能是字符串类型,
不是字符串类型,也会先转化成字符串类型再存进去

/不同域名下能否公用localStorage
不能公用 

/localStorage的兼容性
IE7及一下版本不支持localStorage,IE8开始支持。
支持版本查询网站:caniuse.com


----------------------------------------------------------------------
Ajax和Fetch 

1.Ajax基础
-初识Ajax
异步JavaScript和XML的简写。
Ajax中的异步:在等待服务器的响应过程中,浏览器可以做自己的事情,直到成功获取响应后,浏览器才开始处理响应数据。
XML(可扩展标记语言)是前后端数据通信时传输数据的一种格式。
XML现在已经不怎么用了,现在比较常用的是JSON格式。
/Ajax是什么
Ajax其实就是浏览器与服务器之间的一种异步通信方式。
使用Ajax可以在不重新加载整个页面的情况下,对页面的某个部分进行更新。
/搭建Ajax开发环境
Ajax需要服务器环境,非服务器环境下,很多浏览器无法正常使用Ajax
注册验证;
网络提示;
-Ajax的基本用法
/XMLHttpRequest
Ajax想要实现浏览器与服务器之间的异步通信,需要依靠XMLHttpRequest,它是一个构造函数。
不论是XMLHttpRequest,还是Ajax,都没有和具体的某种数据格式的要求。

/Ajax的使用步骤
(1)创建xhr对象
const xhr = new XMLHttpRequest();
(2)准备发送请求:有3个参数(方法,地址,异步)true:代表异步
xhr.open('HTTP方法:get,post,put,delete',URL,true);
(3)正式发送请求
调用send()正式发送请求:send()的参数是通过请求携带的数据
xhr.send();
(4)监听事件,处理响应当获取到响应后,会触发xhr对象的readystatechange事件,可以在该事件中对响应进行处理
xhr.onreadystatechange = () =>{
    //readysatatechange事件监听readyState这个变化,它的值从0-4,一共5个状态
    //xhr.status:HTTP状态码 200
    //xhr.statusText:HTTP状态说明 0K
    //获取响应后,响应的内容会自动填充xhr对象的属性而存在
    if(xhr.readyState!==4) return;
    //状态码
    if((xhr.status>200&&xhr.status<300)||xhr.status===304){
        console.log('正常使用响应数据');
        console.log(xhr.responseText);
    }else{};
};
0:未初始化,尚未调用open()
1:启动。已经调用open(),但尚未调用send()
2:发送。已经调用send(),但尚未接受到响应
3:接受。已经接受到部分响应数据
4:完成。已经接收到全部响应数据,而且已经可以在浏览器中使用了。
/使用Ajax完成前后端的通信
//通信地址
const url = 'https://www.imooc.com/api/http/search/suggest?words=js'

-GET请求 
/携带数据
在地址栏请求体中携带:?name=lisi&age=18
/数据编码
如果携带的数据是非英文字母的话,比如说汉字,就需要编码之后再发送给后端,不然会造成
乱码问题。可以使用encodeURIComponent()编码。
`https://www.imooc.com/api/http/search/suggest?words=${encodeURIComponent('前端')}`

示例代码: 
//使用Ajax完成前后端的通信
        //通信地址
        const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
        //1.创建对象
        const xhr = new XMLHttpRequest();
        //2.使用onredystatechange事件进行监听
        xhr.onreadystatechange = () =>{
            if(xhr.readyState !== 4) return;//说明数据还没准备好

            if((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304){
                console.log(xhr.responseText);
                console.log(typeof xhr.responseText);
            }
        };
        //3.准备发送
        xhr.open('GET',url,true);
        //4.正真发送
        xhr.send(null);
-POST请求 
/数据携带
POST请求主要通过请求体携带数据,同时也可以通过请求头携带
示例代码: 
//使用Ajax完成前后端的通信
        //通信地址
        const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
        //1.创建对象
        const xhr = new XMLHttpRequest();
        //2.使用onredystatechange事件进行监听
        xhr.onreadystatechange = () =>{
            if(xhr.readyState !== 4) return;//说明数据还没准备好

            if((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304){
                console.log(xhr.responseText);
                console.log(typeof xhr.responseText);
            }
        };
        //3.准备发送
        xhr.open('POST',url,true);
        //4.正真发送
        //POST请求可以在send中传,而GET请求不可以
        //如果想发送数据,直接写在send()的参数位置,一般是字符串
        //方式一
        xhr.send('username=lise&age=18');
        //方式二:需要JSON
/数据编码
2.JSON
-初识JSON
/JSON是什么
JSON是Ajax发送和接收数据的一种格式
常见的数据格式:
XML;
username=lise&age=18;
JSON;(JavaScript Object Notation)JS的对象表示法
JSON格式:{
    "code":200,"data":
    [{"word":"jsp"},{"word":"js"},{"word":"json"},
    {"word":"js \u5165\u95e8"},{"word":"jstl"}]
    }

/为什么需要JSON
JSON有3中形式,每种形式的写法都和JS中的数据类型很像和JS中的数据类型很像,可以很轻松的和JS中

-JSON的3种方式
/简单值形式
JSON的简单值形式就对应着JS中的基础数据类型:数字,字符串,布尔值,null
注意事项:
(1)JSON中没有undefined中
(2)JSON中的字符串必须使用双引号
(3)JSON中不能有注释
plain.json:
5
"字符串"
/对象形式
obj.json: 
{
    "name":"张三",
    "age":18,
    "hobby":["足球","篮球"],
    "family":{
        "father":"张大",
        "mother":"小丽"
    }
}
注意事项:
(1)对象中的属性名必须使用双引号,属性值如果时字符串也必须使用双引号;
(2)JSON中只要涉及到字符串,就必须使用双引号。不支持undefined。
/数组形式
arr.json:
    {
        "id":1,
        "username":"张三",
        "comment":"666"
      
    },
    {
        "id":2,
        "username":"李四",
        "comment":"999"
      
    }
]
-JSON的常用方法
(1)JSON.parse():可以将JSON格式的字符串解析成JS中的对应值
console.log(JSON.parse(xhr.responseText));

(2)JSON.stringify():可以将JS的基本数类型,对象或者数组转换成JSON格式的字符串。
console.log(
    JSON.stringify(
        {
            username:'lisi',
            age:18
        }
    )
)
此时就可以子啊xhr.open(
    JSON.stringify(
        {
            username:'lisi',
            age:18
        }
    )
)中传了
使用JSON.parse()和JSON.staringify()封装localStorage
示例代码: 
const storage = window.localStorage;

const set = (key,value) =>{
    storage.setItem(key,JSON.stringify(value));
};

const get = (key) =>{
    return JSON.parse(storage.getItem(key));
};

const remove = (key) =>{
    storage.removeItem(key);
};

const clear = () =>{
    storage.clear();
};

export{set,get,remove,clear};

3.跨域
-初识跨域

/跨域是什么
/什么是不同域,什么是同域
//请求本地的文件就是同域
//const url = './index.html';

//请求远程地址就是不同域即跨域,默认情况下是会被浏览器阻止
const url = 'https://www.imooc.com'
eg:
https://www.imooc.com:443/course/list 
http://www.imooc.com:80/course/list 
这两个就是跨域(端口号不一样)。
https(协议)://www.imooc.com(域名):443(端口号)/course/list(路径)
协议、域名、端口号,任何一个不一样,就是跨域,与路径无关。
/跨域请求为什么会被阻止
阻止跨域请求,其实是浏览器本身的一种策略---同源策略。

其它客户端或服务器都不存在跨域被阻止的问题。


/跨域解决方法
-CORS跨域资源共享
Access-Control-Allow-Origin:*:表明允许所有的域名来跨域请求它。
Access-Control-Allow-Origin:http://127.0.0.1:5500
/CORS是什么
/使用CORS跨域的过程
(1)浏览器发送请求
(2)后端在响应头中添加Access-Control-Allow-Origin 头信息
(3)浏览器接收到响应
(4)如果是同域下的请求,浏览器不会额外做什么,这次前后端通信就完成了
(5)如果是跨域请求,浏览器会从响应头中查找是否允许跨域访问
(6)如果允许跨域,通信圆满完成。
(7)如果没有找到或不包含想要跨域的域名,就丢弃响应结果


/CORS的兼容性
IE10及以上版本的浏览器可以正常使用CORS
-JSONP
/JSONP的原理
<script scr="https://www.imooc.com/index.js"></script>
script标签跨域是不会被阻止的,JSONP就是利用script标签,加载跨域文件的。
/使用JSONP实行跨域
(1)让服务端准备号JSONP接口:JSONP 接口
      // https://www.imooc.com/api/http/jsonp?callback=handleResponse
(2)手动加载JSONP接口
<script scr="https://www.imooc.com/api/http/jsonp?callback=handleResponse"></script>
或者动态加载:
const script = document.createElement('script');//创建标签
script.src= 'https://www.imooc.com/api/http/jsonp?callback=handleResponse';
document.body.appendChild(script);//放到body中。
(3)声明函数
const handleResponse = (data) =>{
    console.log(data);
}
4.XHR对象
-XHR的属性
/responseType和response属性
xhr.responseType = 'text';设置响应类型以什么样的类型返回(一般是字符串),只有等于空或text才可以使用。
xhr.response;获取返回的数据
/timeout属性:设置请求的超时时间(单位ms)
在xhr.open()后使用
xhr.timeout=10;在规定时间内没有响应,就会取消并触发timeout事件

/withCredentials属性:用来只用Ajax发送请求时是否携带Cookie
补充:使用Ajax发送请求,默认情况下,同域时,会携带Cookie;跨域时不会携带Cookie
xhr.withCredentials = true;
-XHR的方法
abort():终止当前请求,一般配合abort事件一起使用
在xhr.send(null)之后使用
xhr.abort();

setRequestHeader()可以设置请求头信息,xhr.setRequestHeader头部字段的名称,头部字段的值
在xhr.open('POST',url,true)之后使用 
//请求头中的Content-Type字段用来告诉服务器,浏览器发送的数据格式是什么格式的
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencodeed');==='username=lise&age=18'
xhr.setRequestHeader('Content-Type','application/json');===JSON格式的
-XHR的事件
load事件:响应数据可用的时候触发
//使用loade事件进行监听
        xhr.onload = () =>{
            if((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304){
                console.log(xhr.response);
            }
        };
//也可以配和addEventListener使用
xhr.addEventListener('load',()=>{
    if((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304){
                console.log(xhr.response);
            }
},false);

error事件:请求发生错误时触发
xhr.addEventListener('error',()=>{
    console.log('error');
},false);

abort事件:调用abort()终止发送请求的时候触发
xhr.addEventListener('abort',()=>{
    console.log('你已经调用abort方法了,被终止了');
},false);

abort();
timeout事件:请求超时时触发。
xhr.addEventListener('timeout',()=>{
    console.log('timeout');
},false);
xhr.timeout = 10;

5.Ajax进阶
-FormData
/使用Ajax提交表单
/FormData的基本用法
(1)通过HTML表单元素创建FormData对象
const fd = new FormData('login');
(2)通过append()方法添加数据
data.append('age',18);
data.append('sex','male');
xhr.send(fd);

-封装Ajax

-使用Promise改造封装好的Ajax

6.Ajax应用
-搜索提示
-二级菜单
-多个Ajax请求的并发执行
7.Ajax扩展
-axios
axios是什么(封装好的第三方Ajax库)不用自己封装Ajax,用axios就可以了。
axios是一个基于Pormise的HTTP库,可以用在浏览器和node.js中 
http://www.axios-js.com/zh-cn/docs/
axios的基本用法
<script src="https://unpkg.com/axios@0.19.2/dist/axios.min.js"></script>
<script>
const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
axios(url,{//向上面的地址发送请求
  methode:'post';//发送方式
  headers:{
      //请求头信息
      'Content-Type':'application/x-www-form-urlencoded',
  },
  params:{//params:参数类型
      //通过请求头携带数据的方式发送请求
      username:'lisi',
  },
  data:{
      //通过请求体携带数据的方式发送请求
      age:18,
      sex:'male'
  }
  //timeout:10;//超时处理
  //因为axios是基于Promise的所以有then()
}).then(resolve=>{
    console.log(err);
}).catch(err=>{
    console.log(err);
});
</script>
-Fetch 
Fetch是什么
Fetch也是请后端通信的一种方式,
Fetch是Ajax(XMLHttpRequest)的一种替代方案,它是基于Promise的

不足:Fetch的兼容性没有Ajax好
Fetch没有提供abort(终止),timeout(超时)等方法。

Fetch的基本用法
fetch()是一个函数,直接调用就可以了
fetch()调用后返回Promise对象
const url = 'https://www.imooc.com/api/http/search/suggest?words=js';

//结合FromData
const fd = new FormData();
fd.append('username','zs');
//第二个参数是对象,用来配置fetch
fetch(url,{
    methode:'post',
    //body:请求体
    body.fd,
    //body:'uername=lisi&age=18',
    headers:{
        'Content-Type':'application/x-www-form-urlencoded'
    }
}).then(resolve=>{
    console.log(resolve);
    //body/bodyUser
    //body只读一次,读过之后就不让读了
    //ok 
    //如果时为true,表示可以读取数据,不用再取判断HTTP状态了
    if(response.ok){
        //直接读取数据
        //response.json();
        //返回出去就可以看到数据了
        return response.json();
        //如果数据不是json格式的用
        return response.text();
    }else{
        //如果状态码有异常抛出一个错误
        throw new Error(`HTTP CODE异常${response.status}`);
    }
    //模式:跨域资源共享
    mode:'cors'
    //跨域的时候把如果想把cookie传过去
    creadentials:'include',
}).then(date=>{
    //用then接收读出来的数据存在data中
    console.log(data);
    
})
.catch(err=>{
    console.log(err);
})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值