当前位置: 移动技术网 > IT编程>软件设计>面向对象 > ES6——对象

ES6——对象

2020年08月10日  | 移动技术网IT编程  | 我要评论
对象一、新增语法1.成员速写2.方法速写3.计算属性名二、对象新增API1.Object.is2.Object.assign3.Object.getOwnPropertyNames4.Object.setPrototypeOf三、面向对象简介1.面向过程2.面向对象四、构造函数1.传统的构造函数的问题2.类1.基础2.类的可计算的成员名3.getter和setter4.静态成员5.字段初始化器(ES7)6.类表达式3、类的继承1.基础2.新方法3.逻辑方面一、新增语法1.成员速写如果对象字面量初始化时

一、新增语法

1.成员速写

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

function createObj(name,password){
    const say = function(){
        console.log(name,password);
    };
    return {
        name,
        password,
        say
    }
}
const obj = createObj('jimo',123456);
obj.say();

在这里插入图片描述

2.方法速写

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

const user = {
    name: "jimo",
    age: 18,
    sayHello(){
        console.log(this.name, this.age)
    }
};
user.sayHello();

3.计算属性名

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

const prop1 = "name2";//后期如有需要可以利用方法等动态修改
const prop2 = "age2";
const prop3 = "sayHello2";
const user = {
    [prop1]: "jimo",
    [prop2]: 18,
    [prop3](){
        console.log(this[prop1], this[prop2])
    }
};
user[prop3]();

二、对象新增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));
console.log(Object.is(+0, -0));

在这里插入图片描述

2.Object.assign

用于混合对象

const obj1 = {
    a: 123,
    b: 456,
    c: "abc"
};
const obj2 = {
    a: 789,
    d: "kkk"
};
const obj = Object.assign(obj1, obj2);
console.log(obj);
console.log(obj===obj1);//会修改obj1返回

在这里插入图片描述

3.Object.getOwnPropertyNames

枚举顺序,Object.getOwnPropertyNames方法之前就存在,只不过,官方没有明确要求,对属性的顺序如何排序,如何排序,完全由浏览器厂商决定。

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

  1. 先排数字,并按照升序排序
  2. 再排其他,按照书写顺序排序
const obj = {
    d: 1,
    b: 2,
    a: 3,
    0: 6,
    5: 2,
    4: 1
};
const props = Object.getOwnPropertyNames(obj);
console.log(props);

在这里插入图片描述

4.Object.setPrototypeOf

该函数用于设置某个对象的隐式原型

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

三、面向对象简介

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

1.面向过程

大象装进冰箱

//1. 冰箱门打开
function openFrige(){
}
openFrige();
//2. 大象装进去
function elephantIn(){
}
elephantIn();
//3. 冰箱门关上
function closeFrige(){
}
closeFrige();

2.面向对象

//大象
function Elephant() {
}
//冰箱
function Frige() {
}

Frige.prototype.openDoor = function () {
}

Frige.prototype.closeDoor = function () {
}
Frige.prototype.join = function(something){
    this.openDoor();
    //装东西
    this.closeDoor();
}
/*1. 冰箱门打开
var frig = new Frige();
frig.openDoor();*/

/*2. 大象装进去
var ele = new Elephant();
frig.join(ele);*/

/*3. 冰箱门关上
frig.closeDoor();*/

var frig = new Frige();
frig.join(new Elephant());

四、构造函数

1.传统的构造函数的问题

  1. 属性和原型方法定义分离,降低了可读性
  2. 原型成员可以被枚举
  3. 默认情况下,构造函数仍然可以被当作普通函数使用
//构造函数  构造器
function Animal(type, name, age, sex) {
    this.type = type;
    this.name = name;
    this.age = age;
    this.sex = sex;
}
//定义实例方法(原型方法)
Animal.prototype.print = function () {
    console.log(`【种类】:${this.type}`);
    console.log(`【名字】:${this.name}`);
    console.log(`【年龄】:${this.age}`);
    console.log(`【性别】:${this.sex}`);
}
const a = new Animal("猫", "Kity", 3, "男");
a.print();

for (const prop in a) {
    console.log(prop)
}

在这里插入图片描述

2.类

