ES6-铠甲勇士特供版(log's kaming)

232 阅读14分钟

变量常量

1.let,var和const的用法
var usename ='Alex'
let age = 18
const sex = 'nale'
console.log(usename,age,sex)
2.什么是变量,什么是常量
var usename = 'alex'
usename ='ZS' //var/let 变量,初始化之后还可以重新赋值
const age = 18
age = 19 //const 常量,一旦初始化,就不能重新赋值,否则报错

3. 重复声明
var i = 10
var i = 20 //var允许重复声明
let i = 10 //报错,let与const不允许重复声明
4.变量提升
consle.log(a) //undefined var会提升变量声明到当前作用域的顶部
var a = 10

只要作用域内存在let,const,他们所声明的变量过常量就自动"绑定"这个区域,不再受到外部作用的影响,let const存在暂时性死区

fuction fun(){
    console.log(a)
    let a = 1
} 
5.全局/局部作用域

var没有块级作用域

for(var i = 0 ; i < 3 , i ++){
    console.log(i) //0 1 2
}
consle.log(i) //3

let/const 有块级作用域

for(let i = 0 ; i < 3 ; i++){
    consle.log(i) // 0 1 2
}
console.log(i) //报错

模板字符串

1.模板字符串与一般字符串的区别
const prenson = {
    name:"王浩然",
    age: 17,
}
const info ="我的名字是:"+prenson.name+",我的年龄是"+prenson.age;//一般字符串
console.log(info) //我的名字是王浩然,我的年龄是17
const infos =`我的名字是${prenson.name},我的年龄是${prenson.age}`//模板字符串我的名字是王浩然,我的年龄是17
console.log(infos) //我的名字是王浩然,我的年龄是17
//使用模板字符串方便注入
2.输出`和\等特殊字符
const info = `\` \\`
console.log(info) // `\

箭头函数

1.箭头函数结构

const/let 函数名 = 参数 =>函数体

const add = () =>{}
2.单个参数可以省略圆括号
const add = x =>{
    return x+1
}
3.不适合箭头函数的场景
// 1.作为构造函数 箭头函数没有this
const Person = () =>{}
new Person()
// 2.需要this指向调用对象的时候
document.onclick = function(){
    console.log(this)
}
document.addEventLIstener(
    'click'
    () =>{
        console.log(this) //window
     ),
     false
}
// 3.需要使用argunments的时候
function(add){
    console.log(argunments)
}
add(1,2,3,4,5)
const add = () => conslole.log(argunments)

this指向

1.全局作用域的this指向
console.log(this)  //window
2.普通函数指向
function fn(){
    consloe.log(this)  //window
}
3.箭头函数指向
const calc = {
        add: function () {
            const adder = () => {
                console.log(this);
            }
            adder()
        }
    }
    calc.add()  //calc

解构赋值

1.认识结构赋值
const arr =[1,2,3,4,5]
const a = arr[0]
const b = arr[1]
const c = arr[2]
constle.log(a,b,c) // 123
const [a,b,c] = [1,2,3]
console.log(a,b,c) //123
// 解析某一数据的结构,将我们想要的东西提取出来.赋值变量或常量
2.索引值相同的完成赋值
const [a,[,,b],c] = [1,[2,4[5],3]
console.log(a,b,c)  //123
// 不取值的,可以用逗号跳过
3.默认值的基本用法
const [a,b] = []
const [a,b] = [undefined,undefined]
const [a=1, b=2] = []
console.log(a,b)
4.默认值的生效条件
// 只有当一个数组成员严格模式等于(===)undefined时.对应的默认值才会生效
const [a=1,b=2] = [3,0]
const [a=1,b=2] = [3,null]
const [a=1,b=2] = [3]
console.log(a,b)
5.默认值表达式
//如果默认值是表达式,默认值表达式是惰性求值的
const func = () => {
    console.log("我被执行力")
}
const [x=func()]=[]
cconsole.log(x)
6.undefined和unll的解构赋值
//🦑undefin和null无法转为对象,所以对它们进行解构赋值.会报错
const [toString] = undefined // 报错
const [toString] = null // 报错

函数参数默认值

1.函数参数默认值的基本用法
cibst num = (x,y=999) => x * y
console.log(num(2)) //1998
// 不传参数.或者明确的传递undefined作为参数,只有这两种情况下,默认值才会生效
// 如果默认值是表达式,默认值表达式是惰性求值的

剩余参数

1.剩余参数的本质
const add =(x,y,z,...args) => {
    console.log(x,y,z,args) // 1 2 3 [4,5]
}
add(1,2,3,4,5) 
// 剩余参数永远是个数组,即便没有值也是空数组
2.剩余参数的位置
//剩余参数只能是最后一个参数,否则报错
const add = (x,...args,i) => {} // 报错
3.与解构赋值结合使用
// 剩余参数不一定要作为函数使用
const [num,...ags] = [1,2,3,4]
const func = (num,...argg) => {}
func(1,2,3)
const {x,y,...z} = {a:3,x:1,y:2,b:2}
console.log(x,y,z) //1 2 {a:3,b:2}

展开运算符

1.数组展开运算符的基本用法
cosole.log(Math.min(...[3,2,1])) //1
2.合并数组
const a = [1,2]
const b = [2,3]
const c = [3,4]
console.log([...a,...b,...c) //[1,2,2,3,3,4]

对象的展开运算符

1.展开对象
//对象不能直接展开,必须在{}中展开
const apple = {
    color :"蓝色",
    shape :"方形",
    taste :"苦",
}
console.log({...apple}}
2.合并对象
//相同属性后者覆盖前者
const pen = {
    color :"五颜六色",
    shape :"长方体",
    taste :"甜",
}
console.log({...apple,...pen})

set

1.方法
// add
const s = new Set()
s.add(1),add(2)
console.log(s) // set(2) {1,2}
//删除成员
s.delete(1)
//全删
s.clear()
2.判断重复
const s = new Set([1,2,1])
console.log(1 === 1) //true

// Set对重复值的判断基本遵循严格先等(===)
// 但是对于NaN的判断与===不同,Set中的NaN等于NaN       
3.什么时候用set
//数组去重的时候
//不需要通过下标访问,只需要遍历时
//为了使用set提供的方法和属性时(add delete clear has forEach size 等)
4. 去重
console.log([...new Set([1,2,3,1])])
//字符串
console.log([...new Set('abbbbwds')].join(''))
5.更改dom元素
const = new Set(document.querySelectorAll('p')
s.forEach(function(elem){
    elem.style.color = 'red'
}

Map

1.认识Map
// 键 -> 值 , key -> value
const person = {
    name:'alex',
    age:18
}
const m = new Map()
m.set('name','alex')
m.set('age'.18
2.map和对象的区别
//对象一般用字符串当键
const boj = {
    name:'alex',
    true:'true',
    [{}]:'object'
}
console.log(obj)
//引用和基本数据类型都可以作为map的键
3.方法
const m = new Map()
//使用set添加的新成员,键如果已经存在,厚添加的键值对覆盖已有的
m.set('age',18).set(true,'true').set('age',20)

4.数组
new Map([
    ['name','alex'],
    ['age',18]
 ])
 sonst s = new Set([
     ['name','alex'},
     ['age',18]
 ])
5.更改dom元素
const m = new Map([
    [p1,'red'],
    [p2,'green'],
    [p3,'blue']
])
m.forEach((color,elem) => {
    elem.style.color = color
}

遍历

1.iterator
// iterator:遍历器(迭代器)
//寻找iterator
console.log([1,2][Symbol.iterator]())
//使用iterator
const it = [1,2][Symbol.iterator]()
console.log(it.next())
console.log(it.next())
console.log(it.next())
//Symbole.iterator(可遍历对象的生成方法) -> it(可便利对象) -> it.next() -> it.next()...直到done为true
//一般不会直接使用iterator去遍历 用for..of
for of
const arr = [1,2,3]
for(const item of arr){
    console.log(item)
}
// for..of循环只会遍历那些done为false时对应的value值
//与break和continue一起使用
 const arr = [1,2,3,4]
    for (const item of arr){
        if(item ===2){
            // break
            continue
        }
        console.log(item);
    }
//在for of中取得数组的索引
const arr = [1,2,3]
console.log(arr.keys());
for(const key of arr.keys()){
    console.log(key);
}
//entries()得到的是索引+值组成的数组的可遍历对象
for (const entiries of entiries){
    console.log(entiries);
} 

原生,非原生可遍历
//只要有symbol.iterator方法,并且这个方法可以生成可遍历对象,就是可遍历
//原生可遍历 数组,字符串,set,map,arguments,nodelist
for(const item of[1,2,3]){
     console.log(item);
}
for(const item of 'hi'){
     console.log(item);
}
for(const item of new Set([1,2])){
    console.log(item);
}
for(const elem of Document.querySelectorAll('p')){
    elem.style.color = "red"
}
//非原生可遍历的有哪些]
const person = {sex:'male',age:18}
person[Symbol.iterator] =() =>{
    let index = 0
    return{
        next(){
            index++
            if(index == 1){
                return{
                    value:person.age,
                    done:false
                }
            }
            else if(index == 2){
                return{
                    value:person.sex,
                    done:false
                }
            }
            else{
                return{
                    done:true
                }
            }
        }
    }
}
for(const item of person){
    console.log(item);
}
//有length和索引属性的对象
const obj = {
    0:'alex',
    1:'male',
    length:2
}
obj[Symbol.iterator] =()=>{
    let index = 0 
    return{
        next(){
        let valeu,done;
        if(index <obj.length){
            value = obj[index]
            done= false
        }else{
            value = undefined
            done = true
        }
        index++
        return{
            value,
            done
        }
    }
    }
}
for (const item of obj){
    console.log(item);
}

字符串的新增方法

1.includes()

//基本用法
console.log('abc'.includes('a'));//true
console.log('abc'.includes('ab'));//true
console.log('abc'.includes('bc'));//true
console.log('abc'.includes('ac'));//false
//第二个参数
//表示开始位置,默认是0
console.log('abc'.includes('a'));
console.log('abc'.includes('a',0));
console.log('abc'.includes('a',1));//false
//应用
let url =''
const addURLParam = (url,name,value) =>{
    url += url.includes('?')? "&":"?"
    url += `${name}=${value}`
    return url
}
url = addURLParam(url,'c','fe')
console.log(url);
url = addURLParam(url,'sort','pop')
console.log(url);
//判断数组是否含有某个成员
console.log([1, 2, 3].includes('2'))//false
console.log([1, 2, 3].includes(2))//true
//基本遵循严格相等,但是对于nan的判断与===不同,认为nan===nan
console.log([1, 2, NaN].includes(NaN))//true
//去重
const arr = []
for (const item of [1, 2, 3]) {
     if (!arr.includes(item)) {
         arr.push(item)
    }
}
console.log(arr);
2.padStart()和padEnd()
//基本用法
console.log('x'.padStart(5,'ab'));//ababx
console.log('x'.padEnd(5,'ab'));//xabab
console.log('x'.padEnd(4,'ab'));//xaba
//原字符串长度,等于或大于长度,不会消减原字符串,字符串补全不生效
console.log('abc'.padEnd(10,'123456789'));
console.log('x'.padStart(4));//填充空格
//应用 显示日期格式
console.log('10'.padStart(2,0));//10
console.log('1'.padStart(2,0));//01
3.trimStart()和trimeEnd()
//清除字符串首尾空格,中间的空格不会清楚
const s = ' a b c '
console.log(s.trimStart()); //a b c 
console.log(s.trimEnd()); // a b c 
console.log(s.trim()); // 两头全去
//应用
const usernameinput  = document.getElementById('username')
const btn = document.getElementById('btn')
btn.addEventListener('click',
    () =>{
        console.log(usernameinput.value);
        if(usernameinput.value.trim() !==''){
            console.log('可以');
        }else{
            console.log('不能');
        }
    },false
)

数组新增方法

Array.form()
console.log(Array.form('str'));
//Array.form可转化的,数字,字符串,set,map,nodelist,aerguments
console.log(Array.form(new Set([1,2,1])));
console.log([...new Set([1,2,1])]);
//拥有length属性的任意对象
const obj = {
    '0':"a",
    "1":'b',
    name:'alex',
    length:3
}
console.log(Array.form(obj));
// 作用类似于数组的map方法,用来对每个元素进行处理.将处理后的值放入返回的数组
[1,2].map((value)=>{
   return value * 2
})
console.log(Array.form('12',value=>value*2));
//修改this指向
Array.form('12',value=>{
    '12',
    function() {
        console.log(this);
    }
})
find()和findindex
[1,2,5,10,15].find((value,index,arr)=>{
    // console.log(value.index,arr);
    console.log(this);
    return value>9
},document)
[1,2,5,10,15].findindex((value,index,arr)=>{
    // console.log(value.index,arr);
    return value>9
})
//应用
students.find(value=>value.sex ==='女')
students.findindex(value=>value.sex ==='女')

对象的新增方法

Object.assign()
//Object.assign 直接合并道第一个参数中,返回的就是合并后的对象
const apple ={
    color:'red'
}
const pen ={
    color:'bule'
}
console.log(Object.assign({},apple,pen));
//基本数据类型作为源对象
// Object.assign(目标对象,源对象1,2,3,4)
console.log(Object.assign({},undefined));// {}
console.log(Object.assign({},"str"));// {0:'s',1:"t",2:'r'}
//同名属性的替换 后面的直接覆盖前面的
//合并默认参数和用户参数
const logUser = userOpitions =>{
    const DEFAULTS = {
        username:'zhangsan',
        age:0,
        sex:'male'
    }
    const options=Object.assign({},DEFAULTS,userOpitions)
    console.log(options);
}
logUser()
Object.keys()、Object.values()、Object.entries()
const pen ={
     color:'bule'
 }
 //获取键
console.log(Object.keys(pen));
//获取值
console.log(Object.values(pen));
//都获取
console.log(Object.entries(pen));
//使用for of 遍历对象
for(const[key,value] of Object.entries(pen)){
    console.log(key,value);
}
//并不能保证顺序,一直点和forin是一样的

Promise

基本用法
//Promise是异步操作的一种解决方案 一般用来解决层层嵌套的回调函数
document.addEventListener(
    'click',
    ()=>{
        console.log("这里是异步");
    },
    flase
)
console.log('这里是同步的');
//Promise 解决的不是回调函数,而是回调地狱
// const p = new Promise(()=>{})
//Promise的状态
const p = new Promise((resolve,reject)=>{
    //promise 有三种状态,一开始是pending(未完成),执行resolve,变成fulfilled(resolved),已成功
    //执行reject,变成rejected,已失效
    // primise的状态一旦变化,就不会在改变了
    //pending -> fulfillef
    resolve()
    //pending -> rejected
    reject()
})
//then方法
p.this(
    ()=>{
        console.log('success');
    },
    ()=>{
        console.log('reeor');
    }
)
then
/ pending -> fulfillef时,执行then的第一个回调函数
// pending -> rejected时,执行then的第二个回调函数
// then方法执行后返回一个新的promise对象
const p = new Promise((resolve,reject)=>{
    resolve()
    // reject()
})
p.then(
    data =>{
        console.log('su');
    },
    err =>{
        console.log('err');
        //在then的回调中,return后面的东西会用promise包装一下
        return new Promise((resolve,reject)=>{
            resolve()
        })
    }
).then(
    data =>{
        console.log("su2");
    },
    err =>{
        console.log('err2');
    }
).then(
    data =>{
        console.log("succ3",data);
    },
    err =>{
        console.log("err3" ,err);
    }
)
promise解决回调地狱
const move = (el,point)=>{
    return new Promise((resolve)=>{
        move(el,point,()=>{
            resolve()
        })
    })
}
document.addEventListener('click',()=>{
    move(boxEl,{x:150}).then(()=>{
        return move(boxEl,{x:150,y:150})
    }).then(()=>{
        return move(boxEl,{y:150})
    }).then(()=>{
        return move(boxEl,{x:0,y:0})
    })
},false)
catch()
new Promise((resolve,reject)=>{
    // resolve(123)
    reject('reason')
}).then(
    data =>{
    console.log(data);
}).catch(
    err=>{
    console.log(err);
    throw new Error('reason')
}).then(
    data=>{
    console.log(data);
}).catch(err=>{
    console.log(err);
})
//catch()可以捕获它签前面的错误一般总是建议.promise对象跟catch方法, 这样可以处理promise内部发生的错误
finally()
//当promise状态发生时,不论如何都会执行.不变化不执行
new Promise((resoleve,reject)=>{
    // resolve(123)
    reject('reason')
}).finally(data =>{
    console.log(data);
})
.catch(err=>{

})
//finally()本质上是then()的特例等同于
new Promise((resolve,reject)=>{
    reject('reason')
})
.then(
    result =>{
        return result
    },
err =>{
    return new Promise((resolve,reject)=>{
        reject(err)
    })
}
)
.then(data=>{
    console.log(data);
}).cath(err=>{
    console.log(err);
})

构造函数方法

Promise.resolve()和Promise.reject()
//promise resolve()是成功状态promise的一种简写
new Promise(resolve =>resolve('foo'))
//简写
Promise.resolve('foo')
//一般参数
Promise.resolve('foo').then(data=>{
    console.log(data);
})
//特殊参数promise
const p1 = new Promise(resolve =>{
    setTimeout(resolve,1000,"我执行了")
})
Promise.resolve(p1).then(data=>{
    console.log(data);
})
//当resolve函数接受的rromise对象的时候,后面的then会根据传递的promise对象的状态变化决定执行哪一个回调

new Promise(resolve => resolve(p1)).then(data=>{
    console.log(data);//我执行了
})
//具有then方法的对象
const thenable ={
    then(resolve,reject){
        console.log('then');
        // return 123
        resolve('data')
        // reject('reason')
    }
}
Promise.resolve(thenable).then(
    data=>console.log(data),
    err =>console.log(err)
)
console.log(Promise.resolve(thenable));
//promise.reject()失败状态promise的一种简写形式
new Promise((resolve,reject)=>{
    reject('reason')
})
//等于
Promise.reject('reason')
//不管什么参数,都会原封不动的向后传递,作为后续方法的参数
const p2 = new Promise(resolve =>{
    setTimeout(resolve,1000,"我执行了")
})
Promise.reject(p2).catch(err=>console.log(err))
new Promise((resolve,reject)=>{
    resolve(123)
}).then(data=>{
    return Promise.reject('reason')
}).then(data=>{
    console.log(data);
}).cath(err=>{
    console.log(err);
})
Promise.all()
//promise.all()关注多个promise对象的状态变化
//传入多个promise实例,包装成一个新的promise实例返回
const 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'
})
//Promise.all()的状态变化与所有传入的promise实例对象状态有关
//所有状态都变成resolved,最终的状态才会变成resolved
//只要有一个变成rejected,罪状的状态就会变成rejected
const p = Promise.all([p1,p2])
p.then(data=>{
    console.log(data);
}),err=>{
    console.log(err);
}
Promise.race()和Promise.allSettled()
// promise.race()的状态取决于第一个完成的promise实例对象如果第一个成功了,最终成功的就成功.如果第一个失败了,最终的就失败
const 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 reacePRomise = Promise.race([p1,p2])
reacePRomise.then(data =>{
    console.log(data);
}),err=>{
    console.log(err);
}

// Promise.allSettled状态与闯入的promise状态无关永远都是成功的它只会忠实的记录下各个的promise的表现
const rSettledPRomise = Promise.allSettled([p1,p2])
SettledPRomise.then(data =>{
    console.log(data);
})
Promise的应用
//异步加载图片
const loadingimg = url =>{
    return new Promise((resolve,reject)=>{
        const img = new image()
        img.onload = ()=>{
            resolve(img)
        }
        img.onerror =()=>{
            reject(new Error(`Colud not load image at ${url}`))
        }
        img.src =url
    })
}
const imgDOM = document.querySelector('img')
loadingimg('https://img').then(img=>{
    console.log(img.src);
    setTimeout(()=>{
        imgDOM=img.src
    },1000)
}).catch(err=>{
    console.log(err);
})

Class

class与构造函数
//class基本用法 一般首字母大写
class Person{
    //实例化时执行构造方法,所以必须有构造方法,但可以不写出来
    constructor(name,age){
        console.log('实例化时执行构造方法');
        this.name=name
        this.age=age
    }
    //各个实例共享方法
    speak(){

    }
}
// function Person(name,age){
//     //实例化时执行构造方法,所以必须有构造方法,但可以不写出来
//         console.log('实例化时执行构造方法');
//         this.name=name
//         this.age=age
// }
// person.prototype.speak= function(){}
</script>
Class的两种定义形式
//声明形式
class Person{
    constructor(){
    }
    speak(){}
}
//表达式形式
// const Person = function(){}
const Person = class{
    constructor(){
        console.log('1');
    }
    speak(){}
}
(function(){
    console.log('func');
})()
//立即执行类
(new class{
    constructor(){
        console.log('con');
    }
})()

属性方法

实例属性、静态方法和静态属性
//实例属性
//方法就是值为函数的特殊属性
class Person{
    age=18
    sex ='male'
    getSex =function(){
        return this.sex
    }
    constructor(name,sex){
        this.name =name
        this.sex=sex
    }
}
const p = new Person('alex')
console.log(p.name);
//静态方法
class Person{
    constructor(name,sex){
        this.name =name
        this.sex =sex
    }
    speak(){
        console.log('speak');
    }
    static speak(){
        console.log('人类可以说话');
        //this指向类
        console.log(this);
    }
}
// person.speak = function(){
//     console.log(this);
// }
Person.speak()
//静态属性
class Person{
    constructor(name){
        this.name =name
    }
    speak(){
        console.log('speak');
    }
    //不要这么写,只是提案,有兼容问题
    static version = '1.0'
    static getVersion(){
        return '1.0'
    }

}
const pp = new Person('alex')
console.log(pp.name);
console.log(Person.getVerion);
私有属性和方法
//一般情况下,类的属性和方法都是公开的
class Person{
    constructor(name){
        this.name = name 
    }
    speak(){
        console.log('speak');
    }
    getName(){
        return tshi.name
    }
}
const p = new Person('alex')
console.log(p.name);
p.speak()

// 模拟私有属性和方法  _开头表示私有
class Person{
    constructor(name){
        this._name = name
    }
}
//将私有属性和方法移出类
(function(){
    let name = ''
    class Person{
        constructor(username){
            name = name
        }
    }
    window.Person = Person
})()
(function(){
    const p = new Person('Alex')
    console.log(p.name);
    console.log(p.getName);
})()

继承

extends
//子类继承父类
class Person{
    constructor(name,sex){
        this.name = name
        this.sex = sex
        this.say = function(){
            console.log('say');
        }
    }
    speak(){
        console.log("speak");
    }
    static speak(){
        console.log("statci");
    }
}
//改写记成的属性或方法
class Programmer extends Person{
    constructor(name,sex,feature){
        //this操作不能放在super前面
        super(name,sex)
        this.feature =feature
    }
    //同名覆盖
    speak(){
        console.log('speak');
    }
}
Programmer.version =20
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(name){
        this.name = name
    }
}
class Programmer extends Person{
    constructor(name,sex){
        super(name,sex)
    }
}
new Programmer()
//作为对象使用 在构造方法使用
//super代表父类的原型对象Person.prototype,所有定义在父类实例伤的方法或属性,是无法通过super调用的通过super调用父类的方法时,方法内部的this指向当前的子类实例
class Person{
    constructor(name){
        this.name = name
        console.log(this);
    }
    speak(){
        console.log("speak");
        console.log(this); 
    }
}
class Programmer extends Person{
    constructor(name,sex){
        super(name,sex)
        super.speak()
    }
    speak(){
        super.speak()
        console.log('pro sp');
    }
    //在静态方法中使用 指向父类,而不是父类的原型对象
    //通过super调用父类的方法时.方法内的this指向当前子类,而不是子类实例
    static speak(){
        super.speak()
        console.log('progerammer speak');
    }
}
//使用super的时候,必须显示指定是作为函数还是作为对象使用,否则会报错
class person{
    constructor(name){
        this.name = name
    }
    speak(){
        console.log("speak");
    }
}
class Programmer extends Person{
    constructor(name,sex){
        super(name,sex)
        console.log(super.speak);
    }
}

初始Module

Module是什么
//模块:一个一个的局部作用域的代码块

//模块系统需要解决举要问题
//①模块化的问题
//②消除全局变量
//③管理加载顺序
//requireJS seaJS 模块库
Module的两种导入导出

导出的东西可以被导入(import),并访问

//一个模块没有导出,也可以将其导入,仅会执行一边
<script type='module'>
    import age from './module.js'
</scrpt>
//一个模块只能有一个exprot default
exprot default age
export和对应的import
//不能随意命名
improt{age}from `./module.js`
//exprot声明或语句
export const age = 18
//或
export {age}
//多个导出
improt{fn,age,className} from'./moudule.js'
export {age,fn,calssName}
//起别名
export {age as ge}
//整体导入 会导入所有输出,包括通过export default导出的
improt * as obj from'./moudule.js'
Module的注意事项

1.模块中,顶层的this指向undefined
2.impott和import()
import命令具有提升效果,会提升到整个模块头部,率先执行
import和export命令只能在模块的顶层,不能在代码块中执行

//导入导出复合写法 (无法在当前模块使用)
export {age}from `./module.js`
//等价于
improt{age}from `./module.js`

Webpack

Webpack是什么

wabpack是静态模块打包器,当webpack处理应用程序时,会将所有这些模块打包成一个或多个文件
webpack可以处理js/css/图片,图标字体等单位
开发过程中存在于本地的js/css/图片/图标字体等文件,就是静态的
动态的内容,webpack没办法处理,只能处理静态的

Webpack初体验

1.初始化项目:npm init
2.安装webpack包:npm install --save-dev webpack-cli@3.3.12 webpack@4.44.1
3.配置webpack
4.编译并测试

Webpack的四个核心概念

entry
//单入口
entry:'./src/index.js',
//多入口
entry:{
    main:'./src/index.js'
    search:'./src/search.js'
    }
output
//单出口
output:{
        path:path.resolve(__dirname,'dist'),
        filename:'bundle.js'
    }
//多出口
output:{
        path:path.resolve(__dirname,'dist'),
        filename:'[name].js'
    }
loader
// loader让webpack能够去处理那些非js文件的模块
// babel-loader
// npm install --save-dev babel-loader@8.1.0 @babel/core@7.11.0 @babel/preset-env@7.11.0