preface

Last year, I drew a mind map of my knowledge system to plan my learning scope and direction. However, I made a big mistake. My mind map was only a global blueprint, and I did not systematize the knowledge when I learned some knowledge points. The knowledge was too scattered, and on the other hand, it was easy to forget. With this in mind, I recently started to use mind mapping to learn and summarize specific knowledge points, and the results have been good.

Imagine how sour the chain of knowledge is when one mind map ends with another. Of course, just think about it. I guarantee you won’t have enough time to do a mind map of everything. Just pick the key points.

Outline ideas

When we want to study a problem or knowledge point, the focus is nothing more than:

  1. What is?

  2. What to do?

  3. Why is that?

Obviously, understanding “what” is the most fundamental, and this part is important. Great oaks grow from little acorns. If you don’t even know the basics, you won’t be able to talk about application practice (” what to do “), still less understand the essence of the problem (” why “).

In order to organize a high-quality mind map, we must make full use of the idea of “total – points”. First, we must form a basic outline, and then extend it from all aspects, and finally get a relatively complete knowledge tree. After breaking it down, you may be pleasantly surprised to find the connections between the various parts of a piece of knowledge and get a fuller understanding of it.

Combing the outline needs to have an overall understanding of the knowledge. My strategy for learning a new domain is to extract an outline from a list of relevant books or official documents.

The following is my review of javascript object knowledge when some ideas as an example.

Javascript object

When reviewing the knowledge of javascript objects, I extracted the following aspects as an outline from some previous experience, books and documents:

  • Classification of objects

  • Three important concepts of objects: class, prototype, and instance

  • Method of creating an object

  • Object properties

  • Prototypes and Inheritance

  • Static and prototype methods

This leads to a mind map like this:

Classification of objects

There are three main categories of objects:

  • Built-in objects: Classes or objects defined in the ECMAScript specification, such as Object, Array, Date, etc.

  • Host object: Provided by the host environment in which the javascript interpreter is embedded. For example, the browser environment provides browser specific host objects such as Windows, htmlElements, and so on. Nodejs will provide global global objects

  • Custom objects: Objects created by javascript developers to implement a particular business. The familiar Vue, for example, is a custom object. We can instantiate the Vue object to generate vue-based applications.

Three important concepts for objects

class

Javascript did not have a class keyword before ES6, but this does not affect the fact that javascript can be used for object-oriented programming. The class name of javascript corresponds to the constructor name.

Before ES6, if we wanted to define a class, we did it with functions.

function Person(name) {
  this.name = name;
}
Person.prototype.sayHello = function() { 
  console.log(this.name + ': hello! ');
}

var person = new Person('Faker');
person.sayHello();
Copy the code

ES6 clearly defines the class keyword.

class Person {
  constructor(name) {
    this.name = name;
  }

  sayHello() {
    console.log(this.name + ': hello! '); }}var person = new Person('Faker');
person.sayHello();
Copy the code

The prototype

Stereotypes are the core of a class and are used to define the properties and methods of the class that are inherited by the instance.

Defining the prototype properties and methods requires the constructor’s Prototype property, which allows you to get a reference to the prototype object and then extend the prototype object.

function Person(name) {
  this.name = name;
}
Person.prototype.sexList = ['man'.'woman'];
Person.prototype.sayHello = function() {
  console.log(this.name + ': hello! ');
}
Copy the code

The instance

A class is an abstract concept, equivalent to a template, and an instance is a concrete representation of a class. For example, Person is a class, and according to the Person class, we can instantiate multiple objects, such as Xiao Ming, Xiao Hong, Xiao Wang, and so on. The instances of the class are all independent individuals, but they all share a common stereotype.

var xiaoMing = new Person('Ming');
var xiaoHong = new Person('little red');

// Have the same prototype
Object.getPrototypeOf(xiaoMing) === Object.getPrototypeOf(xiaoHong); // true
Copy the code

How to create objects

Object direct

Object literals are also called object literals. Direct quantities create objects by writing key and value pairs without instantiation.

var xiaoMing = { name: 'Ming' };
Copy the code

Every time you write an object, you create a new object. Even if two objects look exactly the same, they point to different heap memory addresses, and objects are accessed by reference, so the two objects are not equal.

