Deep foundation of JS (prototype, call, wrapper class, closure)

In depth JS Foundation

prototype

prototype

Definition: the prototype is an attribute of the function object, which defines the common ancestor of the object created by the constructor. The object generated by the constructor can inherit the properties and methods of the prototype. Prototypes are also objects.
Is the father of the function. You can set properties to the function

  • Each function has a prototype attribute, which points to an object null object (i.e. prototype object) by default.
  • There is a property constructor in the prototype object, which points to the function object

Implicit prototype__ proto__

Object__ proto__ Attribute: automatically added when creating an object. Internal code. The default value (pointing value) is the prototype of the constructor

Person.prototype.name = "sunny";
function Person(){
	//var this = {__proto__:Person.prototype}
}
var person = new Person();
Person.prototype = {
	name : "cherry"
}

console.log(person.name);
//Note that the result here is "sunny" instead of "cherry"
/*Because when new an object, the function is executed, and the default value in the function is__ proto__ Point to prototype
 Next, execute person prototype={name:"cherry"}
Here is only to modify the value of prototype, but__ proto__ It has already been defined in the function to point to sunny*/


Can be understood as prototype and__ proto__ There are different

Connection between the two

Explicit and implicit are displayed in functions in different objects and implicit in objects, but they can be called by pointing to the same address. This is the principle of calling function methods.

        //Constructor
        function Fn(){

        }
        //1. Each function has a prototype, which points to an empty object by default
        console.log(Fn.prototype);

        //2. Each instance object has one__ proto__,

        // Create instance object
        var fn = new Fn();// this.__proto__ = Fn.prototype

        // The value of the implicit prototype of an object is the value of the explicit prototype of its corresponding constructor
        console.log(Fn.prototype === fn.__proto__);//true

        // Add method to prototype
        Fn.prototype.text = function () {
            console.log('1');
        }

        // Call the method of the prototype through an instance
        fn.text();

Prototype chain

