preface

This is the fourth article in the ES6 series, and you can view all the previous articles here

This article mainly recorded some class related content, are our daily development may encounter knowledge points

If there are flaws and mistakes in the article, please also see the small partners to give advice, thank you in advance

The following left

The origin of

Prior to ES6, the way we generated instance objects was through constructors

function Person(name{

    this.name = name

}

Person.prototype.say = function({

    console.log(this.name)

}



var p = new Person('Wandering de Tadpole')

Copy the code

ES6 introduces the concept of classes, defined by the class keyword. The above code can be rewritten in this way

class Person {

    constructor(name) {

        this.name = name

    }

    say() {

        console.log(this.name)

    }

}



let p = new Person('Wandering de Tadpole')

Copy the code

This way of writing class is closer to traditional languages, and it is more clear and convenient to set storage and value functions for a property, or to implement inheritance

Nature and Characteristics

nature

The essence of a class is a function. The class itself refers to the constructor

class Person {}



typeof Person // function



Person.prototype.constructor == Person // true

Copy the code

ES6’s class can be seen as just a syntactic sugar. ES5 can do most of the things it does, but the new class writing just makes the object prototype clearer and more like the syntax of object-oriented programming

The constructor of a class corresponds to its constructor, and the methods defined in the class are defined on the prototype property of the class

class Person {

    constructor() {},

    say() {},

    run() {}

.

}

/ / is equivalent to

Person.prototype = {

    constructor() {},

    say(){},

    run(){}

.

}



let p = new Person()



p.say == Person.prototype.say // true

Copy the code

The characteristics of

  • Internal default strict mode
  • There is no variable promotion
console.log(Person)

class Person {}

// Uncaught ReferenceError:

// Cannot access 'Person' before initialization

Copy the code
  • You can’t repeat the definition
let Person = {}

class Person {}

// Uncaught SyntaxError:

// Identifier 'Person' has already been declared

Copy the code
  • constructorIs the default method of the class, even if it is not defined, it will add an empty method by defaultconstructor
  • The instance must be usednewKeyword initialization, otherwise an error will be reported
  • All instances of a class share the same prototype object
class Person {}

let p1 = new Person()

let p2 = new Person()



p1.__proto__ == p2.__proto__ //true

Copy the code
  • All methods defined internally are non-enumerable andprototypeDefault cannot be overridden
class Person {}



Object.getOwnPropertyDescriptor(Person, 'prototype')

/ *

    configurable: false

    enumerable: false

Value: {constructor: ƒ}

    writable: false

* /


Copy the code

A static method

class Person {

    static say() {

        console.log('Hello')

    }

}

Copy the code

Class if a method is preceded by the static keyword, the method is static. It cannot be inherited by an instance and can only be called by a class

let p = new Person()

p.say() // Uncaught TypeError: p.say is not a function



Person.say() // Hello

Copy the code

It is important to note that static methods of a parent class can be inherited by a child class

class Tadpole extends Person {}



Tadpole.say() // Hello

Copy the code

Static attributes

Static properties are properties of the class itself, that is, properties cannot be defined by adding them to this

// Attributes cannot be defined above this; they are inherited by the instance

class Person {

    constructor(name) {

        this.name = name

    }

}

Copy the code

ES6 explicitly states that classes have only static methods and no static attributes

In general, we implement static properties by adding them directly to the class:

Person.age = 18

Copy the code

May also be implemented in a flexible manner:

// Use the static method with the get method

class Person {

    static get age() {

        return 18

    }

}

Copy the code

Static properties of a class behave much the same as static methods: they cannot be inherited by an instance and can only be used by the class

The proposal provides an alternative way of classifying static properties, also using the static keyword

class Person {

    static name = 18

}

Copy the code

Private property

The so-called private, generally need to have the following characteristics:

  • Only in theclassInternal access, not external
  • Cannot be inherited by subclasses

ES6 does not provide an implementation of class private properties and methods, but we can agree in several ways

  • Add identity above naming: Add before method name_, but this approach is not very safe, because the method is still accessible from outside the class
class Person {

    // Public method

    fn(age) {

        this.age = age

    }

    // Private method

    _foo(age){

        return this.age = age

    }

}

Copy the code
  • Move private methods out of the module and usethisCreate a relatively closed space
class Person{

    foo(age) {

        bar.call(this, age)

    }

}

function bar(age{

    return this.age = age

}

Copy the code

The proposal provides one way to implement class private properties: using the # keyword

class Person {

    #age = 18

}

Copy the code

We get an error if we use this property externally

let p = new Person()

Person.#age

p.#age

// Uncaught SyntaxError:

// Private field '#age' must be declared in an enclosing class

Copy the code

In addition, private properties also support getter and setter methods as well as static methods

class Person {

    #age = 18

    get #x() {

        return #age

    }

    set #x(value) {

        this.#age = value

    }

    static #say() {

        console.log(#age)

    }

}

Copy the code

inheritance

Before classes, we used to use prototypes and constructors to implement inheritance. More ways to implement inheritance refer to inheritance in JavaScript

Class inheritance is also implemented through archetypes

The essence of ES5 inheritance is to create a subclass instance object called this, and then add methods from the parent class to this

ES6 inherits by adding the properties and methods of the superclass instance object to this (so the super method must be called first), and then modifying this using the constructor of the subclass

The extends keyword

Classes are inherited through the extends keyword

With the extends keyword, a child class inherits all properties and methods from its parent class

class Person {}



class Tadpole extends Person {}

Copy the code

The extends keyword can be followed not only by a class but also by an expression

function Person(){

    return class {

        say(){

            alert('Hello')

        }

    }

}



class Tadpole extends Person(a){}



new Tadpole().say() // Hello

Copy the code

The extends keyword can also be followed by any function that has the Prototype property (this feature makes it easy to copy a native constructor, such as Object).

function Fn({

    this.name = 'tadpole'

}

// Note that constructor's orientation has changed

Fn.prototype = {

    say() {

        console.log('My name is tadpole')

    }

}



class Tadpole extends Fn {}



let t = new Tadpole()



t.name // tadpole

t.say() // My name is tadpole

Copy the code

The super keyword

A subclass inherits all the properties and methods of its parent class, so the following method will get the correct result

class Person {

    constructor() {

        this.name = 'Wandering de Tadpole'

    }

}

class Tadpole extends Person{}



let t = new Tadpole()

t.name // Wandering tadpoles

Copy the code

However, if we define the constructor property in a subclass, the result is an error

class Tadpole extends Person {

    constructor() {}

}



let t = new Tadpole()

// Must call super constructor in derived class before accessing 'this' or returning from derived constructor

Copy the code

If we want to define the constructor property in a subclass, we must call the super method

/ / normal

class Tadpole extends Person {

    constructor() {

        super(a)

    }

}



let t = new Tadpole()

Copy the code

Super represents the parent class constructor, and returns the instance of the subclass, equivalent to a Person. The prototype. Call (this) constructor.

So what super() does in the above code is actually add this to the current class and return it

There are two ways to use super:

As a function

Super () can only be used in the constructor of a subclass. If used elsewhere, an error will be reported

As an object
  • In a normal method, a prototype object that points to a superclass (superA prototyped object that points to a superclass, so methods or properties defined on an instance of the superclass cannot passsuperCall)
class Person {

    constructor() {

        this.name = 'Wandering de Tadpole'

    }

    say() {

        console.log('My name is' + this.name)

    }

}



class Tadpole extends Person {

    constructor() {

        super(a)

        console.log(super.say()) // My name is wandering de tadpole

        console.log(super.name) // undefined

    }

}

Copy the code
  • In static methods, point to the superclass
class Person {

    constructor() {

        this.name = 'Wandering de Tadpole'

    }

    say() {

        console.log('My name is' + this.name)

    }

    static say() {

        console.log('My name in tadpole')

    }

}



class Tadpole extends Person {

    static say() {

        super.say()

    }

    say() {

        super.say()

    }

}



Person.say() // My name is tadpole

Tadpole.say() // My name is tadpole

let t = new Tadpole()

t.say() // My name is wandering de tadpole

Copy the code

The class of this

  • If the method inside the class containsthisBy default, points to an instance of the class
class Person {

    say() {

        this.run()

    }

    run() {

        console.log('Run! ')

    }

}

Copy the code
  • If the static method containsthisKeyword, thisthisRefers to classes, not instances
class Person {

    static say() {

        console.log(this// Person

    }

}

Copy the code
  • A subclass inherits from its parent classconstructorIn the callsuper()Then you can use itthis
  • classBy default, strict mode is used in thethisPoint to theundefined(Defaults to global objects)

The problem of a class

The emergence of class provides a lot of programming convenience, but the class itself has some problems

  • First of all, there is no increase in the cost of learning. You said I didn’t know the prototype, the prototype chain, and you asked me to learnclassIt was justSyntactic sugar“, you said not angry people
  • Secondly, based onprototype, soclassThere are some problems with stereotypes, such as changing a property on a parent class that affects all subclasses (of course, the presence of private properties solves some problems).
  • Not all environments support thisclass“, like the blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, blah, blah.babel

Class is still a bit of a problem, but it’s definitely getting richer…

Afterword.

That’s all about class. I hope it helps you see it

Go ahead and use class in your projects, and you’ll love it

If you are interested, you can click here or scan the qr code below to follow my wechat official account for more information. Welcome to star

image

reference

ECMAScript introduction to 6

MDN