var xiaoMing1 = { name: 'Ming' };
var xiaoMing2 = { name: 'Ming' };
xiaoMing1 === xiaoMing2; // false
Copy the code

New constructor

You can get an instance of the object by calling the constructor of the javascript object with the keyword new. Such as:

  1. Create a built-in object instance
var o = new Object(a);Copy the code
  1. Create a custom object instance
function Person(name) {
  this.name = name;
};
new Person('Faker');
Copy the code

Object.create

Object.create creates an Object that takes two arguments, using the following syntax;

Object.create(proto[, propertiesObject]);
Copy the code

The first argument, proto, specifies the prototype of the newly created object;

The second parameter, propertiesObject, is an object consisting of the property name and property descriptor of the newly created object.

Proto can be specified as NULL, but it means that the new Object’s prototype is null and it does not inherit Object methods such as toString().

The propertiesObject parameter has the same format as the second parameter of the object.defineProperties method.

var o = Object.create(Object.prototype, {
  // Foo will become a data attribute of the created object
  foo: { 
    writable:true.configurable:true.value: "hello" 
  },
  // Bar becomes the accessor property of the created object
  bar: {
    configurable: false.get: function() { return 10 },
    set: function(value) {
      console.log("Setting o.bar to", value); }}});Copy the code

Property query and setting

Attribute query

Property queries can also be called property accesses. In javascript, object property queries are very flexible, supporting both dot queries and string index queries (” string index “because it looks like an array and the index is a string rather than a number).

Accessing a property by a dot plus a property name behaves much like some statically typed languages such as Java, C, etc. The property name is a javascript identifier that must be written directly in the property access expression and cannot be accessed dynamically.

var o = { name: 'Ming' };
o.name; // "Xiao Ming"
Copy the code

The attribute name is the value of the string expression, and an expression can accept variables, which means that the attribute can be accessed dynamically, giving javascript programmers a lot of flexibility. Here is a very simple example, but this feature is very useful in business practices, such as deep copy implementations, where you often don’t know what properties are in the object you are copying.

var o = { chineseName: 'Ming'.englishName: 'XiaoMing' };
['chinese'.'english'].forEach(lang= > {
  var property = lang + 'Name';
  console.log(o[property]); // The string index is used to access the object properties
})
Copy the code

By the way, property queries can query not only free properties, but also inherited properties.

var protoObj = { age: 18 };
var o = Object.create(protoObj);
o.age; // 18, where the stereotype attribute is accessed, that is, the inherited attribute
Copy the code

Attribute set

By accessing a property expression, we can get a reference to the property and set the property accordingly. Focus on read-only properties and inherited properties. I won’t expand on the details.

Prototypes and Inheritance

The prototype

As mentioned earlier, archetypes are the basis for implementing inheritance. So how do you understand archetypes?

First, it is necessary to clarify the triangle in the concept of prototype. The three protagonists are constructor, prototype and instance. Let me draw a little bit of a simple diagram here to help you understand it.

Prototypes, I feel, “No one can help you understand, you have to try to understand”.

A constructor has a property called “prototype” that points to its prototype, and an instance can point to its prototype through its __proto__ attribute. This clearly fails to understand that objects are accessed by reference. There is always only one prototype object, which is stored in the heap, and the constructor’s prototype property simply gets a reference to the prototype through which it can be manipulated.

Similarly, __proto__ is only a reference to a prototype, but note that __proto__ is not part of the ECMAScript specification, so never use it in a production environment.

The reason why a prototype cannot be accessed through __proto__ is simple. Access to and modification of the prototype directly through the instance is inherently dangerous.

So, for example, here’s a class called LatinDancer, which means LatinDancer. After the instantiation operation, a number of Latin dancers are obtained.

function LatinDancer(name) {
  this.name = name;
};
LatinDancer.prototype.dance = function() {
  console.log(this.name + 'Latin dance... ');
}

var dancer1 = new LatinDancer('Ming');
var dancer2 = new LatinDancer('little red');
var dancer3 = new LatinDancer('wang');
dancer1.dance(); // Xiao Ming dances Latin dance...
dancer2.dance(); // Little Red dance Latin dance...
dancer3.dance(); // Xiao Wang dances Latin dance...
Copy the code