The prototype is connected with the previous prototype, and the terminal is finally found

  //Access object prototype.__ proto__ Get null, indicating that this is the terminal
  Grand.prototype.lastName = "Deng";
  function Grand(){
  		this.name = "daming";
  }
  var grand = new Grand();
  
  Father.prototype = grand;//grand is the prototype of the constructor Father
  function Father(){
  	this.name = "xiaoming";
  }
  var father = new Father();

  function Son(){
  	this.name = "xiaoxiaoming";
  }
  Son.prototype = father;//father is the prototype of the constructor Son
  var son = new Son();
  console.log(son.lastName);
  /*This is accessed through the prototype chain, son-->son.__proto__(Namely father)
  -->father.__proto__(Namely grand)-->grand.__proto__,lastName

call/apply

Function: change the direction of this

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

    var person = new Person('c',100);
    var obj = {
    }
    Person.call(obj,'jc',90)
     // Obj is also passed into person, and this = obj, which means borrowing other people's methods to generate attributes. Does not affect the original function, person or w 100
    console.log(obj);

//Borrow other people's functions to realize their own functions
function Person(name,age,sex){
	this.name = name;
	this.age = age;
	this.sex = sex;
}
function Student(name,age,sex,tel,grade){
	Person.call(this,name,age,sex);	
	this.tel = tel;
	this.grade = grade;
}

closure

About closure

Generally speaking, local variables only act on local variables, and local variables inside the function cannot be read outside the function. Sometimes local variables inside a function are needed, and a workaround method is needed, that is, another function is defined inside the function

    function f1(){
          var n=999;
        function f2(){
          alert(n); // 999
        }
      }

In the above code, function f2 is included in function f1. At this time, all local variables in f1 are visible to f2.

But not the other way around. The local variables inside f2 are invisible to f1. This is the unique "chained scope" structure of JavaScript language.

Since f2 can read the local variables in f1, we can read its internal variables outside f1 as long as f2 is taken as the return value.

At this time, function f2 is a closure, which can be understood as a bridge between the inside and outside of the function.

In essence, a closure is a function inside a function. By returning the child function and calling it externally, the local variables of the parent function are activated, that is, the stack area where the function is located is still retained.

For the well-known mainstream languages, such as C and java, as long as return is executed inside the function, the function will return the result, and then delete the area where the function is located in memory. The life cycle stops. The same is true for general js functions.

However, js functions with closure feature are a little special. After return, although the f1 function is cleared, f2 is returned and retained. The stack area of f1 and f2 in memory, that is, local variables, will be retained. The stack area can be continuously modified externally and will be retained because f2 always exists. This creates a closure.

be careful:
  • Closures are generated when internal functions are saved externally. Closure will cause the original scope chain not to be released, resulting in memory leakage. A leak is when memory is consumed.
  • Closure will change the value of the internal variable of the parent function outside the parent function. Therefore, if you use the parent function as an object, the closure as its Public Method, and the internal variable as its private value, you must be careful not to change the value of the internal variable of the parent function.
Execute function now

This kind of function is not declared and is released after one execution. It is suitable for initialization.

  (function(a,b,c){
          console.log(a+b+c);
      }(1,2,3))

effect

  1. Public variable implementation
      //Function accumulator
       function add(){
            var count = 0;
            function demo(){
                count ++ ;
                console.log(count);
            }
            return demo;
       }
 
       var counter = add();
       counter();
       counter();
       counter();
       counter();

  1. Can be used as cache (storage structure)
// 1.
      function test(){
          var num = 100
          function a(){
              num ++
              console.log(num);
          }
          function b(){
            num --
              console.log(num);
          }
          return [a,b]
      }

      var myArr = test();
      myArr[0]();//101
      myArr[1]();//100

 // 2.
      function eater(){
          var food = "apple"
          var obj = {
              eat :function(){
                  console.log('eating'+ food);
                  food = ""
              },
              push : function(myfood){
                  food = myfood;
              }
          }
          return obj
      }

      var eater1 = eater()
      eater1.push('banana')
      eater1.eat();

// Eliminate the impact of closures

// Purpose: output 1-10
      function test(){
          var arr = []
          for(var i = 0;i<10;i++){
              arr[i] = function(){
                  console.log(i);
              }
          }
          return arr;
      }
    //   The stack created by array arr is unique. i has become 10 in the loop, and the stack corresponding to the subset is also the same, forming one
    //   For the case of ten, that is, 10 objects in a space are used together, so it will be the last to change the value of the stack
    
      var myArr = test()
      for(var j = 0;i<10;j++){
          myArr[j]();
          //Output 10 10
      }

// Solution 👇
      function test(){
          var arr = []
          for(var i = 0;i<10;i++){
              (function(j){
                  arr[j] = function(){
                  console.log(j);
               } 
              }(i))
          }
          return arr;
      }
      // Turn each memory into an immediate execution function, constantly update the incoming parameters, and destroy them after use. There is no cumulative cache problem, and it becomes one-to-one
  1. Encapsulation and property privatization can be realized (supplemented later)

  2. Model development to prevent pollution of global variables (later supplement)

Packaging

Give the original value a new attribute without reporting an error, but the result is undefined or null. The reason is that the computer has done a process of wrapping classes

var num = 4;
num.len = 3;
/*Implicitly, the following process occurs to make up for your shortcomings:
new Number(4).len=3
 That is, first create a digital object to store the original value, and then add an attribute len=3; But the next step after execution is to destroy the delete
*/
console.log(num.len);
//This is to access num.len, so new number (4) occurs again Len, but the len here is different from the above. It is undefined


      var str = 'abc'
      str +=1
      var test = typeof(str);//test = 'string'
      if(test.length == 6){
          test.sign = '123'
      }
      console.log(test.sign);
      //Print out undefined

Keywords: Front-end

Added by jeffkee on Mon, 07 Mar 2022 16:19:52 +0200