What are closures? The role of closure? Application scenarios of closures? Lazy functions Higher-order functions

The concept of closure

Closure is such a mechanism: functions nest functions, and inner functions can refer to parameters and variables of outer functions. Parameters and variables are not 垃圾回收机制evicted.

What are closures?

  • A closure is a function that has access to variables in the scope of another function. The most common way to create a closure is to create another function inside a function and access the local variables of this function through another function.
  • An airtight container, similar to a set/map container, used to store data
  • A closure is an object that stores data in the format: key:value

Conditions for closure formation*

  • 1. Function nesting

  • 2. Internal functions refer to external functions

    function fun(){
          
          
        var count = 1;
        function fun2(){
          
          //条件1:函数嵌套
        //形成条件2:内部函数引用外部函数
        console.log(count);
        }
    }
    fun();
    

Why use closures?

Closures can be used to break through the scope of the chain and pass local variables inside .

garbage collection mechanism

1. Mark Clear

Mark clear : js will mark the variable with a yes or no label for the js engine to process. When the variable is used in a certain environment, it will be marked as yes. When it exceeds the environment (which can be understood as out of scope), it will be marked is no, and then release the tags with no.

2. Reference counting

Reference counting : For variables of reference type in js, the memory recycling mechanism of reference counting is adopted. When a variable of reference type is assigned to another variable, the reference count will be +1, and when one of the variables is no longer equal to the value, The reference count will be -1, if the reference count is 0, the js engine will release it.

scope

global scope

Scopes not outside function inner scopes and block-level inner scopes

function scope

scope inside a function

block scope

Scopes inside curly braces {},

Note :

① The {} of the object does not belong to the block-level scope, curly braces like for(){}, if(){}, else{}, try{}, cath(){}, etc. are block-level scope

②The scope of the {} of the object depends on the scope of the object. For example, if the object is defined under the global scope, then the scope of the {} of the object is the global scope

scope chain

When the inner scope accesses the variables of the outer scope, it adopts 链式查找the method to decide which value to take, and adopts the approach of the principle of proximity to find the value of the variable at the next level. The top level is the global scope. If you go to the global scope If the field does not find a value, then an error will be reported.

As long as it is code, there is at least one scope. If the scope still has a scope, then another scope can be born in this scope;

// 作用域链: 内部作用域访问外部作用域的变量,采取的是链式查找的方式来决定取哪个值,这种结构我们称为作用域链
let num = 10;
function fn() {
    
     //外部函数
     let num = 20;
     return function fun() {
    
     //内部函数
         console.log(num);
     }
}
const funn = fn()
funn() // 20 ,一级一级访问

The role of closure

  • Has the feature of not being released for global variables
  • Features that have local variables that cannot be accessed externally

characteristic:

Nested functions within functions Internal functions can refer to outer parameters and variables Parameters and variables will not be recovered by the garbage collection mechanism

advantage

  • Extend the life cycle of local variables of external functions, so that a variable will not be released in memory for a long time
  • Avoid pollution of global variables. Unlike global variables, variables in closures cannot be used externally
  • The existence of private members cannot be called externally, but can only be called directly internally

harm

  • It is the problem of memory consumption and improper use that will cause memory overflow

Functions that closures can complete

Execute the function immediately

const a = 666;

(function getA(){
    
    
    console.log(a);
})()

Simulate block-level scope

for(var i = 0; i < 5; i++) {
    
    
    (function (j) {
    
    
        setTimeout(() => {
    
    
            console.log(j);
        },1000)
    })(i)
}

Encapsulate private variables

function Person(name) {
    
    
    this.getName = function(){
    
    
        return name
    }
}

anti shake

Continuously triggering does not execute, and executes after a period of time after not triggering

**Principle**Since you don’t want to print the previously entered results, clear the previously triggered timer. We should store the variable of this timer in memory (memory leak) [closure]

