es6中class类、super和estends关键词

更新日期: 2021-08-09阅读: 1.8k标签: super

前言

JavaScript 语言在ES6中引入了 class 这一个关键字,在学习面试的中,经常会遇到面试官问到谈一下你对 ES6 中class的认识,同时我们的代码中如何去使用这个关键字,使用这个关键字需要注意什么,这篇来总结一下相关知识点。


1.es6之前创建对象

先来看下es6之前我们要想创建一个对象,只能通过构造函数的方式来创建,将静态方法添加在原型上面使得每一个实例能够调用该方法。

        function Person(name, age) {
            this.name = name
            this.age = age
            Person.prototype.sayHello = function () {
                return "hello," + this.name + ",早上好"
            }
        }
        let person = new Person("serendipity", 18)
        console.log(person.sayHello())//hello,serendipity,早上好
        console.log(person instanceof Person);//true
        console.log(person instanceof Object);//true


2.es6之后class的声明

类是用于创建对象的模板,他们用代码封装数据以处理该数据。js中的 class 类建立在原型之上,但也具有某些语法和语义与ES5类相似语义共享。

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

        class Person {
            constructor(name, age) {//自有属性,该属性出现在实例上,只能在类的构造器或者方法内部进行创建
                this.name = name
                this.age = age
            }
            sayHello() {//等价于Perosn.prototype.sayHello
                return `hello,${this.name},早上好`
            }
        }
        let person = new Person("serendipity", 18)
        console.log(person.sayHello());//hello,serendipity,早上好
        console.log(person instanceof Person);//true
        console.log(person instanceof Object);//true
        console.log(typeof Person);//function
        console.log(typeof Person.prototype.sayHello);//function

类声明允许在class中使用 constructor 方法定义一个构造器,而不需要定义专门的构造方法来当构造器使用。

class 类的语法与普通es5之前的函数语法相似,但是还存在一些特性需要注意:

(1)类的声明不会被提升,类的声明行为和 let 相似,因此执行时类会存在暂时性死区;

(2)类中所有代码自动运行在严格模式下,且改严格模式无法退出

(3) 类中所有方法都是不可枚举的,普通自定义方法只有通过 object.defineProperty() 才能将方法定义为不可枚举

(4)类中的所有方法内部都没有 [[construct]] ,因此使用new 来调用他们会抛出错误

(5)调用类构造器时不使用 new 会抛出错误

(6)试图在类的方法内部重写类名会抛出错误

将上面的代码转换为ES5之前的写法如下:

        let PersonClass = (function () {
            "use strict"
            const PersonClass = function (name, age) {
                // 判断是否被new调用构造函数
                if (typeof new.target === "undefined") {
                    throw new Error("Constructor must be call with new.")
                }
                this.name = name
                this.age = age
            }
            Object.defineProperty(PersonClass.prototype, "sayHello", {
                value: function () {
                    if (typeof new.target !== "undefined") {//保正调用时没有使用new
                        throw new Error("Method cannot be called with new.")
                    }
                    return "hello," + this.name + ",早上好!"
                },
                enumerable: false,
                configurable: true,
                writable: true
            })
            return PersonClass
        })()
        var personClass = new PersonClass("serendipity", 18)
        console.log(personClass.name);//serendipity
        console.log(personClass.sayHello());///hello,serendipity,早上好!

两个PersonClass 声明,一个在外部作用域的 let 声明,另一个在立即执行函数内部的 const 声明,这就是为何类的方法不能对类名进行重写,而类的外部的代码则被允许。同时,只在类的内部类名才被视为使用了const声明,这意味着你可以在外部(相当于let)重写类名,但是不能在类的方法内部这么写。


3.类的继承

ES6之前的继承方式主要通过构造函数和原型链组合的方式来实现继承,具体代码如下:

        function Rectangle(length, width) {
            this.length = length
            this.width = width
            Rectangle.prototype.getArea = function () {
                return this.length * this.width
            }
        }
        function Square(length) {
            Rectangle.call(this, length, length)
        }
        Square.prototype = Object.create(Rectangle.prototype, {
            constructor: {
                value: Square,
                enumerble: true,
                writeable: true,
                configurable: true
            }
        })
        var square = new Square(3)
        console.log(square.getArea());//9
        console.log(square instanceof Square);//true
        console.log(square instanceof Rectangle);//true

