JavaScript archetypes and inheritance

The prototype

Let’s take a look at some code

function User(name) {
  this.name = name
}
let no= new User('don't forget')

console.log(no);//User {name: "not forgotten "}
console.dir(User);/ / ƒ User (name)
console.dir(Function);ƒ Function() // Constructor of Function
console.dir(Object);//ƒ Object() // Constructor of Object
Copy the code

When you open the output above, you’ll see a Prototype, or __proto__ property, which is their prototype. When you open the prototype you’ll see a constructor property, which is the object’s constructor, which passes parent properties to children so that children have parent properties, parent and subset relationships

Children. _prop_ = = = parent. The prototype

Children. _prop_ the constructor = = = the parent

Since the parent can also be someone else’s child, so

_prop_._proto_=== prototype

A grandfather can also have a great-grandfather, and the chain of archetypes continues to the end by __prop__

I have drawn a diagram of the four outputs of the above function based on the above conditions

Yes, the JavaScript family is so dysfunctional that if you’re interested in studying it for yourself,

Such as:

Function gives birth to itself, so function._proto_ === function.prototypt

The parent of No is User, and the parent of user is Function, but the grandfather of No is Object

Function’s grandfather is Object, but Object’s father is Function and so on

The key is to know the relationship between the object and its prototype, and the child can use this method to directly call the parent’s properties. JavaScript inheritance uses this method to let the child inherit the parent’s properties.

function User(name) {
  this.name = name
  this.getName=function(){
    console.log(this.name); }}let no= new User('don't forget')
no.getName()/ / don't forget
// The method added in the prototype of the parent User can also be called by the child no
Copy the code

Methods on stereotype attributes

Set the create _proto_

let no={name:'don't forget'}
let yes=Object.create(no,{
  name: {value:'memories'}})console.log(yes);//{name: "memory "}
// The __proto__ of yes is no, and this method cannot be queried


let ok={name:'good'}
ok.__proto__ = no

console.log(ok);//{name: "ok "}
// The __proto__ of yes is no, which can be queried
Copy the code

SetPrototypeOf set _proto_

let no={name:'don't forget'}
let yes={name:'memories'}
Object.setPrototypeOf(yes,no)
console.log(yes);//{name: "memory "}
// The __proto__ of yes is no

__proto__ is an accessor that can only be changed to an object
Copy the code

IsPrototype determines if it is on the other party’s __proto__

let no={name:'don't forget'}
let yes={name:'memories'}
Object.setPrototypeOf(yes,no)
console.log(no.isPrototypeOf(yes));//true
// No returns true on yes's __proto__
Copy the code

The prototype of the instanceof constructor is on the prototype chain

function User(name) {
  this.name = name
}
let no= new User('don't forget')
console.log(no instanceof User);//true
// Returns true when no has User's prototype on its chain
Copy the code

HasOwnPrototype does not determine if the value above the prototype chain exists

let no={Nname:'don't forget'}
let yes={name:'memories'}
Object.setPrototypeOf(yes,no)

console.log('Nname' in no);//true
console.log(yes.hasOwnProperty('Nname'));//false
//hasOwerProperty will not be queried on the prototype chain
Copy the code

You can use Call and apply to call methods on other prototypes

function User(name) {
  this.name = name
}
User.prototype.getName=function(){
  console.log(this.name);
}
let no= new User('don't forget')

let yes={name:'memories'}

no.getName.call(yes)/ / recall
Copy the code

inheritance

I mentioned earlier that the prototype chain is used to implement inheritance, and the emphasis of inheritance is on the child. Prototype, the value given to the child’s prototype

basis

function User(name) {
  this.name = name
}
function Name() {}
Name.prototype.getName = function() {// Add a method to Name's prototype
  console.log(this.name);
}

User.prototype.__proto__=Name.prototype;//User inherits Name's prototype
// user.prototype = object.create (Name. Prototype
let no=new User('don't forget');
no.getName()// The prototype of Name is inherited, so we can call getName
Copy the code

Combined with the construct

function User(name) {
  this.name = name
}
function Name() {}
Name.prototype.getName = function() {
  console.log(this.name);
}

User.prototype=Object.create(Name.prototype)
User.prototype.constructor = Name;// Point the constructor past
Object.defineProperty(User.prototype,'constructor', {value:Name,
  enumerable:false
})// Static traverse
let no=new User('don't forget');
no.getName()/ / don't forget

// This changes Name to the parent of User
Copy the code

Child methods and parent methods call each other

function User(name) {
  this.name = name
}

function Name() {}
Name.prototype.getName = function() {
  return this.name
}
User.prototype=Object.create(Name.prototype)
User.prototype.show =function () {// This addition will be written after create
  console.log(this.getName()+'Girlfriend is Bing Bing');
}
User.prototype.constructor = Name;// Point the constructor past
Object.defineProperty(User.prototype,'constructor', {value:Name,
  enumerable:false
})// Static traverse
let no=new User('don't forget');
no.show()// Don't forget your girlfriend is Bingbing
Copy the code

Parent initial property

function User(name,age) {
  this.name = name
  this.age=age
}

Girl.prototype=Object.create(User.prototype)

function Girl(name,age) {
  User.call(this,name,age)// Call it with call
}
User.prototype.show=function(){
  console.log(this.name+"This year"+this.age+'old');
}

let yes=new Girl('ice ice'.'18')

yes.show()// Bingbing is 18 years old
Copy the code

Inheritance method encapsulation

 function extend(son,father) {// Son, father
   son.prototype=Object.create(father.prototype);/ / set the prototy
   Object.defineProperty(son.prototype, 'constructor', {/ / set the constructor
     value: father,
     enumerable:false})},function User(name,age) {
  this.name = name
  this.age=age
}

extend(Girl,User)

function Girl(name,age) {
  User.call(this,name,age)
}
User.prototype.show=function(){
  console.log(this.name+"This year"+this.age+'old');
}

let yes=new Girl('ice ice'.'18')

yes.show()// Bingbing is 18 years old
Copy the code

Object Factory inheritance

function User(name,age) {
  this.name = name
  this.age=age
}


function girl(name,age) {
  const gproto=Object.create(User.prototype)Create an object that inherits Prototype
  User.call(gproto,name,age)
  return gproto
}
User.prototype.show=function(){
  console.log(this.name+"This year"+this.age+'old');
}

let yes=girl('ice ice'.'18')

yes.show()
Copy the code

Multiple inheritance

function extend(son,father) {
   son.prototype=Object.create(father.prototype);
   Object.defineProperty(son.prototype, 'constructor', {value: father,
     enumerable:false})},function Boy(name,age) {
  this.name = name;
  this.age = age;
}

function Sound() {}
Sound.prototype.a=function(){
  console.log(this.name+'Falsetto');
}
function Mackeup() {}
Mackeup.prototype.b=function(){
  console.log(this.name+'Can put on make-up');
}
function Wear() {}
Wear.prototype.c=function(){
  console.log(this.name+'Dress for the ladies');
}

extend(Mackeup,Wear)
extend(Sound,Mackeup)
extend(Boy,Sound)
let yes=new Boy('ice ice'.'18')
yes.a()// Ice ice can falsetto
yes.b()// Ice will make up
yes.c()// Bingbing will wear women's clothing

// When you need to inherit from different parents, you can only have one father, so you can change the link to grandfather or great-grandfather
Copy the code

Mixins upgrade

function Boy(name,age) {
  this.name = name;
  this.age = age;
}

Sound={
  a:function(){
    console.log(this.name+'Falsetto');
  }
 }
Mackeup={
  b:function(){
    console.log(this.name+'Can put on make-up');
  }
 }
Wear={
  c:function(){
    console.log(this.name+'Dress for the ladies');
  }
}
Boy.prototype=Object.assign(Boy.prototype,Sound,Mackeup,Wear);

let yes=new Boy('ice ice'.'18')
yes.a()// Ice ice can falsetto
yes.b()// Ice will make up
yes.c()// Bingbing will wear women's clothing
// This eliminates the need to keep extending the prototype chain
Copy the code

Mixins can have internal inheritance and super keywords

function Boy(name,age) {
  this.name = name;
  this.age = age;
}

let Run={
  go:function(){
    return 'Run fast'}}let Mackeup={
  __proto__:Run,
  make(){// The method must be written this way to use super
    // console.log(this.__proto__.go()+' go to makeup ');
    console.log(super.go()+'Go put on your make-up');
  }
 }

Boy.prototype=Object.assign(Boy.prototype,Mackeup,Run);

let yes=new Boy('ice ice'.'18')
yes.make()
Copy the code

class

Inherited grammar sugar

class User {
  constructor(name){
    this.name = name;
  }
  girlfriend(){
    console.log(this.name+'Have a lot of girlfriends'); }}let no=new User('don't forget');
no.girlfriend()// Don't forget to have many girlfriends

// Create objects in strict mode, not traversal
Copy the code

Static attributes

class User {
  static from='China'
  where(){
    console.log(User.from); }}let no=new User();
let yes=new User();
no.where()/ / China
yes.where()/ / China
// Public data are static attributes
Copy the code

A static method

class User {
  static show(){
    console.log('Directly called method');
  }
}

User.show()// The method called directly
// Call the object directly without instantiating it
Copy the code

Accessor to class

class User {
  constructor(name,age){
    this.name = name;
    this.age = age;
  }
  set age(nub) {if(nub<=18) {throw new Error("No minors allowed.")}}get age() {return this.age
  }
}

let no=new User('don't forget'.18)//Uncaught Error: Minors cannot enter // same as objects
Copy the code

The class inheritance

class Change {
  constructor(age){
   this.age=age;
  }
  code(){
    console.log(this.name+'Code gets stronger and stronger.');
  }
  see(){
    console.log(this.age); }}class User extends Change{
  constructor(name,age){
    super(age)
    this.name = name; }}let no=new User('don't forget'.18)
no.code()// Do not forget the code more powerful
no.see()/ / 18
Copy the code

Private property

class Change {
  #characteristics="Birthmark on ass."
  constructor(age){
   this.age=age;
  }
  #code(){
    console.log(this.name+'Code gets stronger and stronger.');
  }
  see(){
    console.log(this.age); }}class User extends Change{
  constructor(name,age){
    super(age)
    this.name = name; }}let no=new User('don't forget'.18)
// no.#code()//Uncaught SyntaxError: Private field '#code' must be declared in an enclosing class
console.log(no.#characteristics);//Uncaught SyntaxError: Private field '#characteristics' must be declared in an enclosing class
            
 // The property and the method cannot be accessed externally, and the method cannot be inherited
Copy the code

Multiple inheritance

class Boy{
  constructor(name,age){
    this.name = name;
    this.age = age;
  }
  
}

Sound={
  a:function(){
    console.log(this.name+'Falsetto');
  }
 }
Mackeup={
  b:function(){
    console.log(this.name+'Can put on make-up');
  }
 }
Wear={
  c:function(){
    console.log(this.name+'Dress for the ladies');
  }
}
Boy.prototype=Object.assign(Boy.prototype,Sound,Mackeup,Wear);

let yes=new Boy('ice ice'.'18')
yes.a()// Ice ice can falsetto
yes.b()// Ice will make up
yes.c()// Bingbing will wear women's clothing
// Same as constructor
Copy the code