Everyone is dancing happily Latin dance, suddenly xiao Wang this guy whim, said: “I want to do B-boy, I want to do Breaking”. So he privately modified the prototype method dance().

Dancer3.__proto__.dance = function() {console.log(this.name + 'breaking... '); } dancer1.dance(); // Xiao Ming is breaking... dancer2.dance(); // Little Red is breaking... dancer3.dance(); // Xiao Wang is breaking...Copy the code

At this time, something was wrong, Xiao Ming and Xiao Hong were dancing Latin, suddenly Breaking out of control, and they started to dance. In their heart, they secretly swore: “Woma, isn’t Labor dancing Latin?”

This is just an example, no disrespect to any kind of dance or dancer, sorry, sorry.

So you can see why __proto__ can’t be used.

Prototype chain

In javascript, every Object has a prototype except object. prototype, which has no prototype, or its prototype is null.

So what is a prototype chain? When a javascript program looks for an object’s properties or methods, it first looks in the object itself, and if it can’t find them, it looks in the object’s prototype. If you can’t find it on the prototype, you’ll find it on the prototype, and you’ll find it on the prototype, and you’ll find it on the prototype, and you’ll find it on the prototype, and you’ll form a chain that ends in null.

Note also that the constructor is an Object and has a prototype. Its prototype can be obtained through function.prototype, while the prototype of function.prototype can be obtained through object.prototype.

inheritance

When it comes to inheritance, the concepts of “prototype chain inheritance”, “borrow constructor inheritance”, “parasitic inheritance”, “prototype inheritance”, and “parasitic combination inheritance” may come to mind. To tell you the truth, I remember that at first, but it seems not so easy to understand. At the end of the day, I found that it was easy to understand how to implement inheritance by starting with the prototype triangle.

As we know, there are three sources of properties and methods that an object instance can access: properties that are mounted to the instance when the constructor is called, prototype properties, and properties that are added to the object itself after it is instantiated.

Obviously, the third source is not used for inheritance, so what are the advantages and disadvantages of the first two sources? Obviously, it is not possible to fully inherit properties or methods from a parent class if you inherit from only one of these sources.

First of all, the three main bodies in the inheritance: parent class, subclass, subclass instance. So how do you get a subclass instance to be related to a parent class?

Prototype chain inheritance

Inheritance is simply the ability to access properties and methods of a parent class through an instance of a subclass. And the use of prototype chain can achieve such a purpose, so as long as the parent class prototype, subclass prototype, subclass instances form a prototype chain relationship.

Example code:

function Father() {
  this.nationality = 'Han';
};
Father.prototype.propA = 'I am a property on a superclass stereotype';
function Child() {};
Child.prototype = new Father();
Child.prototype.constructor = Child; // Modify the constructor property on the stereotype
Child.prototype.propB = 'I'm a property on a subclass stereotype.';
var child = new Child();
console.log(child.propA, child.propB, child.nationality); // can be accessed
child instanceof Father; // true
Copy the code

As you can see, in the above code, we have done such a Child. The special handling prototype. The constructor = Child; . One is to ensure that constructor is pointing correctly, since the instance is instantiated by a subclass. It would be inappropriate for constructor to point to a superclass constructor. The other is to prevent some methods from showing trouble when calling Constructor. Why is it Necessary to set the prototype constructor?

Key: make a subclass prototype an instance of the parent class, and a subclass instance an instance of the parent class.

Disadvantages: No arguments can be passed to the superclass constructor during instantiation.

Borrowing constructor

When the subclass constructor is called, the superclass constructor is called by call, specifying the value of this.

function Father() {
  this.nationality = 'Han';
};
Father.prototype.propA = 'I am a property on a superclass stereotype';
function Child() {
  Father.call(this);
};
Child.prototype.propB = 'I'm a property on a subclass stereotype.';
var child = new Child();
console.log(child.propA, child.propB, child.nationality);
Copy the code

PropA is undefined because a subclass instance is not an instance of the parent class and cannot inherit the parent class stereotype properties.

child instanceof Father; // false
Copy the code

Key point: constructor reuse.

Disadvantages: A subclass instance is not an instance of the parent class and cannot inherit the parent class archetype properties.

Combination of inheritance

