美文网首页
[ES6] 对象

[ES6] 对象

作者: Darkdreams | 来源:发表于2019-12-16 16:24 被阅读0次

    新增对象字面量语法

    1. 成员速写

    如果对象字面量初始化时,成员的名称来自于一个变量,并且和变量的名称相同,则可以进行简写。

    function person(userName, password, nickName) {
        return {
            userName: userName,    // 原本
            password,              // 简写
            nickName
        }
    }
    
    2. 方法速写

    对象字面初始化时,方法可以省略冒号和function关键字

    const obj = {
        name : "abc",
        age : 20,
        //简写前
        sayHello: function() {
            console.log(this.name)
        }
        //简写后
        sayHello(){
            console.log(this.name)
        }
    }
    
    3. 计算属性名

    有的时候初始化对象,某些属性名可能来自于某个表达式的值,在ES6,可以使用中括号来表示该属性名是通过计算得到的。

    let name = "name", age = "age";
    
    const obj = {
        [name]: "abc",
        [age]: 20
    }
    
    // 调用
    console.log(obj[name])
    

    Object的新增API

    1. Object.is

    用于判断两个数据是否相等,基本上跟严格相等(===)是一致的,除了以下两点:

    1. NaN和NaN相等
    2. +0和-0不相等
    console.log(NaN === NaN);   // false
    console.log(+0 === -0)      // true
    
    console.log(Object.is(NaN, NaN))   // true
    console.log(Object.is(+0, -0))     // false
    
    2. Object.assign

    用于混合对象

    const obj1 = {
        a: "1",
        b: "2",
        c: "3"
    }
    
    const obj2 = {
        a: "a",
        b: "b",
        d: "d"
    }
    
    const obj3 = {
        ...obj1,
        ...obj2
    }
    
    const obj4 = Object.assign({}, obj1, obj2)
    
    3. Object.getOwnPropertyNames 的枚举顺序

    这个方法之前就存在,只不过官方没有明确要求对属性顺序如何排序,如何排序完全由浏览器厂商自行决定。

    ES6规定了该方法返回的数组排序如下:

    • 先排数字,按照升序排序
    • 再排其他,按照书写顺序排序
    const obj = {
        d: "1",
        b: "2",
        c: "3",
        0: "A",
        10: "B",
        5: "C"
    }
    console.log(Object.getOwnPropertyNames(obj))  // ["0", "5", "10", "d", "b", "c"]
    
    4. Object.setPrototypeOf

    该方法用于设置某个对象的隐式原型
    比如:Object.setPrototypeOf(obj1, obj2) == obj1.__proto__ = obj2

    const obj1 = {
        a: "1"
    }
    
    const obj2 = {
        b: "2"
    }
    
    const obj3 = Object.setPrototypeOf(obj1, obj2)
    
    console.log(obj1 === obj3)  // true
    

    面向对象简介

    面向对象:一种编程思想,跟具体的语言

    对比面向过程:

    • 面向过程:思考的切入点是功能的步骤
    // 大象关进冰箱
    // 打开门
    function openFridge (params) {
        
    }
    openFridge()
    // 把大象装进去
    function putIn() {
    
    }
    putIn()
    // 把门关上
    function closeFridge() {
    
    }
    closeFridge()
    
    • 面向对象:思考的切入点是对象的划分
    // 一个冰箱原型
    function Fridge() {
    
    }
    // 一个大象原型
    function Elephant () {
        // 大小,体重,等等
    }
    
    // 给冰箱原型增加三个方法
    Fridge.prototype.openFridge = function() {
        // 打开冰箱
    }
    
    Fridge.prototype.closeFridge = function () {
        // 把冰箱关上
    }
    
    Fridge.prototype.putIn = function(ele) {
        // 把什么东西放进去
        
        // -----
        // this.openFridge()      // 打开冰箱
        // this.closeFridge()      // 把冰箱门关上
    }
    
    // 调用冰箱原型上的方法
    
    //打开冰箱
    let fridge = new Fridge();
    fridge.openFridge();
    
    //把大象装进去
    let elephant = new Elephant();
    fridge.putIn(elephant)
    
    //把冰箱门关上
    fridge.closeFridge()
    //putIn方法里面的参数可以随意组合,往冰箱里放什么东西都可以,这体现了面向对象写法的好处
    

    面向对象的写法更适合多人开发的大型项目,模块化开发,

    类:构造函数的语法糖

    传统构造函数的问题
    1. 属性和原型方法定义分离,降低了可读性
    2. 原型成员可以被枚举
    3. 默认情况下,构造函数仍然可以被当作普通函数使用
    // 传统写法
    function Animal (type, name, age, sex) {
        this.type = type;
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    // 给构造函数Animal增加打印方法
    Animal.prototype.print = function () {
        console.log(`【种类】:${this.type}`)
        console.log(`【名字】:${this.name}`)
        console.log(`【年龄】:${this.age}`)
        console.log(`【性别】:${this.sex}`)
    }
    
    let dog = new Animal("狗", "柴", "3岁", "公")
    
    dog.print()  // 调用原型上的方法
    
    类的特点
    1. 类声明不会被提升,与letconst一样,存在暂时性死区
    2. 类中的所有代码均在严格模式下执行
    3. 类的所有方法都是不可枚举的
    4. 类的所有方法内部都无法被当作构造函数使用
    5. 类的构造器必须使用new使用
    // ES6类的写法
    class Animal {
        constructor(type, name, age, sex) {
            this.type = type;
            this.name = name;
            this.age = age;
            this.sex = sex;
        }
    
        print() {
            console.log(`【种类】:${this.type}`)
            console.log(`【名字】:${this.name}`)
            console.log(`【年龄】:${this.age}`)
            console.log(`【性别】:${this.sex}`)
        }
    }
    
    let dog = new Animal("狗", "柴", "3岁", "公")
    
    dog.print()
    

    类的其他书写方式

    1. 可计算的成员名
    const newProp = "newProp"
    
    class Animal {
        constructor(type, name, age, sex) {
            this.type = type;
            this.name = name;
            this.age = age;
            this.sex = sex;
        }
    
        [newProp]() { // 声明
            console.log(`【种类】:${this.type}`)
            console.log(`【名字】:${this.name}`)
            console.log(`【年龄】:${this.age}`)
            console.log(`【性别】:${this.sex}`)
        }
    }
    
    let dog = new Animal("狗", "柴", "3岁", "公")
    
    dog[newProp]()   // 调用
    
    2. getter和setter

    使用gettersetter定义的属性不在原型上

    const newProp = "newProp"
    
    class Animal {
        constructor(type, name, age, sex) {
            this.type = type;
            this.name = name;
            this.age = age;
            this.sex = sex;
        }
    
        get age() {  // 获取属性 get
            return this._age
        }
    
        set age(age) {  // 设置属性 set
            if(age < 0) {
                age = "0"
            } else if(age > 1000) {
                age = "1000"
            }
            this._age = age
        }
    
        [newProp]() {
            console.log(`【种类】:${this.type}`)
            console.log(`【名字】:${this.name}`)
            console.log(`【年龄】:${this.age}`)
            console.log(`【性别】:${this.sex}`)
        }
    }
    
    let dog = new Animal("狗", "柴", "10岁", "公")
    
    dog[newProp]()
    
    3. 静态成员

    构造函数本身的成员
    使用static关键字定义成员,即静态成员

    class box {
        constructor (name) {
            this.name = name;
        }
    
        static width = 100;
    
        static height = 100;
    
        static fn() {
            console.log("这是方法")
        }
    }
    
    console.log(box.width)  // 100
    console.log(box.height)  // 100
    
    box.fn()  // 调用静态方法
    
    4. 字段初始化器 [ES7]

    注意:
    1)使用static的字段初始化器,添加的是静态成员
    2)没有使用static的字段初始化器,添加的成员位于对象上
    3)箭头函数在字段初始化器位置上,指向当前对象

    class Test {
        static a = 1
        b = 2
        c = 3
        constructor (){
            // b = 2,  c = 3 相当于
            // this.b = 2
            // this.c = 3
            this.d = this.c + this.b       // 5
        }
    }
    
    const t = new Test()
    
    console.log(t)   //Test {b: 2, c: 3}
    
    5. 类表达式

    用法和之前的相同

    // 匿名类,类表达式
    const A = class {  
        b = 2
        c = 3
    }
    
    const a = new A()
    console.log(a)
    
    6. 装饰器 [ES7]

    类的继承

    新的关键字:

    • extends:继承,用于类的定义
    • super
      • 直接当做函数调用,表示父类构造函数

        ES6要求,如果定义constructor,并且该类是子类,则必须在constructor的第一行手动调用父类的构造函数

        如果子类不写constructor,则会有默认的构造器,该构造器需要的参数和父类一致,并且自动调用父类构造器

      • 如果当作对象使用,则表示父类的原型

    【冷知识】

    • 用JS制作抽象类
      • 抽象类:一般是父类,不能通过该类创建对象
    • 正常情况下this的指向始终指向具体的类的对象
    // ES6类的写法
    // 父类
    class Animal {
        constructor(type, name, age, sex) {
            if (new.target === Animal) {
                throw new TypeError("不能直接创建Animal对象,应该通过子类创建")
            }
            this.type = type;
            this.name = name;
            this.age = age;
            this.sex = sex;
        }
    
        print () {
            console.log(`【种类】:${this.type}`)
            console.log(`【名字】:${this.name}`)
            console.log(`【年龄】:${this.age}`)
            console.log(`【性别】:${this.sex}`)
        }
    }
    
    // 子类
    class Dog extends Animal {
        constructor(name, age, sex) {
            super("犬类", name, age, sex)
            this.hobby = "吃骨头"    // 子类特有属性
        }
    
        print () {
            super.print()    // 调用父类上的方法
            console.log(`【爱好】:${this.hobby}`)  // 给父类增加一个子类特有方法
        }
    }
    
    // let dog = new Animal("柴", "3岁", "公")  // 抛出错误,throw new TypeError("不能直接创建Animal对象,应该通过子类创建")
    let dog = new Dog("柴", "3岁", "公")
    
    dog.print()  // 如果子类有这个方法就执行子类的方法,如果子类没有就执行父类的方法。
    

    相关文章

      网友评论

          本文标题:[ES6] 对象

          本文链接:https://www.haomeiwen.com/subject/qckwbctx.html