JS advanced understanding prototype

Posted by gurjit on Sat, 11 Dec 2021 05:10:02 +0100

Hello, I'm A bowl week , a front end that doesn't want to be drunk. If you are lucky enough to get your favor, I am very lucky~

summary

What is the prototype

In JavaScript, a Function is an object of type Function that contains properties and methods. The Prototype is an attribute of a Function type object.

The function definition contains the prototype attribute, and its initial value is an empty object. The original type of the function is not defined in JavaScript, so the prototype can be any type.

Prototypes are used to save the shared properties and methods of objects. The properties and methods of prototypes do not affect the properties and methods of the function itself.

The sample code is verified as follows

function fun() {
  console.log('Function prototype')
}
console.log(fun.prototype) // {}

fun.prototype also returns an empty object, but this does not mean object There are no attributes or methods in prototype. These attributes and methods cannot be enumerated. The example code is as follows:

function fun() {
  console.log('Function prototype')
}

console.log(fun.prototype) // {}
// Through object Getownpropertynames() get all properties
console.log(Object.getOwnPropertyNames(fun.prototype)) // [ 'constructor' ]

The constructor attribute points to the reference of the constructor. The code is as follows:

// constructor property

console.log(fun.prototype.constructor) // [Function: fun]

console.log(fun.prototype.constructor === fun) // true

Get prototype

After understanding the concept and functions of prototypes, we need to obtain prototypes before we can operate them. There are two ways to obtain prototypes in JavaScript, as shown below:

  1. Through the prototype attribute of the constructor.

  2. Through object Getprototypeof (obj) method.

The difference between the two is that the prototype attribute of the constructor is generally used only with the constructor, while object The getprototypeof (obj) method is generally a prototype method to obtain the object instantiated by the constructor.

The example code is as follows:

// Constructor
function Person(name) {
  this.name = name
}

// Points to the prototype of the constructor
var p1 = Person.prototype

var person = new Person('A bowl week')

// Points to the prototype of the constructor
var p2 = Object.getPrototypeOf(person)

console.log(p1 === p2) // true

After obtaining the prototype, you can operate like an operation object, because the prototype itself is an object.

Prototype properties

In JavaScript, the function itself is also an object containing methods and properties. Next, we will learn another property of the function object - prototype. The initial value of this property is an empty object.

Add attributes and methods using prototypes.

Another way to add properties and methods to an object is to add them through a prototype. When you add a prototype property and a prototype method to a constructor, all objects new through the constructor share the property and method.

PS: the so-called prototype attribute or prototype method is the attribute or method added through the prototype.

There are several ways to add properties and methods

  1. Directly add attributes or methods to it

  2. Through object Defineproperty () method, add a property or method. This method is more secure than the first method.

  3. Add objects directly to the prototype.

The example code is as follows:

//Constructor
function Fun() {}
//Add properties and methods directly to the constructor
Fun.prototype.str = 'This is a string'
Fun.prototype.fn = function () {
  console.log('This is a method')
}
//Add a property or method through defineProperty
Object.defineProperty(Fun.prototype, 'MyFun', {
  value: function () {
    console.log('this is MyFun')
  },
})
//test
console.log(Fun.prototype.str)
Fun.prototype.fn()
Fun.prototype.MyFun()
var fun = new Fun()
fun.MyFun()
//Directly define an object for it to overwrite the previous prototype
Fun.prototype = {
  name: 'A bowl week',
  fun: function () {
    console.log('this is function')
  },
}
Fun.prototype.fun()
var fun = new Fun()
fun.fun()

Accessing prototype properties prototype methods

For the prototype, the most important point is its real-time performance. In JavaScript, almost all objects are passed by reference, so each new object entity we create does not have its own prototype copy. This means that we can modify the prototype property at any time, and the prototype properties of all objects created by the same constructor will change at the same time, including the properties and methods created by the constructor between us.

Still in the above code, we add a new method to the prototype and call it. The example code is as follows:

Fun.prototype.fn = function () {
  console.log('This is a method')
}
fun.fn() //This is a method

The objects we created earlier can access the newly added prototype properties and prototype methods.

Own attribute and prototype attribute

Let's first create a constructor and add two prototype properties to it.

//Constructor
function Fun() {}
//Add prototype properties and methods
Fun.prototype.name = 'A cup of porridge'
Fun.prototype.print = function () {
  console.log('this is function')
}

After creating an object through this constructor, set its properties and methods

//Creating objects through constructors
var fun = new Fun()
//Adding properties and methods to objects
fun.name = 'A bowl week'
fun.SayMe = function () {
  console.log('this is SayMe')
}