The so-called combination inheritance is the synthesis of the above two methods. The implementation code is as follows:

function Father() {
  this.nationality = 'Han';
};
Father.prototype.propA = 'I am a property on a superclass stereotype';
function Child() {
  Father.call(this);
};
Child.prototype = new Father();
Child.prototype.constructor = Child; // Modify the constructor property on the stereotype
Child.prototype.propB = 'I'm a property on a subclass stereotype.';
var child = new Child();
console.log(child.propA, child.propB, child.nationality); // can be accessed
Copy the code

At first glance, this looks fine, but the Father() constructor is actually called twice. Prototype = new Father(); At this time, the subclass prototype becomes the instance of the parent class. When the parent class constructor Father() is executed, the instance attribute Nationality is obtained. Var child = new child (); In this case, the subclass constructor Child() is executed, and the parent class constructor is called through call() in Child(), so the subclass instance also obtains the instance attribute Nationality. This may seem a little confusing, but let’s look at the object structure of a subclass instance:

As you can see, both the subclass instance and the subclass stereotype have the property Nationality, which is acquired when the superclass constructor is executed. However, the purpose of inheritance is very simple, that is, “let the subclass inherit the properties and methods of the parent class”, but we should not contaminate the subclass stereotype by mounting unnecessary properties.

Some people will say “such a little side effect is afraid of what”. Of course, this side effect is minimal for such a simple parent class. Given that the superclass has hundreds of properties or methods, is this performance and memory wastage necessary? The answer is obvious.

Key point: Both instance properties and stereotype properties are inherited.

Disadvantages: The superclass constructor is executed twice, contaminating the subclass prototype.

Original type inheritance

Prototype inheritance is relative to prototype chain inheritance. The difference with prototype chain inheritance is that when a subclass prototype is created, it does not execute the superclass constructor and is a purely empty object.

function Father() {
  this.nationality = 'Han';
};
Father.prototype.propA = 'I am a property on a superclass stereotype';
function Child() {};
Child.prototype = Object.create(Father.prototype);
Child.prototype.constructor = Child; // Modify the constructor property on the stereotype
Child.prototype.propB = 'I'm a property on a subclass stereotype.';
var child = new Child();
console.log(child.propA, child.propB, child.nationality); // can be accessed
child instanceof Father; // true
Copy the code

Before ES5, you could simulate object.create like this:

function create(proto) {
  function F() {}
  F.prototype = proto;
  return new F();
}
Copy the code

Key point: Use an empty object transition to break the strong relationship between the subclass prototype and the superclass constructor. This also means that inheritance can be pure between objects, with no constructors involved.

Disadvantages: There is no way to pass arguments to the superclass constructor when instantiating, just like the prototype chain inheritance.

Parasitic inheritance

Parasitic inheritance has a design pattern that draws on factory functions, encapsulating the inheritance process into a function that returns the object, and extending the object’s methods or properties within the function.

var obj = {
  nationality: 'Han'
};
function inherit(proto) {
  var o = Object.create(proto);
  o.extendFunc = function(a, b) {
    return a + b;
  }
  return o;
}
var inheritObj = inherit(obj);
Copy the code

[inheritObj] [obj] [extendFunc] [obj] [extendFunc] [obj] [extendFunc]

Key points: factory functions, encapsulating procedure functionalization.

Disadvantages: If you extend object properties or methods in a factory function, reuse is not possible.

Parasitic combination inheritance

It is used to solve the problem of “the superclass constructor is called many times” in the process of combination inheritance.

function inherit(childType, fatherType) {
  childType.prototype = Object.create(fatherType.prototype);
  childType.prototype.constructor = childType;
}

function Father() {
  this.nationality = 'Han';
}
Father.prototype.propA = 'I am a property on a superclass stereotype';
function Child() {
  Father.call(this)
}
inherit(Child, Father); / / inheritance
Child.prototype.propB = 'I'm a property on a subclass stereotype.';
var child = new Child();
console.log(child);
Copy the code

Key point: Solve the problem of multiple execution of the superclass constructor, while making the subclass prototype more pure.

A static method

What is a “static method”? Static methods are class-owned, do not belong to any instance, and need to be called directly by the class name.