1.基础

  1. 类声明不会被提升,与 let 和 const 一样,存在暂时性死区(即未声明不使用)
  2. 类中的所有代码均在严格模式下执行
  3. 类的所有方法都是不可枚举的
  4. 类的所有方法都无法被当作构造函数使用
  5. 类的构造器必须使用 new 来调用
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}`);
    }
}

const a = new Animal("狗", "旺财", 3, "男");
a.print();

for (const prop in a) {
    console.log(prop)
}

在这里插入图片描述

2.类的可计算的成员名

const printName = "print";
class Animal {
    constructor(type, name) {
        this.type = type;
        this.name = name;
    }
    [printName]() {
        console.log(`【种类】:${this.type}`);
        console.log(`【名字】:${this.name}`);
    }
}
const animal = new Animal("狗", "旺财");
animal[printName]();

在这里插入图片描述

3.getter和setter

const printName = "print";
class Animal {
    constructor(name, age) {
        this.name = name;
        this.age = age;//会直接执行下列函数
    };
    //创建一个age属性,并给它加上getter,读取该属性时,会运行该函数
    get age() {
        return this._age + "岁";
    }
    //创建一个age属性,并给它加上setter,给该属性赋值时,会运行该函数
    set age(age) {
        if (typeof age !== "number") {
            throw new TypeError("age property must be a number");
        }
        if (age < 0) {
            age = 0;
        }
        else if (age > 1000) {
            age = 1000;
        }
        this._age = age;
    }
    [printName]() {
        console.log(`【名字】:${this.name}`);
        console.log(`【年龄】:${this.age}`);
    }
}
var a = new Animal("Kity", 3);
console.log(a);

在这里插入图片描述

4.静态成员

构造函数本身的成员,使用static关键字定义的成员即静态成员,实例对象无法访问构造函数的静态成员

class Chess {
    constructor(name) {
        this.name = name;
    }
    static width = 50;
    static height = 50;
    static method() {
        console.log(this.name);
    };
    printf(){
        console.log(this.name);
    }
};
console.log(Chess.width,Chess.height)
var horse = new Chess('horse');
//horse.method();//报错
horse.printf();
console.log(horse,horse.width,horse.width);

在这里插入图片描述
在这里插入图片描述

5.字段初始化器(ES7)

适用一开始固定的值

  1. 使用static的字段初始化器,添加的是静态成员
  2. 没有使用static的字段初始化器,添加的成员位于对象上
  3. 箭头函数在字段初始化器位置上,指向当前对象
class Test {
    static a = 1;
    b = 2;
    c = 3;
    constructor() {
        this.d = this.b + this.c;
    }
}
const t = new Test();
console.log(t);

箭头函数注意点
正常情况,将实例的方法赋予其它变量并执行时,可能会因为this指向出问题

class Test {
    constructor() {
        this.a = 123;
    }
    print = function(){
        console.log(this.a)
    }
};
const t1 = new Test();
const t2 = t1.print;
t1.print();//this指向变成window了
t2();

在这里插入图片描述
利用箭头函数可以解决该问题,但是构造函数的方法将不会被实例获取,而不再是原型。

class Test {
    constructor() {
        this.a = 123;
    }
    print = () => {
        console.log(this.a)
    }
};
const t1 = new Test();
const t2 = new Test();
const t3 = t1.print;
t1.print();
t3();
console.log(t1);
console.log(t1.print === t2.print);

在这里插入图片描述

6.类表达式

const A = class { //匿名类,类表达式
    a = 1;
    b = 2;
};
const a = new A();
console.log(a);

在这里插入图片描述

3、类的继承

1.基础

如果两个类A和B,如果可以描述为:B 是 A,则,A和B形成继承关系

function Animal(type, name, age, sex) {
    this.type = type;
    this.name = name;
    this.age = age;
    this.sex = sex;
}
Animal.prototype.print = function () {
    console.log(`【种类】:${this.type}`);
    console.log(`【名字】:${this.name}`);
    console.log(`【年龄】:${this.age}`);
    console.log(`【性别】:${this.sex}`);
}
function Dog(name, age, sex) {
    //借用父类的构造函数
    Animal.call(this, "犬类", name, age, sex);
}
const d = new Dog("旺财", 3, "公");
console.log(d);
d.print();//d不是继承自Animal,没有printf方法

在这里插入图片描述

在这里插入图片描述

Object.setPrototypeOf(Dog.prototype, Animal.prototype);//将Animal原型给Dog
const d = new Dog("旺财", 3, "公");
console.log(d);
d.print();

在这里插入图片描述

在这里插入图片描述
虽然比圣杯模式简单一些,但是代码阅读性不高

2.新方法

新的关键字:

  1. extends:继承,用于类的定义
  2. super
    1. 直接当作函数调用,表示父类构造函数
    2. 如果当作对象使用,则表示父类的原型
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}`);
    }
}
class Dog extends Animal {
    constructor(name, age, sex) {
        // super("犬类", name, age, sex);
    }
}
const d = new Dog("旺财", 3, "公");
d.print();

在这里插入图片描述
注意:ES6要求,如果定义了constructor,并且该类是子类,则必须在constructor的第一行手动调用父类的构造函数

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}`);
    }
}
class Dog extends Animal {
    constructor(name, age, sex) {
        super("犬类", name, age, sex);
    }
}
const d = new Dog("旺财", 3, "公");
d.print();

在这里插入图片描述
如果子类不写constructor,则会有默认的构造器,该构造器需要的参数和父类一致,并且自动调用父类构造器

class Dog extends Animal {

}
const d = new Dog("旺财", 3, "公");
d.print();

在这里插入图片描述

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}`);
    }
    jiao(){
        throw new Error("动物怎么叫的?");
    }
}

class Dog extends Animal {
    constructor(name, age, sex) {
        super("犬类", name, age, sex);
        // 子类特有的属性
        this.loves = "吃骨头";
    }
    print(){
        //调用父类的print
        super.print();//同类方法直接调用父级
        //特殊的就自己特有的代码
        console.log(`【爱好】:${this.loves}`);
    }
    //同名方法,会覆盖父类
    jiao(){
        console.log("旺旺!");
    }
}
const d = new Dog("旺财", 3, "公");
d.print();
console.log(d)
d.jiao();

3.逻辑方面

对于下面代码,逻辑上Animal是规定动物的类型等的构造函数,Dog才是创建狗类的构造函数,我们一般通过Dog生成实例狗而不是Animal

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.loves = "吃骨头";
    }
    print() {
        //调用父类的print
        super.print();
        //自己特有的代码
        console.log(`【爱好】:${this.loves}`);
    }
}
const a = new Dog("旺财", 3, "公")
a.print();//不管console是运行的祖先的printf还是父级的
//正常情况下,this的指向,this始终指向具体的类的对象

本文地址:https://blog.csdn.net/xun__xing/article/details/107877010

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网