Now our fun object has two own properties / methods and two prototype properties / methods. Let's access these properties and methods in turn.

//Access properties and methods
console.log(fun.name) // A bowl week
fun.SayMe() // this is SayMe
fun.print() // this is function

When we access the name attribute, the JavaScript engine will traverse all the attributes of fun and return the value of the name attribute. The same goes for the SayMe() method. However, when it comes to the print() method, the JavaScript engine will still traverse all the properties of the object. At this time, there is no print() method. Then the JavaScript engine will access the prototype of the constructor function that creates the current object, that is, our fun Prototype. If it has this attribute, it will be returned immediately. Otherwise, it will return undefined or throw an exception

Conclusion: when there are self owned attributes, first access the self owned attributes, and then access the prototype attributes after accessing the self owned attributes.

Detect own attribute or prototype attribute

Now we know the concepts and uses of self owned attributes and prototype attributes, but how do we know whether a free attribute or an original attribute is an attribute? JavaScript provides the following two ways to detect an attribute

  • Use object prototype. Hasownproperty (prop) method to detect whether the prop property is a free property. This method returns a Boolean value. If it is a self owned property, it returns true, otherwise it returns false.

  • To use the in keyword to detect whether the object and prototype chain have specified attributes.

The test code is as follows:

// Through object prototype. The hasownproperty (prop) method detects whether it is a self owned property
console.log(fun.hasOwnProperty('name')) // true
console.log(fun.hasOwnProperty('print')) // false
// If an attribute does not exist, the detection result is also false
console.log(fun.hasOwnProperty('SayMe')) // true

// Through the in operator
console.log('name' in fun) // true
console.log('print' in fun) // true
console.log('SayMe' in fun) // true

Through the test, we found that the two methods can not detect whether an attribute is a self owned attribute or a prototype attribute, but the combination of the two methods can detect whether it is a self owned attribute or a prototype attribute. The example code is as follows:

function DetectionAttributes(obj, attr) {
  if (attr in obj) {
    if (obj.hasOwnProperty(attr)) {
      // If it is a self owned attribute, the attribute returns 1
      return 1
    } else {
      // If it is a prototype property, return 0
      return 0
    }
  } else {
    // Without this property, - 1 is returned
    return -1
  }
}

The tests are as follows:

console.log(DetectionAttributes(fun, 'name')) // 1
console.log(DetectionAttributes(fun, 'print')) // 0
console.log(DetectionAttributes(fun, 'SayMe')) // 1

isPrototypeOf() method

The isPrototypeOf() method is used to detect whether an object exists in the prototype chain of another object. If it exists, it returns true, otherwise it returns false.

The example code is as follows:

// Defines an object to assign to the prototype object
var obj = function () {
  this.name = 'A bowl week'
}
var Hero = function () {} // Define constructor
// Assign the defined object to the prototype of the constructor
Hero.prototype = obj

// Creating objects with Hero
var hero1 = new Hero()
var hero2 = new Hero()
// Judge whether the two created objects are in the prototype chain of obj
console.log(obj.isPrototypeOf(hero1)) // true
console.log(obj.isPrototypeOf(hero2)) // true

Extend built-in objects

Some built-in objects in JavaScript also have the prototype attribute. Using the prototype attribute of the built-in object, you can extend the attributes and methods for the built-in object.

It is very flexible to extend the properties and methods of built-in objects through prototypes, and formulate the specific content of JavaScript language according to personalized requirements.

There are two ways to extend built-in objects, as shown below:

  • By directly adding attributes and methods.

  • Add a new property or method for the Object object through its defineProperty() method. This method is better than the first method because the created properties and methods are more secure

The example code is as follows:

// Extend properties and methods for Object
// Use the first method
Object.prototype.MyPrint = function () {
  console.log('this is MyPrint()')
}
// Use the second method
Object.defineProperty(Object.prototype, 'MyInput', {
  value: function () {
    console.log('this is MyInput()')
  },
})
// call
Object.prototype.MyPrint() // this is MyPrint()
Object.prototype.MyInput() // this is MyInput()

Write at the end

This article introduces the concept of prototype in JavaScript, prototype properties, how to detect self owned properties and prototype properties, and how to extend built-in objects. We will introduce some contents of prototype chain in the next article

This is[ Ab initio front end ]The 51st article in the series, prototype, if you like this column, you can pay attention to me or the column~

This series of articles started in nuggets. It is not easy to reprint. Please get permission

Previous recommendation

Topics: Javascript Front-end