function Child() {}
Child.staticMethod = function() { console.log("I'm a static method")}var child = new Child();
Child.staticMethod(); // "I am a static method"
child.staticMethod(); // Uncaught TypeError: child.staticMethod is not a function
Copy the code

The Object class has a number of static methods, which I tend to divide into these classes (of course, I haven’t listed all of them here, just the common ones).

Create and copy objects

  • Object.create() : Creates a new Object based on a collection of stereotypes and property descriptors.

  • Object.assign() : Merges multiple objects, affecting the source objects. So to avoid this problem when merging objects, we do this:

var mergedObj = Object.assign({}, a, b);
Copy the code

Attributes related to

  • Object.defineproperty: Defines or modifiers the properties of an Object using the property descriptors. These properties include value, signals, writable, and Enumerable.

  • Object.defineproperties: An updated version of defineProperty that defines or modifies multiple properties at once.

  • Object. GetOwnPropertyDescriptor: obtaining property descriptors, is an Object that contains value, configurable, writable, enumerable four characteristics.

  • Object. GetOwnPropertyNames: returns a specified by the Object of all its attributes of the attribute name (including not enumerated attribute but does not include Symbol value as the name of the attribute) consisting of an array.

  • Object.keys: returns an array of enumerable properties of a given Object. The difference between getOwnPropertyNames and keys is that keys returns only enumerable properties that are true, and returns properties on the prototype Object.

The stereotype

  • Object.getPrototypeOf: returns the prototype of the specified object.
function Child() {}
var child = new Child();
Object.getPrototypeOf(child) === Child.prototype; // true
Copy the code
  • Object.setPrototypeOf: Sets the prototype of the specified object. This is a dangerous action, but also a poor performance method, not recommended.

Behavior control

The three ways listed below are a progressive relationship. Let’s look at them in order:

  • Object.preventExtensions: Make an Object nonextensible, i.e. no new properties can be added.

  • Object.seal: Seals an Object, preventing the addition of new properties and marking all existing properties as non-configurable. The object. seal, based on Object. PreventExtensions, sets the information of the Object to false.

The problem is that you can change the writable property of a new property that is freely set to false from true to false, although it runs without any additional feature or Enumerable.

  • Object.freeze: Freezes an object. Properties cannot be added, modified, deleted, or prototyped. There’s also a deep freezedeepFreezeIt’s kind of like deep copy, recursive freeze.

Detection capability

  • Object. IsExtensible: checks whether an Object isExtensible.

  • Object.isSealed: checks whether the Object isSealed.

  • Object. IsFrozen: checks whether an Object isFrozen.

Compatibility is poor

  • Object.entries

  • Object.values

  • Object.fromEntries

Prototype method

A stereotype method is a method that is mounted on a stereotype object and can be called through an instance, essentially with the help of a stereotype object. Such as:

function Child() {}
Child.prototype.protoMethod = function() { console.log("I'm a prototype method.")}var child = new Child();
child.protoMethod(); // "I am a prototype method"
Copy the code

ECMAScript defines a number of prototype methods for objects.

hasOwnProperty

This method returns a Boolean value indicating whether the object itself has a specified property (that is, whether it has a specified key), often accompanied by for… The in statement is used to traverse the enumerable properties of the object itself.

isPrototypeOf

This method tests whether an object exists on another object’s prototype chain. Object. The prototype. IsPrototypeOf with Object. GetPrototypeOf difference lies in:

  • Object. The prototype. IsPrototypeOf judgment is the prototype chain relations, and returns a Boolean value.

  • Object.getPrototypeOf is a direct prototype of the target Object, returning the prototypeobject of the target Object

PropertyIsEnumerable

This method returns a Boolean value indicating whether the specified property is enumerable. It checks for the Enumerable property of the object property.

valueOf & toString

Object to the original value of the method will be used, previously wrote a note, see the js data type is very simple, but not simple.

toLocaleString

The toLocaleString method returns a string representation of the object. This method is used when derived objects are overridden for location-specific purposes. Often seen with date objects.

The last

By reading this article, readers should have a basic understanding of Javascript objects. Objects are a very complex part of Javascript, which cannot be included in a note or a mind map. Many details are not easy to develop. You can follow my message exchange and reply “Mind map” to get my mind map.