//防抖 避免函数的重复调用 只会调用一次
function Antishake(fn,wait){
    
     //第一个参数是函数 第二个参数是毫秒值
     let timer = null //声明一个变量来接收延时器 初始值为null
     return function(){
    
    
         clearTimeout(timer)
          timer = setTimeout(() => {
    
    
              fn() //调用这函数
           }, wait);
      }
}
let an = Antishake(function(){
    
     //用一个变量接收
    console.log('555');
   },2000)
  document.querySelector('div').onmouseenter = ()=>{
    
    
     an() //调用一次
  }

throttling

Continuous triggering is also executed, only once in a period of time

**Principle** When an event is triggered, we set a timer. When the event is triggered again, if the timer exists, it will not be executed. After the delay time, the timer executes the execution function and clears the timer, so that The next timer can be set.

function throttle(fn, wait) {
    
    
  let timer = null; //节点闸
  return function () {
    
    
    if (timer) return; //null false 不是null结果减少true 如果上传没有我就直接跳过 没有人我就上去
    timer = setTimeout(() => {
    
    
      //上车了
      fn();
      timer = null; //做完之后重新关闭节点闸
    }, wait);
  };
}
let throttleFn = throttle(() => {
    
    
  console.log("我上车了");
}, 2000);
document.querySelector("div").onclick = () => {
    
    
  throttleFn();
};

function currying

In fact, it is the granulation of functions, turning a function into individual particles that can be assembled, that is, the multiple parameters in it turn it into individual functions to pass this parameter.

let add = (a, b) => a + b
console.log(add(2, 3));
// 函数柯里化
let currying = (a) => (b) => a + b
console.log(currying(2)(3));

Which methods of arrays use closures?

forEach

const arr = [1,2,3];

arr.forEach((item,index) => {
    
    
    setTimeout(() => {
    
    
        console.log(item);
    },1000)
})

Commonly used higher-order functions in js

condition :

  1. accepts one or more functions as input
  2. output a function

**Higher-order function:** Refers to a function that accepts a function as an argument or returns a function. This kind of function allows you to implement some advanced tricks in JavaScript, such as using functions as the basic unit of data processing.

  • map: Operates on each element in the array and returns a new array.

  • filter: Filters the elements in the array and returns a new array.

  • reduce: Iterates over all elements in an array, reducing them to a single value.

  • sort: Sort the elements in the array.

  • forEach: Performs an operation on each element in the array.

  • some: Checks if at least one element in the array matches a certain condition.

  • every: Checks whether all elements in the array meet a certain condition.

filter

Function : Create a new array, and the elements in the new array are checked by checking all the elements in the specified array that meet the conditions.
Syntax : array.filter (function (currentValue, index, arr), thisValue)
return value : a new array of qualified elements

let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let newNums = nums.filter((item, index, arr) => {
    
    
  return item % 2 === 0;
});
console.log(newNums); // [ 2, 4, 6, 8, 10 ]
console.log(nums); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

map

Function : return a new array, and the elements in the array are the values ​​processed by calling the function of the original array elements.
Syntax : array.map(function(currentValue,index,arr), thisValue)
Return value : a new array

let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let newNums = nums.map((item, index, arr) => {
    
    
  return item * 2;
});
console.log(newNums);
// [2,  4,  6,  8, 10, 12, 14, 16, 18, 20]

reduce

Function : statistics, accumulation
Syntax : array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
   total: required. The initial value, or the return value currentValue after completion
   : required. Current element
   currentIndex: optional, current element index
   arr: optional, the array object to which the current element belongs
   initialValue: optional, the initial value passed to the function
return value : cumulative result

let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let newNums = nums.reduce((total, item, index, arr) => {
    
    
  return total + item;
});
console.log(newNums); //55

find

Function : The method returns the value of the first element of the array that passes the test (in-function judgment).
Syntax : array.find(function(currentValue, index, arr), thisValue)
Return value : Returns the first array element value that meets the test conditions, and returns undefined if there is no one that meets the conditions.

let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let newNums = nums.find((item, index, arr) => {
    
    
  return item === 3;
});
console.log(newNums); // 3

findIndex

Similar to find, the return value is the index value of the first eligible element

