JS: closure

Enjoy 2021-05-04 11:04:36
js closure


Closure

2021/5/3

One . What is a closure ?

  • A function and its surrounding states (lexical environment, Lexical environment ) The references of the ( Or functions are surrounded by references ), Such a combination is Closure closure).
  • Closures allow you to access the scope of an outer function in an inner function .
  • stay JavaScript in , Every time you create a function , Closures are created at the same time as functions are created .

Two . Lexical scope

  • function init() {
    var name = "Mozilla"; // name Is a init function Local variables created
    function displayName() { // displayName() Is an internal function , A closure
    alert(name); // Variables declared in the parent function are used
    }
    displayName();
    }
    init();
     Copy code 
    • displayName() Is defined in init() Internal functions in , And only in init() Functions are available in the body .
    • Because it can access variables of external functions , therefore displayName() You can use the parent function init() Variables declared in name .
  • This Lexical scope This example describes how the analyzer resolves variable names in the case of nested functions .

  • morphology (lexical) The word means , Lexical scope determines where a variable is available based on the location of the declared variable in the source code .

  • Nested function Access variables declared in their external scope .

3、 ... and . Closure

  • function makeFunc() {
    var name = "Mozilla";
    function displayName() {
    alert(name);
    }
    return displayName;
    }
    var myFunc = makeFunc();
    myFunc();
     Copy code 
    • Internal function displayName() Before implementation , From an external function . But the effect of running this code is the same as before init() The example of the function is exactly the same .
    • The reason lies in ,JavaScript Functions in form closures .
    • Closure Is a combination of a function and the Lexical Environment in which it is declared . The environment contains any local variables in the scope of the closure when it was created .
    • In this case ,myFunc Is to perform makeFunc Created when displayName References to function instances .
    • displayName The instance of maintains a lexical environment for it ( Variable name It's in it ) References to .
    • therefore , When myFunc When called , Variable name Still available .
  • function makeAdder(x) {
    return function(y) {
    return x + y;
    };
    }
    var add5 = makeAdder(5);
    var add10 = makeAdder(10);
    console.log(add5(2)); // 7
    console.log(add10(2)); // 12
     Copy code 
    • makeAdder It's a function factory
    • add5 and add10 All are closures. .
    • They share the same function definition , But different lexical environments are preserved .

Four . Closure practice

1. Switch page font size

  • function makeSizer(size) {
    return function() {
    document.body.style.fontSize = size + 'px';
    };
    }
    // Call the following different examples , You can switch the page font size
    var size12 = makeSizer(12);
    var size14 = makeSizer(14);
    var size16 = makeSizer(16);
     Copy code 

2. Simulate private methods

  • Private methods are not just good for limiting access to code : It also provides a powerful ability to manage global namespaces , Avoid non core methods messing up the common interface part of the code .

  • JavaScript There is no native support for declaring methods private API

  • But we can use closures to simulate private methods .

  • var Counter = (function() {
    var privateCounter = 0;
    function changeBy(val) {
    privateCounter += val;
    }
    return {
    increment: function() {
    changeBy(1);
    },
    decrement: function() {
    changeBy(-1);
    },
    value: function() {
    return privateCounter;
    }
    }
    })();
    console.log(Counter.value()); /* logs 0 */
    Counter.increment();
    Counter.increment();
    console.log(Counter.value()); /* logs 2 */
    Counter.decrement();
    console.log(Counter.value()); /* logs 1 */
     Copy code 
    • This example only creates a lexical environment , Shared by three functions .
    • The shared environment contains two private items , Neither of these can be accessed directly outside this anonymous function . Must be accessed through three public functions returned by anonymous functions .
    • These three common functions are closures that share the same environment ,JavaScript The lexical scope of makes them all accessible privateCounter Variables and changeBy function .
Change it
  • Change the anonymous immediate function to a normal anonymous function and assign it to a variable

  • var makeCounter = function() {
    var privateCounter = 0;
    function changeBy(val) {
    privateCounter += val;
    }
    return {
    increment: function() {
    changeBy(1);
    },
    decrement: function() {
    changeBy(-1);
    },
    value: function() {
    return privateCounter;
    }
    }
    };
    // Create two instance references , Generate two independent lexical environments
    // Each closure refers to a variable in its lexical scope .
    // Modifications to variables within a closure , Will change the lexical environment of this closure , But it doesn't affect the variables in the other closure .
    var Counter1 = makeCounter();
    var Counter2 = makeCounter();
    console.log(Counter1.value()); /* logs 0 */
    Counter1.increment();
    Counter1.increment();
    console.log(Counter1.value()); /* logs 2 */
    Counter1.decrement();
    console.log(Counter1.value()); /* logs 1 */
    console.log(Counter2.value()); /* logs 0 */
     Copy code 

3. solve for loop var The problem of variable Promotion

explain for loop
  • for The loop creates a block every time it loops , also for The cycle is a very short time and the cycle ends
  • and var The created variable does not have a block level scope , There's also variable Promotion
  • So at the end of the day, all of the blocks var The value of the declared variable becomes the latest value because the variable is promoted
Example
  • <p id="help">Helpful notes will appear here</p>
    <input type="text" id="email" name="email">
    <input type="text" id="name" name="name">
    <input type="text" id="age" name="age">
    -------------------------------------------------------------------------------------
    function showHelp(help) {
    document.getElementById('help').innerHTML = help;
    }
    function setupHelp() {
    var helpText = [
    {'id': 'email', 'help': 'Your e-mail address'},
    {'id': 'name', 'help': 'Your full name'},
    {'id': 'age', 'help': 'Your age (you must be over 16)'}
    ];
    for (var i = 0; i < helpText.length; i++) {
    var item = helpText[i];
    document.getElementById(item.id).onfocus = function() {
    showHelp(item.help);
    }
    }
    }
    setupHelp();
     Copy code 
    • Assign a value to onfocus It's a closure . These closures are defined by their functions and in the setupHelp Of the environment captured in the scope .
    • These three closures are created in the loop , But they share the same lexical scope , There is a variable in this scope item.
    • This is because of variables item Use var Make a statement , Due to variable Promotion , So it has function scope .
    • When onfocus When the callback is executed , The variable object item( Shared by three closures ) It has pointed to helpText The last item of .
Solution
1. Use more closures
  • function showHelp(help) {
    document.getElementById('help').innerHTML = help;
    }
    function makeHelpCallback(help) {
    return function() {
    showHelp(help);
    };
    }
    function setupHelp() {
    var helpText = [
    {'id': 'email', 'help': 'Your e-mail address'},
    {'id': 'name', 'help': 'Your full name'},
    {'id': 'age', 'help': 'Your age (you must be over 16)'}
    ];
    for (var i = 0; i < helpText.length; i++) {
    var item = helpText[i];
    document.getElementById(item.id).onfocus = makeHelpCallback(item.help);
    }
    }
    setupHelp();
     Copy code 
  • Using factory functions makeHelpCallback Create a new lexical environment for each callback .

  • All callbacks no longer share the same environment , In these environments ,help Point to helpText The corresponding string in the array .

2. Using anonymous closures
  • function showHelp(help) {
    document.getElementById('help').innerHTML = help;
    }
    function setupHelp() {
    var helpText = [
    {'id': 'email', 'help': 'Your e-mail address'},
    {'id': 'name', 'help': 'Your full name'},
    {'id': 'age', 'help': 'Your age (you must be over 16)'}
    ];
    for (var i = 0; i < helpText.length; i++) {
    (function() {
    var item = helpText[i];
    document.getElementById(item.id).onfocus = function() {
    showHelp(item.help);
    }
    })(); // Now, let's take the item Associated with event callbacks
    }
    }
    setupHelp();
     Copy code 
3. Use let keyword
  •  for (var i = 0; i < helpText.length; i++) {
    let item = helpText[i];// Use let instead of var, So each closure is bound to a block scoped variable , This means that no additional closures are needed
    document.getElementById(item.id).onfocus = function() {
    showHelp(item.help);
    }
    }
     Copy code 
4. Use forEach() To traverse helpText Array
  •  helpText.forEach(function(text) {
    document.getElementById(text.id).onfocus = function() {
    showHelp(text.help);
    }
    });
     Copy code 

5、 ... and . Performance considerations

  • If you don't need closures for certain tasks , It's unwise to create functions in other functions , Because closures have a negative impact on script performance in terms of processing speed and memory consumption .

  • When creating a new object or class , Methods should usually be associated with the prototype of the object , Not defined in the constructor of the object .

  • The reason is that this will cause every time the constructor is called , Methods are all reassigned once ( in other words , For the creation of each object , Methods are reassigned ).

  • function MyObject(name, message) {
    this.name = name.toString();
    this.message = message.toString();
    }
    MyObject.prototype.getName = function() {
    return this.name;
    };
    MyObject.prototype.getMessage = function() {
    return this.message;
    };
     Copy code 
版权声明
本文为[Enjoy]所创,转载请带上原文链接,感谢
https://qdmana.com/2021/05/20210504110147485s.html

  1. JS: event flow
  2. Front end performance optimization: rearrangement and redrawing
  3. JS - deep and shallow copy
  4. JavaScript异步编程3——Promise的链式使用
  5. JavaScript asynchronous programming 3 -- chain use of promise
  6. Vue.js组件的使用
  7. The use of vue.js component
  8. How to judge whether a linked list has links
  9. Element UI custom theme configuration
  10. Text image parallax effect HTML + CSS + JS
  11. Spring的nohttp宣言:消灭http://
  12. Vue3 intermediate guide - composition API
  13. Analysis of URL
  14. These 10 widgets that every developer must know
  15. Spring's nohttp Manifesto: eliminate http://
  16. Learn more about JS prototypes
  17. Refer to await to JS to write an await error handling
  18. A short article will directly let you understand what the event loop mechanism is
  19. Vue3 uses mitt for component communication
  20. Characteristics and thinking of ES6 symbol
  21. Two way linked list: I'm no longer one-way driving
  22. Vue event and form processing
  23. Reactive TraderCloud实时外汇开源交易平台
  24. Reactive tradercloud real time foreign exchange open source trading platform
  25. Node.js REST API的10个最佳实践
  26. Ten best practices of node.js rest API
  27. Fiddler advanced usage
  28. Process from Vue template to render
  29. Promise up (asynchronous or synchronous)
  30. Principle and implementation of promise
  31. Vs code plug in sharing - run code
  32. Vue practical notes (1) introduction of Ant Design
  33. Vue actual combat notes (2) introduction of element plus
  34. Introduction to webpack
  35. Webpack construction process
  36. Vue notes
  37. The experience and lessons of moving from ruby megalith architecture to go microservice
  38. Using leancloud to add artitalk module to hexo blog
  39. Implementation of chrome request filtering extension
  40. Detailed introduction of beer import declaration elements and label quarantine [import knowledge]
  41. Gallop workflow engine design series 01 process element design
  42. VUE移动端音乐APP学习【十六】:播放器歌词显示开发
  43. Vue Mobile Music App learning [16]: player lyrics display development
  44. jquery cookie
  45. jquery cookie
  46. 体面编码之JavaScript
  47. JavaScript for decent coding
  48. React17 系统精讲 结合TS打造旅游电商平台
  49. React17 system combined with TS to build tourism e-commerce platform
  50. 2021-05-04 hot news
  51. HttpSession对象与Cooike的关系 以及 Cookie对象构造函数问题
  52. gRPC-Web:替代REST的gRPC的Javascript库包
  53. The relationship between httpsession object and cooike and the construction of cookie object
  54. Grpc Web: a JavaScript library package to replace rest grpc
  55. Building reactive rest API with Java - kalpa Senanayake
  56. PDF转HTML工具——用springboot包装pdf2htmlEX命令行工具
  57. Pdf to HTML tool -- Wrapping pdf2htmlex command line tool with springboot
  58. PDF转HTML工具——用springboot包装pdf2htmlEX命令行工具
  59. Pdf to HTML tool -- Wrapping pdf2htmlex command line tool with springboot
  60. Vue.js比jQuery更容易学习