上面的代码通过构造函数和原型上面添加静态方法实现了 Rectangle 父类,然后子类 Square 通过 Rectangle.call(this,length,length) 调用了父类的构造函数,Object.create 会在内部创建一个空对象来连接两个原型对象,再手动将 constructor 指向自身。这种方法实现继承代码繁杂且不利用理解,于是ES6 class 类的创建让继承变得更加简单,使用extends 关键字来指定当前类所需要继承的父类,生成的类的原型会自动调整,还可以使用 super() 方法来访问基类的构造器。具体代码如下:

        class Rectangle {
            constructor(length, width) {
                this.length = length
                this.width = width
            }
            getArea() {
                return this.length * this.width
            }
        }
        class Square extends Rectangle {
            constructor(length) {
                super(length, length)
            }
            getArea() {
                return this.length + this.length
            }

        }
        var square = new Square(3)
        console.log(square.getArea());//6
        console.log(square instanceof Square);//true
        console.log(square instanceof Rectangle);//true

上面的代码中 Square 类重写了基类的 getArea() 方法,当派生的子类中函数名和基类中函数同名的时候,派生类的方法会屏蔽基类的方法,同时也可以再子类中getArea () { return super.getArea() }中调用基类的方法进行扩展。


4.继承类的静态成员

静态成员:直接在构造器上添加的额外的方法。例如ES5中在原型上添加的方法就属于静态成员,ES6 class类引入简化了静态成员的创建,只需要在方法与访问器属性的名称前添加 static关键字即可。例如下面的代码用于区分静态方法和实例方法。

    function PersonType(name) {
        this.name = name;
    }
    // 静态方法
    PersonType.create = function(name) {
        return new PersonType(name);
    };
    // 实例方法
    PersonType.prototype.sayName = function() {
        console.log(this.name);
    };
  var person = PersonType.create("Nicholas");

在ES6中要想使用静态成员如下:

        class Rectangle {
            constructor(length ,width) {
                this.length = length
                this.width = width
            }
            getArea() {
                return this.length * this.width
            }
            static create(length,width) {
                return new Rectangle(length , width)
            }
        }
        class Square extends Rectangle{
            constructor (length){
                super(length,length)
            }
        }
        var square =Square.create(3,4)
        console.log(square.getArea());//12
        console.log(square instanceof Square);//false
        console.log(square instanceof Rectangle);//true

上面的代码中,一个新的静态方法 create() 被添加到 Rectangle 类中,通过继承,以Square.create() 的形式存在,并且其行为方式与Rectangle.create() 一样。需要注意静态成员不懂通过实例来访问,始终需要直接调用类自身来访问他们。


链接: https://fly63.com/article/detial/10616

ES6 类继承 和 super的使用

ES6中继承的子类中,如果使用构造函数constructor()那么就必须使用 super()方法初始化,这样下面才可以调用this关键字。super()只能用在子类的构造函数之中,用在其他地方就会报错。

谈谈super(props) 的重要性

我听说 Hooks 最近很火。讽刺的是,我想用一些关于 class 组件的有趣故事来开始这篇文章。你觉得如何?本文中这些坑对于你正常使用 React 并不是很重要。 但是假如你想更深入的了解它的运作方式,就会发现实际上它们很有趣。

js中的super的使用

super()相当于Parent.prototype.constructor.call(this)ES5的继承,实质上是先创造子类的实例对象this,然后再将父类的方法添加到this上(Parent.call(this)). ES6的继承

ES6 class继承与super关键词深入探索

在ES6版本之前,JavaScript语言并没有传统面向对象语言的class写法,ES6发布之后,Babel迅速跟进,广大开发者也很快喜欢上ES6带来的新的编程体验。当然,在这门“混乱”而又精妙的语言中,许多每天出现我们视野中的东西却常常被我们忽略。

为什么我们要写 super(props) ?

据说 Hooks 势头正盛,不过我还是想略带调侃地从 class 的有趣之处开始这篇博客。可还行?这些梗对于使用 React 输出产品并不重要

jses6语法:class类 class继承 super关键字

Class可以通过extends关键字实现继承,这比ES5通过修改原型链实现继承,super关键字既可以当做函数使用,也可以当做对象使用,当做函数使用的时候,代表的是父类的构造函数

面试官:this和super有什么区别?this能调用到父类吗?

this 和 super 都是 Java 中的关键字,都起指代作用,当显示使用它们时,都需要将它们放在方法的首行(否则编译器会报错)。this 表示当前对象,super 用来指代父类对象

ES6中class方法及super关键字

记录下class中的原型,实例,super之间的关系,构造器中的this指向实例对象,在构造函数上定义的属性和方法相当于定义在类实例上的,而不是原型对象上

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!