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
constructor
Is the default method of the class, even if it is not defined, it will add an empty method by defaultconstructor
- The instance must be used
new
Keyword 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 and
prototype
Default 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 the
class
Internal 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 use
this
Create 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 (
super
A prototyped object that points to a superclass, so methods or properties defined on an instance of the superclass cannot passsuper
Call)
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 contains
this
By default, points to an instance of the class
class Person {
say() {
this.run()
}
run() {
console.log('Run! ')
}
}
Copy the code
- If the static method contains
this
Keyword, thisthis
Refers to classes, not instances
class Person {
static say() {
console.log(this) // Person
}
}
Copy the code
- A subclass inherits from its parent class
constructor
In the callsuper()
Then you can use itthis
class
By default, strict mode is used in thethis
Point 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 learn
class
It was justSyntactic sugar
“, you said not angry people - Secondly, based on
prototype
, soclass
There 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 this
class
“, 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
reference
ECMAScript introduction to 6
MDN