Several hook functions of custom instructions, js loop mechanism

  • Several hook functions for custom directives

  • bind : Called only once, when the directive is bound to the element for the first time. One-time initialization settings can be performed here.

  • inserted : Called when the bound element is inserted into the parent node (only the parent node is guaranteed to exist, but not necessarily inserted into the document).

  • update : Called when the component's VNode is updated, but it may happen before its child VNode is updated. The value of the directive may or may not have changed. But you can ignore unnecessary template updates by comparing the values ​​before and after the update.

  • componentUpdated : Called after the VNode of the component where the command is located and its child VNodes are all updated.

  • unbind : Called only once, when the directive is unbound from the element.

The loop mechanism of js

1. What is a circular reference

When a certain attribute in object 1 points to object 2, and a certain attribute in object 2 points to object 1, a circular reference will occur. (Of course there is more than this one situation, but the principle is the same.) The code and memory diagram are shown below to illustrate one time.

function circularReference() {
  let obj1 = {};
  let obj2 = {
    b: obj1
  };
  obj1.a = obj2;
}

2. Problems with reference counting garbage collection strategy in JS

Let me briefly talk about the general principle of the reference garbage collection strategy in JS. When a variable is assigned a value of a reference type, the reference count of the value of this reference type is increased by 1. Just like the variable obj1 in the code is assigned the address of the object obj1, the variable obj1 points to the object obj1 (upper right), and the reference count of obj1 (upper right) will increase by 1. When the value of the variable obj1 is not When it is the address of the obj1 (upper right) object, the reference count of the obj1 (upper right) object will be reduced by 1. When the reference count of the obj1 (upper right) object becomes 0, the garbage collector will recycle it. Because there is no variable pointing to you at this time, there is no way to use you.

Why is there a problem with the seemingly reasonable garbage collection strategy?

It is caused by the circular reference mentioned above, let's analyze it below. When the obj1 variable executes the obj1 object, the reference count of the obj1 object will increase by 1. At this time, the reference count value is 1, and then the b attribute of obj2 points to the obj1 object, so the reference count of the obj1 object at this time for 2. Similarly, the reference count of the obj2 object is also 2.

When the code is executed, the variables obj1 and obj2 will be assigned as null, but at this time the reference counts of the two objects obj1 and obj2 are 1, not 0, so garbage collection will not be performed, but these two The objects are useless, and it is impossible to use them outside the function, so this causes a memory leak.

The above problems will not appear in the widely used mark-and-sweep recycling strategy. The general flow of the mark-and-sweep recycling strategy is as follows. At the beginning, all variables are marked, and when the circularReference function is executed, the function will be These tags are cleared for internal variables, and the tags are added after the function is executed. These variables that are cleared and marked are considered variables to be deleted because the variables in these functions are no longer accessible. The two variables like obj1 and obj2 in the above code are marked at the beginning, they are cleared after entering the function, and then marked as variables to be cleared after the function is executed, so there will be no reference counting The problem arises in , because mark-sweeping doesn't care how many references it has.

3. Why does JSON.stringify report an error for circularly referenced objects?

JSON.stringify is used to serialize a JS object into a JSON string. Suppose now we want to serialize the obj1 object into a JSON string. Now let's print out the obj1 object to have a look.

function circularReference() {
  let obj1 = {};
  let obj2 = {
   b: obj1
  };
  obj1.a = obj2;
  console.log(obj1);
}
circularReference();

The result looks like this:

The obj1 object and obj2 will refer to each other infinitely, and JSON.tostringify cannot serialize an infinitely referenced object into a JSON string.

Here's how MDN explains it:

JSON.stringify() converts the value to the corresponding JSON format:
if the converted value has a toJSON() method, this method defines what value will be serialized.
Properties of non-array objects are not guaranteed to appear in a particular order in the serialized string.
Wrapper objects of Boolean values, numbers, and strings are automatically converted to corresponding primitive values ​​during serialization.
undefined, any function and symbol value, will be ignored (appear in the attribute value of non-array object) or be converted to null (appear in the array) during the serialization process. When functions and undefined are converted separately, undefined will be returned, such as JSON.stringify(function(){}) or JSON.stringify(undefined).
Execute this for objects containing circular references (objects refer to each other to form an infinite loop) method, an error will be thrown.
All properties keyed with symbol are completely ignored, even if they are mandatory to include in the replacer parameter.
Date calls toJSON() to convert it to a string string (same as Date.toISOString()), so it will be treated as a string.
Numeric values ​​in NaN and Infinity formats and null will be treated as null.
Other types of objects, including Map/Set/WeakMap/WeakSet, will only serialize enumerable properties.

We can see from the bold font that executing JSON.stringify on an object that contains a circular reference will throw an error.

Solution

A natural idea can eliminate circular references, a JSON extension package has done this, using JSON.decycle can remove circular references. For the convenience of testing, I directly downloaded the cycle.js function from the Github warehouse of the JSON extension package, assigned the following code to the bottom, and then used node to run the test. The problem was solved, and the result is shown in the figure below.

function circularReference() {
 
  let obj1 = {};
  let obj2 = {
    b: obj1
  };
  obj1.a = obj2;
  let c = JSON.decycle(obj1);
  console.log(JSON.stringify(c));
}
circularReference();

operation result:

Guess you like

Origin blog.csdn.net/wangshuaibinggg/article/details/129070276