class

Class is a syntactic sugar, the underlying layer of which is created through the constructor. So most of its functions, ES5 can do. The new class writing method simply makes the writing of object prototypes clearer and more like the syntax of object-oriented programming.

function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.sayName = function() {
    return this.name;
}

const xiaoming = new Person('Ming'.18);
console.log(xiaoming);
Copy the code

The above code is implemented using ES6 class, which looks like this

class Person {
    constructor(name, age) {
      this.name = name;
      this.age = age;
    }
  
    sayName() {
      return this.name; }}const xiaoming = new Person('Ming'.18)
console.log(xiaoming);
// {name: 'xiao Ming ', age: 18}

console.log((typeof Person));
// function
console.log(Person === Person.prototype.constructor);
// true
Copy the code

The constructor method. This keyword represents the instance object. The data type of a class is a function, and the class itself points to a constructor.

When defining a class, you do not need to add function in front of it, and methods do not need to be separated by commas.

All methods of a class are defined on the prototype property of the class.

class A {
    constructor() {}
    toString() {}
    toValue(){}}/ / is equivalent to
function A () {
    // constructor
};
A.prototype.toString = function() {};
A.prototype.toValue = function() {};
Copy the code

Calling a method on an instance of a class is actually calling a method on the prototype.

let a = new A();
a.constructor === A.prototype.constructor // true
Copy the code

The constructor method

The constructor method is the default method of the class and is automatically called when an object instance is generated using the new command. A class must have a constructor method; if it is not explicitly defined, an empty constructor method is added by default.

class A {}/ / is equivalent to
class A {
  constructor(){}}Copy the code

The constructor method returns the instance object (that is, this) by default; you can specify to return another object at all.

class A {
  constructor() {
      return Object.create(null); }}console.log((new A()) instanceof A);
// false
Copy the code

Instances of the class

The attributes of an instance are defined on the stereotype (class) unless they are explicitly defined on themselves (that is, on this object).

A new way to write instance attributes

Instance attributes can be defined at the top level of the class, in addition to above this in the constructor() method.

class IncreasingCounter {
  constructor() {
    this._count = 0;
  }
  get value() {
    console.log('Getting the current value! ');
    return this._count;
  }
  increment() {
    this._count++; }}Copy the code

In the above code, the instance attribute this._count is defined in the constructor() method. Another way to write this is that this property can also be defined at the top level of the class, all else being the same.

class IncreasingCounter {
  _count = 0;
  get value() {
    console.log('Getting the current value! ');
    return this._count;
  }
  increment() {
    this._count++; }}Copy the code

In the code above, the instance attribute _count is at the same level as the value() and increment() methods. At this point, you do not need to prefix the instance attribute with this.

The nice thing about this new approach is that all the attributes of the instance object itself are defined in the header of the class, so you can see at a glance what instance attributes the class has.

