Recently, we found that symbol is a unique value, but symbol cannot perform new operation. It can only be used as a function. Type errors will occur when running new
new Symbol() // error Uncaught TypeError: Symbol is not a constructor at new Symbol (<anonymous>) at <anonymous>:1:1
If the underlying implementation is not considered, is it possible to implement a function that can only be called but cannot be called at the code level? After thinking, write the following code:
function disConstructor() { if (this !== window) { throw new TypeError(' disConstructor is not a constructor') } console.log('gogo go') } // The test results are as follows disConstructor() // gogo go new disConstructor() // error Uncaught TypeError: disConstructor is not a constructor at new disConstructor (<anonymous>:3:15) at <anonymous>:1:1
When using nodejs, window can switch to global, and the execution result of the code remains unchanged. This is because there is no applicable scenario for individuals. Therefore, although there is no further research, recently, rereading es 6 found new target.
new.target attribute
Introduction (reference mdn documents)
new. The target attribute allows you to detect whether a function or constructor is called through the new operator. In a function or constructor initialized by the new operator, new Target returns a reference to a constructor or function. In a normal function call, new The value of target is undefined.
In this way, our code can be changed to:
function disConstructor() { // In ordinary function calls, new The value of target is undefined. if (new.target) { throw new TypeError(' disConstructor is not a constructor') } console.log('gogo go') }
Get the same answer as the above code.
thorough
Is the function specially added by es6 only used to check our function call mode? In the process of consulting, it is found that most of the schemes use new Target writes out classes that can only be inherited. It is similar to an abstract class that implements java.
class Animal { constructor(name, age) { if (new.target === Animal) { throw new Error('Animal class can`t instantiate'); } this.name = name this.age = age } // Other codes ... } class Dog extends Animal{ constructor(name, age, sex) { super(name, age) this.sex = sex } } new Animal() // error Uncaught Error: Animal class can`t instantiate at new Animal (<anonymous>:4:13) at <anonymous>:1:1 new Dog('mimi', 12, 'common') // Dog {name: "mimi", age: 12, sex: "male"}
However, java abstract classes and methods need to be rewritten, and there is no solution. Therefore, in the process of testing and using, it was unexpectedly found that the superclass can access the prototype of the derived class during construction and make use of it.
class Animal { constructor(name, age) { console.log(new.target.prototype) } // Other codes ... }
This is how the error report of calling the method to be rewritten by the runtime is written.
class Animal { constructor(name, age) { this.name = name this.age = age } getName () { throw new Error('please overwrite getName method') } } class Dog extends Animal{ constructor(name, age, sex) { super(name, age) this.sex = sex } } const pite = new Dog('pite', 2, 'common') a.getName() // error Uncaught Error: please overwrite getName method at Dog.getName (<anonymous>:8:11) at <anonymous>:1:3
However, at this time, use new Target, I can use the operation of subclasses during construction to report errors.
class Animal { constructor(name, age) { // If the target is not a base class and there is no getName, an error is reported if (new.target !== Animal && !new.target.prototype.hasOwnProperty('getName')) { throw new Error('please overwrite getName method') } this.name = name this.age = age } } class Dog extends Animal{ constructor(name, age, sex) { super(name, age) this.sex = sex } } const pite = new Dog('pite', 2, 'common') // error Uncaught Error: please overwrite getName method at new Animal (<anonymous>:5:13) at new Dog (<anonymous>:14:5) at <anonymous>:1:1
At this time, the errors occurred during the operation of the method can be advanced to the construction period. Although they are all in the operation period, the error trigger mechanism should be early and the harm should be great. Instead, it is a kind of protection for the code.
Of course, using superclasses to access the prototype of derived classes during construction is far from simple. It must be very powerful. We can talk about understanding and role in combination with business scenarios.