1. Basic concepts

  • The traditional way is to generate instance objects through constructors
  • ES6’s Class is just a syntactic sugar, and the new Class notation just makes writing object prototypes clearer and more like object-oriented programming syntax.
  • The usage is exactly the same as that of the constructor
  • Internally defined methods do not require the function keyword; Methods do not need semicolons; You must use the new call
  • All methods of a class are defined on the prototype property of the class
  • The this keyword points to the instance object of the class, and the properties defined on this are defined on the instance object
  • The name attribute always returns the class name immediately after the class keyword
  • Inside classes and modules, the default is strict mode, so there is no need to use strict to specify the runtime mode
// 1
function Point(x, y) {
  this.x = x;
  this.y = y;
}
Point.prototype.toString = function () {
  return "(" + this.x + "," + this.y + ")";
};
let p = new Point(1.2); // {x:1,y:2}

// 2. Class rewrite =>
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    console.log("this->".this); // Point {x:1,y:2}
  }
  toString() {
    return "(" + this.x + "," + this.y + ")"; }}let p = new Point(1.2); // {x:1,y:2}
/ / is equivalent to
Point.prototype = {
  constructor() {},
  toString(){}};// 3. The data type of class is a function, and the class itself points to the constructor (consistent with ES5 behavior!).
typeof Point; // 'function'
// constructor is stored in prototype and points to its own constructor
Point === Point.prototype.constructor; // true
Copy the code

2. Construction method

  • Generated by the new commandInstance objectsIs automatically calledconstructor()
  • By default, the instance object this is returned

3. Instance properties, instance objects, this points to

  • A class is the prototype of an instance, and all methods defined in a class are inherited by the instance
  • Instance attributes: Attributes defined on this object are defined on the instance itself
  • Other defined methods are defined on the instance’s prototype by default (on the class’s Prototype property)
  • All instances of the class share a stereotype object
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  toString() {
    return "(" + this.x + "," + this.y + ")"; }}let point = new Point(2.3);
// x is defined on this, the instance itself; Methods are defined on the prototype of the instance
point.hasOwnProperty("x"); // T
point.hasOwnProperty("toString"); // F
point.__proto__.hasOwnProperty("toString"); // T
Copy the code
  • This loss problem
// Continue with the above example
const { toString } = point;
toString(); // Error x cannot be found
Copy the code

Solution: 1) bind this in constructor 2) use arrow function 3) use Proxy to automatically bind this when fetching method

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    // this.toString = this.toString.bind(this);
  }

  toString = () = > {
    return "(" + this.x + "," + this.y + ")";
  };
}
let point = new Point(2.3);
const { toString } = point;
toString(); / / 😀)
Copy the code

Instance attributes can be defined at the top of the class, not just above the constructor() method’s this. The advantage of this is that you can see at a glance what instance attributes the class has

class Foo {
  bar = "hello";
  baz = "world";
  constructor(){}}let f = new Foo(); // Foo {bar,baz}
Copy the code

4. Store values/value functions setter/getter

  • Use the get/set keyword to set a value/store function for an attribute, intercepting operations on that attribute
  • The store and value functions are set on the Descriptor object of the property
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

5. Static properties, static methods

  1. A static method
  • Static methods, preceded by the static keyword, are not inherited by the instance and are called directly from the class
  • This in a static method refers to a class, not an instance! (Because it is called through a class, this points to the caller)
  • Static methods can have the same name as non-static methods
  • Static methods of a parent class that can be inherited by subclasses
  • Static methods can also be called from super objects
class Foo {
  static classMethod() {
    return "hello";
  }
  static f1() {
    this.f2(); // This refers to class, so static methods are still called
    // Foo.prototype.f2(); // to call a non-static method
  }
  static f2() {
    console.log("static f2");
  }
  f2() {
    console.log("f2");
  }
}

Foo.classMethod(); // hello
Foo.f1(); // static f2
Copy the code
  1. Static properties: properties of the class itself, not properties defined on the instance object (this)
/ / the old way
class MyClass {}
MyClass.myStaticProp = 42;

/ / a new way
class MyClass {
  static myStaticProp = 42;
  constructor() {
    console.log(MyClass.myStaticProp); / / 42}}let m = new MyClass(); // MyClass{} : there is nothing on the instance object
Copy the code

6. Private methods, private properties

  1. Private methods can be moved out of the class because all methods inside the class are visible
class Widget {
  foo(baz) {
    bar.call(this, baz); }}function bar(baz) {
  return (this.snaf = baz);
}

let w = new Widget();
w.foo("123");
w; // Widget {snaf:123}
Copy the code
  1. A proposal for a private property, used before the property name#said

#count is a private attribute that can only be used inside a class (this.#count). If used outside the class, an error is reported

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

other

The class expressions

// Use an expression to define the class
const MyClass = class Me {};
let inst = new MyClass();

// Execute class immediately
let person = new (class {
  constructor(name) {
    this.name = name;
  }
})("Zhang");
Copy the code

Add methods to the class

  1. Use the object.assign () method
Object.assign(Point.prototype,{
  toString()
})
Copy the code
  1. By instance__proto__Property rewriting prototype. However, you must be careful not to use it, because it changes the original definition of the “class” and affects all instances
p1.__proto__.printName = function () {
  return "Oops";
};
Copy the code

And ES5 distinction

  1. Class has no variable promotion (for inheritance purposes)

  2. All methods defined inside a class are not enumerable; And ES5 is enumerable!

class Point {
  constructor(x, y) {}
  toString(){}}Object.keys(Point.prototype); / / []
Object.getOwnPropertyNames(Point.prototype); // ["constructor","toString"]

// ES5
let Point = function (x, y) {};
Point.prototype.toString = function () {};
Object.keys(Point.prototype); // ["toString"]
Object.getOwnPropertyNames(Point.prototype); // ["constructor","toString"]
Copy the code

The new target attribute

  • ES6 introduces a target attribute for the new command, which is typically used in constructors to return the constructor on which the new command operates
  • This property can be used to determine how the constructor is called. Okay
  • When a subclass inherits from its parent, new.target returns the subclass

Reference: es6.ruanyifeng.com/#docs/class