class foo {
  bar = 'hello';
  baz = 'world';
  constructor() {
    // ...}}Copy the code

As you can see at a glance from the above code, class Foo has two instance attributes. In addition, it is relatively simple to write.

Pay attention to

  1. Class does not have variable promotion because ES6 does not promote the class declaration to the code header. The reason for this rule has to do with inheritance and the need to ensure that subclasses are defined after their parents.
new A(); // ReferenceError
class A {}
Copy the code

ES6 does not elevate class declarations to the code header. The reason for this rule has to do with inheritance and the need to ensure that subclasses are defined after their parents.

{
  let A = class {};
  class B extends A {}}Copy the code

The above code does not report an error, because when B inherits from A, A is already defined. However, if there is A class promotion, the above code will report an error because the class is promoted to the header, while the let command is not promoted, resulting in B inheriting from A before Foo is defined.

  1. If this is inside a method that points to a class, it points to an instance of the class by default. You must be careful, however, that you may get an error if you use this method alone.

A static method

A class is the prototype of an instance, and all methods defined in a class are inherited by the instance. The static keyword before a method means that the method is not inherited by the instance but is called directly from the class. This is called a “static method”.

class A {
    static classMethod() {
        return 'hello';
    }
}
A.classMethod();
console.log(A.classMethod());
// 'hello'
const a = new A();
a.classMethod();
// TypeError: a.classMethod is not a function
Copy the code

A static method called on instance A will throw an error indicating that the method does not exist.

If a static method contains the this keyword, this refers to the class, not the instance.

class A {
    static classMethod() {
      this.baz();
    }
    static baz() {
      console.log('hello');
    }
    baz() {
      console.log('world');
    }
}
A.classMethod();
// hello
Copy the code

The static method classMethod calls this.baz, where this refers to class A, not an instance of A, the same as calling A.baz. Also, as you can see from this example, static methods can have the same name as non-static methods.

Static methods of a parent class that can be inherited by subclasses.

class A {
    static classMethod() {
        console.log('hello'); }}class B extends A {}
B.classMethod() // 'hello'
Copy the code

Static attributes

Static properties refer to properties of the Class itself, class.propName, not properties defined on the instance object (this). This is done by adding the static keyword before the instance attribute.

class MyClass {
  static myStaticProp = 42;
  constructor() {
    console.log(MyClass.myStaticProp); / / 42}}Copy the code

Getters and setters

As in ES5, you can use the get and set keywords inside a “class” to set the store and value functions for an attribute and intercept the access behavior of that attribute.

class MyClass {
  constructor() {
    // ...
  }
  get prop() {
    return 'getter';
  }
  set prop(value) {
    console.log('setter: '+value); }}let inst = new MyClass();

inst.prop = 123;
// setter: 123

inst.prop
// 'getter'
Copy the code

In the above code, the prop property has corresponding store and value functions, so the assignment and read behavior are customized.

The store and value functions are set on the Descriptor object of the property.

class CustomHTMLElement {
  constructor(element) {
    this.element = element;
  }

  get html() {
    return this.element.innerHTML;
  }

  set html(value) {
    this.element.innerHTML = value; }}var descriptor = Object.getOwnPropertyDescriptor(
  CustomHTMLElement.prototype, "html"
);

"get" in descriptor  // true
"set" in descriptor  // true
Copy the code

In the above code, the store and value functions are defined on the description object of the HTML attribute, which is exactly the same as in ES5.

inheritance

Class can be inherited through the extends keyword

class Animal {}
class Cat extends Animal {};Copy the code

This code defines a Cat class that extends all the properties and methods of the Animal class through the extends keyword. But since no code is deployed, the two classes are exactly the same, making a copy of the Animal class. Now, let’s add code inside Cat.

class Cat extends Animal {
    constructor(name, age, color) {
        // Call parent constructor(name, age)
        super(name, age);
        this.color = color;
    }
    toString() {
        return this.color + ' ' + super.toString(); // Call the parent toString()}}Copy the code

The super keyword appears in both the constructor and toString methods, where it represents the parent’s constructor, which is used to create a new parent’s this object.

Subclasses must call the super method from the constructor method, or new instances will report an error. This is because the subclass’s this object must be molded by the parent’s constructor to get the same instance attributes and methods as the parent, and then processed to add the subclass’s instance attributes and methods. If you don’t call super, your subclasses don’t get this.

class Animal { / *... * / }
class Cat extends Animal {
  constructor(){}}let cp = new Cat();
// ReferenceError
Copy the code

Cat inherits from Animal, but its constructor does not call super, causing an error when creating a new instance.

If the subclass does not define a constructor method, this method is added by default, as shown below. That is, any subclass has a constructor method whether or not it is explicitly defined.

class Cat extends Animal {}/ / is equivalent to
class Cat extends Animal {
    constructor(. args) {
        super(...args);
    }
}
Copy the code

Another point to note is that es5 constructors can access this before calling the parent constructor, but ES6 constructors can’t access this before calling the parent constructor (that is, super).

class A {
  constructor(x, y) {
    this.x = x;
    this.y = y; }}class B extends A {
  constructor(x, y, name) {
    this.name = name; // ReferenceError
    super(x, y);
    this.name = name; / / right}}Copy the code

In the code above, the subclass’s constructor method uses the this keyword without calling super, which results in an error and is correct after the super method.

Static methods of the parent class are also inherited by subclasses.

class A {
  static hello() {
    console.log('hello world'); }}class B extends A {
}
B.hello()  // hello world
Copy the code

super

The super keyword can be used as either a function or an object

Super is called as a function

When called as a function, super represents the constructor of the parent class. ES6 requires that the constructor of a subclass must execute the super function once.

class A {}
class B extends A {
  constructor() {
    super();
  }
}
Copy the code

The super() in the constructor of subclass B represents the constructor calling the parent class. This is necessary, otherwise the JavaScript engine will report an error.

Note that super although represents the parent class constructor, but returns the instance of the subclass B, namely the inside of the super this refers to the instance of B so super () is equivalent to Amy polumbo rototype here. The constructor. Call (this).

class A {
  constructor() {
    // new.target points to the function being executed
    console.log(new.target.name); }}class B extends A {
  constructor() {
    super();
  }
}
new A() // A
new B() // B
Copy the code

When super() executes, it points to the constructor of subclass B, not the constructor of superclass A. That is, the this inside super() refers to B.

Super is called as an object

** In normal methods, a prototype object refers to the parent class; ** In static methods, points to the parent class.

The super object is called in a normal function

class A {
  p() {
    return 2; }}class B extends A {
  constructor() {
    super(a);console.log(super.p()); / / 2}}let b = new B();
Copy the code

In the code above, super.p() in subclass B uses super as an object. In this case, super refers to a.prototype in normal methods, so super.p() equals a.prototype.p ().

It is important to note that since super refers to the parent’s prototype object, methods or properties defined on the parent instance cannot be called by super.

class A {
  constructor() {
    this.p = 2; }}class B extends A {
  get m() {
    return super.p; }}let b = new B();
b.m // undefined
Copy the code

In the code above, p is an attribute of an instance of superclass A. super.p does not refer to it.

Super can be fetched if the property is defined on a stereotype object of the parent class.

class A {}
A.prototype.x = 2;
class B extends A {
  constructor() {
    super(a);console.log(super.x) / / 2}}let b = new B();
Copy the code

In the code above, the attribute x is defined above a.protoType, so super.x can take its value.

The super object is called in a static method

Used in static methods, super refers to the parent class, not the parent class’s prototype object.

class Parent {
  static myMethod(msg) {
    console.log('static', msg);
  }
  myMethod(msg) {
    console.log('instance', msg); }}class Child extends Parent {
  static myMethod(msg) {
    super.myMethod(msg);
  }
  myMethod(msg) {
    super.myMethod(msg);
  }
}
Child.myMethod(1); // static 1
const child = new Child();
child.myMethod(2); // instance 2
Copy the code

In the code above, super refers to the parent class in static methods and to the parent class’s prototype object in normal methods.

Also, when a method of a parent class is called through super in a static method of a subclass, the this inside the method refers to the current subclass, not the instance of the subclass.

class A {
  constructor() {
    this.x = 1;
  }
  static print() {
    console.log(this.x); }}class B extends A {
  constructor() {
    super(a);this.x = 2;
  }
  static m() {
    super.print();
  }
}
B.x = 3;
B.m() / / 3
Copy the code

In the code above, in the static method B.m, super.print points to the static method of the parent class. This in this method refers to B, not an instance of B.

conclusion

  • Class is a syntactic sugar, the underlying layer of which is created through the constructor.

  • All methods of a class are defined on the prototype property of the class.

  • Static methods: Add static before a method to indicate that the method is not inherited by the instance, but is called directly from the class.

  • Static property: Add static before the property to refer to the property of the Class itself, not the property defined on the instance object (this).

  • The constructors of ES5 can access this before calling the parent constructor, but the constructors of ES6 cannot access this before calling the parent constructor (that is, super).

  • super

    • Called as a function, representing the constructor of the parent class
    • Called as an object, in a normal method, pointing to a prototype object of the parent class; In static methods, point to the parent class.

Let’s do a couple more problems to check

1. What does the following code output

class Person {
  constructor(name) {
    this.name = name
  }
}
const member = new Person("John")
console.log(typeof member)
Copy the code

Answer: the object

The class is the syntactic sugar of the constructor. If you override the Person class as a constructor, it will be:

function Person() {
  this.name = name
}
Copy the code

Calling the constructor with new generates an instance of the constructor Person, on which typeof the keyword returns “object”, in which case “object” is printed.

2. What does the following code output

class Chameleon {
  static colorChange(newColor) {
    this.newColor = newColor
    return this.newColor
  }
  constructor({ newColor = 'green' } = {}) {
    this.newColor = newColor
  }
}
const freddie = new Chameleon({ newColor: 'purple' })
freddie.colorChange('orange')
Copy the code

Answer: TypeError

ColorChange is a static method. Static methods are designed to be used only by the constructor that created them (that is, Chameleon) and cannot be passed to instances. Because Freddie is an instance, static methods cannot be used by the instance, so TypeError is thrown.

3. What does the following code output

class Person {
  constructor() {
    this.name = "Lydia"
  }
}
Person = class AnotherPerson {
  constructor() {
    this.name = "Sarah"}}const member = new Person()
console.log(member.name)
Copy the code

The answer: “Sarah”

We can set the class to be equal to other class/function constructors. In this case, we set Person to AnotherPerson. The constructor name is Sarah, so the name attribute on the new Person instance member is Sarah.

Refer to the article

Author: Wood son star

Links: juejin. Cn/post / 684490…

Source: Nuggets