前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript中的类(ES5+ES6)

JavaScript中的类(ES5+ES6)

作者头像
刘亦枫
发布2020-03-19 17:36:32
9510
发布2020-03-19 17:36:32
举报
文章被收录于专栏:亦枫的大佬之路

ES5

ECMAScript 2015 中引入的 JavaScript 类实质上是 JavaScript 现有的基于原型的继承的语法糖。类语法不会为JavaScript引入新的面向对象的继承模型。

类实际上是个“特殊的函数”,就像你能够定义的函数表达式和函数声明一样,类语法有两个组成部分:类表达式和类声明。

类声明

定义一个类的一种方法是使用一个类声明。要声明一个类,你可以使用带有class关键字的类名(这里是“Rectangle”)。

代码语言:javascript
复制
class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

函数声明和类声明之间的一个重要区别是函数声明会提升,类声明不会。

类表达式

一个类表达式是定义一个类的另一种方式。类表达式可以是被命名的或匿名的。赋予一个命名类表达式的名称是类的主体的本地名称。

代码语言:javascript
复制
/* 匿名类 */ 
let Rectangle = class {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};

/* 命名的类 */ 
let Rectangle = class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};

类表达式也同样受到类声明中提到的提升问题的限制。

ES6

在ES6中,class (类)作为对象的模板被引入,可以通过 class 关键字定义类。它可以被看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法。

ES5与ES6对比

在ES5中定义一个类:

代码语言:javascript
复制
function Person(name) {
 
    this.name = name;
}
 
Person.prototype.sayHello = function(){
 
    return 'Hi, I am ' + this.name;
}

而用ES6的写法重写一下,检测类型发现Person本质上仍然是函数:

代码语言:javascript
复制
class Person {
 
    constructor(name){
        this.name = name;
    }
 
    sayHello(){
        return 'Hi, I am ' + this.name;
    }
}
 
typeof Person; //'function'

调用的方式都是一致的:

代码语言:javascript
复制
var p1 = new Person('zhangsan');   

用ES6定义class中的方法,定义在原型对象上的。与ES5不同的是,这些定义在原型对象的方法是不可枚举的。

ES6类和模块是严格模式下的;不存在变量提升,保证子类父类的顺序;类的继承也有新的写法:

代码语言:javascript
复制
class Female extends Person {
 
    constructor(name){
        super(name); //调用父类的,调用之后,子类才有this
        this.sex = 'boy';
    }
 
    sayHello(){
        return super.sayHello() + ', I am ' + this.sex;
    }
 
}

注意,子类必须在父类的构造函数中调用super(),这样才有this对象,因为this对象是从父类继承下来的。而要在子类中调用父类的方法,用super关键词可指代父类。

ES5中类继承的关系是相反的,先有子类的this,然后用父类的方法应用在this上。

ES6类继承子类的this是从父类继承下来的这个特性,使得在ES6中可以构造原生数据结构的子类,这是ES5无法做到的。

ES6也可以定义类的静态方法和静态属性,静态的意思是这些不会被实例继承,不需要实例化类,就可以直接拿来用。ES6中class内部只能定义方法,不能定义属性。在方法名前加上static就表示这个方式是静态方法,而属性还是按照ES5的方式来实现。

代码语言:javascript
复制
function Person(name){
 
    if(new.target === Person){
        this.name = name;
    }
    else{
        throw new Error('必须用new生成实例');
    }
}

ES6中当函数用new关键词的时候,增加了new.target属性来判断当前调用的构造函数。这个有什么用处呢?可以限制函数的调用,比如一定要用new命令来调用,或者不能直接被实例化需要调用它的子类。

代码语言:javascript
复制
function Person(name){
 
    if(new.target === Person){
        this.name = name;
    }
    else{
        throw new Error('必须用new生成实例');
    }
}

ES5类中的 实例方法&原型方法&静态方法

1.实例方法只有实例可以调用

2.实例方法可以调用静态方法,不能调用原型方法

3.原型方法可以被实例和构造函数访问到

4.原型方法只可以调用静态方法

5.静态方法只有构造函数可以调用

ES5中定义三种方法及调用关系:

代码语言:javascript
复制
let Animal = function (type) {
  this.type = type
  // 实例方法
  this.drink = function () {
    // 实例方法可调用类的静态方法
    Animal.walk()
    console.log('drink')
  }
}

// 原型方法
Animal.prototype.eat = function () {
  // 原型方法可调用类的静态方法
  Animal.walk()
  console.log('eat food')
}

// 静态方法
Animal.walk = function () {
  console.log('walking')
}

let dog = new Animal('dog')
dog.drink() // walking drink
dog.eat() // walking eat food
Animal.walk() // walking静态方法只能由<类自身&实例方法&原型方法>调用,实例对象无法调用
// dog.walk() // dog.walk is not a function  实例对象无法调用静态方法

ES6类中的 实例方法&原型方法&静态方法

1.实例方法=原型方法 类中直接定义的实例方法默认就是ES5中的原型方法(语法糖)

2.静态方法用static前缀定义

3.静态方法只有构造函数可以调用,原型方法是实例和构造函数都可以调用,是共享的方法。

ES6中定义三种方法及调用关系:

代码语言:javascript
复制
class Animal {
  constructor (type) {
    this.type = type
  }
  // 定义实例对象的方法
  eat () {
    // 使用静态方法,以类形式访问,而非this访问
    Animal.walk()
    console.log('eat food')
    console.log(this.type) // 类的例实例对象的方法可以获取到实例对象的信息,输出dog
  }
  // static 定义类的静态方法
  static walk () {
    console.log('walking')
    console.log(this.type) // 类的静态方法无法获取到实例对象的信息,输出undefined
  }
}
let dog = new Animal('dog')
dog.eat() // walking ; undefined ; eat food ; dog
Animal.walk() // walking ; undefined ;
dog.walk() // dog.walk is not a function
// 得出结论:需要访问实例对象的信息时用实例对象的方法,否则使用static静态方法
// 实例方法就是只有实例可以调用,静态方法只有构造函数可以调用,原型方法是实例和构造函数都可以调用,是共享的方法。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ES5
  • ES6
  • ES5与ES6对比
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档