ES6

124 阅读3分钟

const 常量标识

    const LIMIT = 10 // 常量一般是大写
    const OBJ_MAP = {
        a: 'A'A: 'a'
    }
    const QUEUE = [1, 2, 3, 4, 5]

1、不允许反复声明赋值

    // 变量重新赋值
    var arg1 = '叶夜葉'
    arg = '宵夜'
    
    // 常量
    // ES5
    Object.defineProperty(window, 'arg2', {
        valur: '宵夜'
        writable: false
    })
    arg2 = '叶夜葉' // 报错

    // ES6
    const arg3 = '宵夜' // const不允许反复声明赋值
    arg3 = '小可'
    
    、、 
    

2、 块级作用域

    if(true) {
        var arg1 = '宵夜'
    }
    console.log('arg1', arg1)
    
    if(true) {
        const arg2 = '宵夜'
    }
    console.log('arg2', arg2) // 报错 arg2 is not defined

3、 无变量提升

    console.log(arg1)
    var arg1 = '宵夜'
    
    // 相当于
    var arg1;
    console.log(arg1)
    arg1 = '宵夜'
    
    // 无变量提升 - 先声明在使用
    console.log(arg2)
    const arg2 = '宵夜' // 报错 arg2 is not defined
    
    // const 不在window中
    const arg3 = '宵夜'
    console.log(window.arg3) // 找不到

4、 let or const

  • 引用类型
    const obj = {
        teacher: '宵夜',
        leader: '小可'
    }
    obj.leader = '部部'
    
    const arr = ['宵夜', '小可']
    arr[0] = 'aaaa'
    // const 在引用类型里面指的是地址

    // ? 引用类型不让他修改
    object.freeze(obj)
    
    const obj2 = {
        teacher: '宵夜',
        leader: '小可',
        zhuawa: ['黄小洋', '部部']
    }
    
    // !freeze只能冻结一层,嵌套引用类型需要遍历递归
    // 面试题  不让修改引用类型所有属性
    function deepFreeze(obj) {
        // 2、确定主执行步骤
        Object.freeze(obj)
        // 3、逐级深入
        (Object.key(obj) || []).forEach(key => {
            let innerObj = obj[key];
            if(typeof innerObj === 'object') {
                // 1、 递归模式确定
                deepFreeze(innerObj)
            }
        })
    
    }

箭头函数

    // 传统函数
    function test(a, b) {
        return a + b
    }
    const test2 = function(a, b) {
        return a + b
    }

箭头函数

    // ES6
    const test1 = (a, b) => {
        return a + b
    }
    const test2 = (a, b) => a + b;
    const test3 = x => {
        // content
    }
    
    const test4 = () => {
        // ....
    }

上下文

    let obj = {
        teacher: '宵夜',
        leader: '小可',
        getTeacher: function() {
            console.log('teacher is:', this.teacher)
            return this.teacher
        },
        getLeader: () => {
            console.log('leader is:', this.leader)
            return this.leader
        }
    }
    obj.getTeacher() // '宵夜'
    obj.getLeader() // undefined

追问: 上下文形成的原因 箭头函数并不会形成独立上下文,内部this指向了window

场景1: dom操作cb时

    const btn = document.querySelector('#btn')
    
    btn.addEventListener('click', function() {
        this.style.color = '#fff'
    })

场景2:类操作

    // 箭头函数无法成为完整构造类
    function Obj(teacher, leader) {
        this.teacher = teacher
        this.leader = leader
    }
    
    const obj = (teacher, leader) => {
        this.teacher = teacher
        this.leader = leader
    }
    // 实例验证
    const o1 = new obj('宵夜', '小可')
    console.log(o1)
    
    // 箭头函数无法构造原型方法 prototype
    Obj.prototype.learn = function() {
        console.log(this.teacher, this.leader)
    }
    obj.prototype.learn = () => {
        console.log(this.teacher, this.leader)
    }

箭头函数的参数特性 没有办法使用argument

    const test = function(teacher) {
        console.log(arguments)
    }
    const test = teacher => {
        console.log(arguments)
    }

