ES5 与 ES6 中类的区别

ES5 与 ES6 中类的区别

类定义与调用的区别

在 ES5 中主要是通过构造函数方式和原型方式来定义一个类,但是在 ES6 新引入了 class 关键字,使之具有了正式类的能力,类(class)是ECMAScript 中新的基础性语法糖结构。虽然 ES6 类表面上看起来可以支持正式的面向对象编程,但实际上它背后使用的仍然是原型和构造函数的概念。

  • 使用 ES5 定义一个类并调用
function Person(name, age, job) {
   
   
    this.name = "Totora";
    this.age = 19;
    this.job =  "student";
    this.sayName = function() {
   
   
        console.log(this.name);
    };
}
let person = new Person();
person.sayName();
  • 使用 ES6 定义一个类并调用

    • ES6中有两种定义类的方式:类声明和类表达式

      class Person {}const Person = class {};

class Person {
   
   
    constructor() {
   
   
        this.name = "Totora";
        this.age = 19;
        this.job = "student";
    }
    sayName() {
   
   
        console.log(this.name);
    }
}
let person = new Person();
person.sayName();
//当我们使用typeof检测Person的类型时:
console.log(typeof Person); //function,它的本质仍然是函数

在调用类时,不管是ES5还是ES6,都必须使用new操作符来进行调用,不可以直接执行。

两者区别在于:

  • ES5这样调用不会报错,可以正常执行(因为ES5中的类和普通函数几乎没有本质上的区别)
function Person(name, age, job) {
   
   
    this.name = "Totora";
    this.age = 19;
    this.job =  "student";
    this.sayName = function() {
   
   
        console.log(this.name);
    };
}
let person = Person();
console.log(person); //undefined
  • ES6会报错
class Person {
   
   
    constructor() {
   
   
        this.name = "Totora";
        this.age = 19;
        this.job = "student";
    }
    sayName() {
   
   
        console.log(this.name);
    }
}
let person =Person();
console.log(person);
person.sayName(); //Class constructor Person cannot be invoked without 'new'

变量提升

  • 通过以下对比可以发现,当用class声明类执行时会报错,说明ES6中用class定义的类无法实现变量提升。

  • 函数受函数作用域的限制,但是类受块作用域的限制

//变量提升
let person = new Person()
function Person(name, age, job) {
   
   
    this.name = "Totora";
    this.age = 19;
    this.job =  "student";
    this.sayName = function() {
   
   
        console.log(this.name);
    };
}
person.sayName(); //Totora
let person = new Person();
class Person {
   
   
    constructor() {
   
   
        this.name = "Totora";
        this.age = 19;
        this.job = "student";
    }
    sayName() {
   
   
        console.log(this.name);
    }
}
person.sayName(); // Cannot access 'Person' before initialization

class中类的构成

类可以包含构造函数方法、实例方法、获取函数、设置函数、静态类的方法。但是空的类定义照样有效

//空类定义
class Foo {
   
   }
//有构造函数的类
class Bar {
   
   
    constructor() {
   
   }
}
//有获取函数的类
class Baz {
   
   
    get myBaz() {
   
   }
}
//有静态方法的类
class Qux {
   
   
    static myQux() {
   
   }
}

class中的静态方法

  • 可以在类上定义静态方法。静态类成员在类定义中使用static关键字作为前缀,在静态成员中,this引用类自身;
  • 与原型成员类似,静态成员每个类上只能有一个;
  • static声明的静态属性和方法都可以被子类继承。
class Person {
   
   
    constructor() {
   
   
        //添加到this的所有内容都会存在于不同的实例上
        this.locate = () => console.log('instance', this);
    }
    //定义在类的原型对象上
    locate() {
   
   
        console.log('prototype', this);
    }
    //定义在类本身上
    static locate() {
   
   
        console.log('class', this);
    }
}
let p = new Person();
p.locate(); //instance Person { locate: [Function (anonymous)] }
Person.prototype.locate(); //prototype {}
Person.locate(); //class [class Person]
class Person {
   
   
    static name() {
   
   
        this.job(); //此处的this指向类
    }
    static job() {
   
   
        console.log('Totora'); //不会出现在实例中
    }
    job() {
   
   
        console.log('student');
    }
}
Person.name(); //Totora

继承

  • ES5中的继承实质上是先创建子类的实例对象,再将父类的方法添加到this上(Parent.apply(this)),通过原型或构造函数机制来实现
  • ES6的继承实际上是先创建父类的实例对象this,然后再用子类的构造函数修改this。
  • ES6中类之间通过extends关键字,就可以继承任何拥有[[Construct]]和原型的对象,在很大程度上,这不仅i仅可以继承一个类,也可以继承普通的构造函数(保持向后兼容)
  • ES6中派生类的方法可以通过super关键字引用它们的原型,这个关键字只能在派生类中使用,而且仅限于类的构造函数、实例方法和静态方法的内部。在类构造函数中使用super可以调用父类构造函数。
//ES5中的继承
function parent(a,b) {
   
   
    this.a = a;
    this.b = b;
}
function child(c) {
   
   
    this.c = c;
}
parent.call(child, 1, 2); //子级来继承父级
child.prototype = new parent(1, 2);
//ES6中的继承
class parent {
   
   
    constructor(a, b) {
   
   
        this.a = a;
        this.b = b;
    }
    parentMethods() {
   
   
        return this.a + this.b
    }
}
class child extends parent {
   
   
    constructor(a, b, c) {
   
   
        super(a, b); //通过super调用父类
        this.c = c;
    }
    childMethods() {
   
   
        return this.c + ',' + super.parentMethods() //通过super实例化调用父类
    }
}
const point = new child(1, 2, 3);
console.log(point.childMethods());
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章