let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let newNums = nums.findIndex((item, index, arr) => {
    
    
  return item === 3;
});
console.log(newNums); // 2

lazy function

Lazy Function (Lazy Function) : A lazy function means that the branch of function execution will only be executed when the function is called for the first time. During the first call, the function will be overwritten with another function that is executed in an appropriate way, so that Any call to the original function does not need to go through the execution branch.

The essence of lazy functions is function rewriting. The so-called lazy loading means that the branch of function execution will only happen once. So when is the function rewritten? Since a function can return another function, it is possible to overwrite an old function with a new one.

function a() {
    
    
    console.log('a');
     a = function () {
    
    
                console.log('b');
      }
}
a(); //q
a(); //b

When this function is called for the first time, console.log('a') will be executed, and a will be printed out. The global variable a will be redefined and given a new function. When it is called again, console.log('b' ) is executed.

Usefulness: Because of the behavioral differences between browsers, a large number of if statements are often included in the function to check browser characteristics and solve compatibility problems with different browsers.

There are two ways to implement lazy functions :

  • When the function is called, the function is processed. When a function is called for the first time, the function will be overwritten with another function that is executed in a suitable way, so that any call to the original function does not need to go through the execution branch
  • The appropriate function is specified when the function is declared.

The chicken-and-egg problem of Object and Function

Reference: https://muyiy.cn/blog/5/5.3.html#%E5%BC%95%E8%A8%80

Object(), String()and other constructors are not really created by the original constructor Function(). Essentially, they are all JavaScriptimplemented by the underlying layer, because these constructors __proto__all point to the constructor Function.prototype;

Object.prototype

Object.prototype represents the prototype object of Object, its [[Prototype]]property is null, and the accessor property __proto__exposes the interior of an object [[Prototype]]. ObjectObject.prototype is not created through the function, why? Look at the following code

function Foo() {
    
    
  this.value = 'foo';
}
let f = new Foo();
f.__proto__ === Foo.prototype;
// true

The of the instance object __proto__points to the constructor prototype, that is, f.__proto__points to Foo.prototype, but Object.prototype.__proto__is null, so Object.prototype is not created through the Object function, so how is it generated? In fact, Object.prototype is an object created by the bottom layer of the browser according to the ECMAScript specification.

Object.prototype is the top of the prototype chain (without considering null), all objects inherit its toString and other methods and properties.

Function.prototype

The Function.prototype object is a function (object), whose [[Prototype]]internal property values ​​point to the built-in object Object.prototype. The Function.prototype object itself has no valueOfproperty, and it inherits valueOfthe property from the Object.prototype object.

The Function.prototype [[Class]]property is Function, so this is a function, but not quite the same. Why do you say that? Because we know that only functions have the prototype attribute, but not all functions have this attribute, because the Function.prototype function does not.

Why not? My understanding is Function.prototypethat is a function created by the engine. The engine thinks that there is no need to add prototypeattributes to this function object, otherwise Function.prototype.prototype…it will be endless and meaningless.

function Object

When Object is used as a constructor, its [[Prototype]]internal property value points to Function.prototype, that is

bject.__proto__ === Function.prototype // true

function Function

The Function constructor is a function object whose [[Class]]property is Function. The Function [[Prototype]]property points to Function.prototype, that is,

Function.__proto__ === Function.prototype // true

Function & Object egg problem

Whether the instanceofprototype` 检查的是右操作数的property is on the prototype chain of the left operand .

Object instanceof Function 		// true
Function instanceof Object 		// true

Object instanceof Object 		// true
Function instanceof Function 	// true

ObjectConstructors inherit Function.prototype, while Functionconstructors inherit Object.prototype. Here a chicken and egg problem arises .

Why does this problem occur?

Because Function.prototypeboth and Function.__proto__point to Function.prototype.

3 Soul Tortures

Who is the instance of Object and Function

Objectyes Functioninstance

Function.prototype is a function?

Yes

Function.prototype()It can be executed without reporting an error, indicating that Function.prototypeit is really a function.

Guess you like

Origin blog.csdn.net/qq_37831545/article/details/129361948