class 使js更面向对象 - 类

    // 传统对象 - function
    function Course(teacher, leader) {
        this.teacher = teacher;
        this.leader = leader;
    }
    
    Course.prototype.getCourse = function() {
        return `teacher is: ${this.teacher}, course: ${this.course}`
    }
    
   const course = new Course('宵夜', 'ES6')
    course.getCourse();
    
    
    // ES6
    class Course {
        // init 实例会默认执行
        constructor(teacher, course) {
            this.teacher = teacher
            this.course = course
        }
        // 扩展方法
        getCourse() {
            return `teacher is:${this.teacher}, course:${this.course}`;
        }
    }
    const course = new Course('宵夜', 'ES6')
    course.getCourse()

追问 class的类型是什么

    console.log(typeOf Course); // function 
    // class 其实是语法糖 后期baler打包会成为function

class的prototype

    console.log(Course.prototype); // 有区分 但本职相同

属性定义 构造器 & 顶层定义 两种定义方式

    class Course {
        // init 实例会默认执行
        constructor(teacher, course) {
            this.teacher = teacher
            this.course = course
        }
        // 扩展方法
        getCourse() {
            return `teacher is:${this.teacher}, course:${this.course}`;
        }
        
        get teacher() {
            return this.teacher
        }
        
        set teacher(val) {
            // 留有空间
            this.teacher = val
        }
    }

js 如何建立私有属性

    class Course {
        // init 实例会默认执行
        constructor(teacher, course) {
            this._teacher = teacher
            this.course = course
        }
        // 扩展方法
        getCourse() {
            return `teacher is:${this.teacher}, course:${this.course}`;
        }
        
        get teacher() {
            return this._teacher
        }
    }
    // 修改只读变量,会报错么 - 无法修改但是不会报错
    
    // js 如何建立一个私有属性
    class Course {
        constructor(teacher, course) {
            this._teacher = teacher;
            
            // 在constructor作用域内定义一个局部变量
            let _course = 'es6'
            // 内部通过闭包的形式去暴露该变量
            this.getCourse = () => {
                return _course
            }
        }
    }
    
    class Course {
        #course = 'es6'
        constructor(teacher, course) {
            this._teacher = teacher
        }
        get course() {
            return this.#course
        }
        set course(val) {
            if(val) {
                this.#course = val
            }
        }
    }
    
    
    // 3、封装核心 - 适配器模式
    class utils {
        constructor(core) {
            this._main = core
            this._name = 'my-utils'
        }
        
        get name() {
            return {
                ...this._main.name,
                name: `utils is ${this._name}`
            }
        }
        set name(val) {
            this._name = val
        }
    }

静态方法 - 直接挂载在类上的方法无需实例化获取

    // ES5
    function Course() {
        // ....
    }
    Course.ring = function() {
        //...
    }
    
    // ES6
    class Course {
        constructor() {
            // ....
        }
        static ring() {
        
        }
    }

继承

    // ES5继承
    function Course() {
        // ...
    }
    Course.ring = function() {
        // ...
    }
    Course.prototype.send = function() {
        // ...
    }
    
    function Child() {
        Course.call(this, '宵夜', 'ES5')
        this.ring = function() {
            // ...
        }
    }
    Child.prototype = Course.prototype
    
    // es6
    class Course {
        constructor() {
            //...
        }
        static ring() {
            // ...
        }
        send() {
            // ...
        }
    }
    // 工厂模式
    class Child extends Course {
        constructor() {
            siper('宵夜', 'ES6')
        }
        send() {
            // ...
        }
    }
    
    

key解构

    const zhaowa = {
        teacher: {
            teacher: {
                name: '',
                age: 30
            },
            leader: '',
            name: 'es6'
        }
    }
    // 别名
    const {
        teacher: {
            name,
            age
        },
        leader,
        name: className
    } = zhaowa

追问解构使用场景

1、形参结构

    const sum = arr => {
        let res = 0;
        arr.forEach((v) => {
            res += v
        })
    }
    const sum = ([a, b, c]) => {
        return a + b + c
    }

2、结合初始值

    const course = ({teacher, leader, course = 'yeye'}) => {
        // ...
    }
    
    course({
        teacher: 'yy',
        leader: '宵夜'
    })

3、返回值

    const getCourse = () => {
        return {
            teacher: '',
            leader: ''
        }
    }
    const { teacher, leader } = getCourse()