search
HomeWeb Front-endJS TutorialWhat are the common scenarios in which closures can be exploited in JS? (Picture and text tutorial)

Scenario 1: Calling setTimeout using a function reference

A common usage of closures is to provide parameters for a function that is executed before a certain function is executed. For example, in a web environment, it is a very common application for a function to be used as the first parameter of the setTimeout function call.

setTimeout takes the function to be executed (or a piece of javascript code, but this is not what we are going to discuss) as its first parameter, and the next parameter is the time to delay execution. If a piece of code wants to be called via setTimeout, then it needs to pass a reference to the function object as the first parameter. The number of milliseconds to delay as the second parameter, but this function object reference cannot provide parameters for the object that will be delayed.

However, you can call another function that returns a call to an internal function, passing a reference to that internal function object to the setTimeout function. The parameters required when the internal function is executed are passed to it when calling the external function. setTimeout does not need to pass parameters when executing the internal function, because the internal function can still access the parameters provided when the external function is called:

function callLater(paramA, paramB, paramC) {  
            /*使用函数表达式创建并放回一个匿名内部函数的引用*/  
            return (function () {  
                /* 
                这个内部函数将被setTimeout函数执行; 
                并且当它被执行时, 
                它能够访问并操作外部函数传递过来的参数 
                */  
                paramA[paramB] = paramC;  
            });  
        }  
        /* 
        调用这个函数将在它的执行上下文中创建,并最终返回内部函数对象的引用 
        传递过来的参数,内部函数在最终被执行时,将使用外部函数的参数 
        返回的引用被赋予了一个变量 
        */  
        var funcRef = callLater(elStyle, "display", "none");  
        /*调用setTimeout函数,传递内部函数的引用作为第一个参数*/  
        hideMenu = setTimeout(funcRef, 500);

Scenario 2: Associating the function to the instance method of the object

There are many Scenario: You need to allocate a reference to a function object in order to execute the function at some time in the future. Then closures can be very helpful to provide a reference to the function that will be executed. Because the function may not be accessible until execution.

One example is that a JavaScript object is encapsulated to participate in the interaction of a specific DOM element. It has doOnClick, doMouseOver and doMouseOut methods. And want to execute these methods when the corresponding event on the DOM element is triggered. However, any number of JavaScript objects may be created associated with DOM elements, and individual instances have no idea what the code that instantiates them will do with them. Object instances do not know how to refer to themselves "globally" because they do not know which global variable (if any) a reference will be assigned to them.

So, the problem is to execute an event handler function associated with a specific JavaScript object instance, and know which method of that object to call.

The next example uses a simple closure on the associated function of an object instance with element event handling. Event handlers are assigned different object instance methods to call by passing the event object and a reference to the element to be associated.

/* 
        一个给对象实例关联一个事件处理器的普通方法, 
        返回的内部函数被作为事件的处理器, 
        对象实例被作为obj参数,对象上将要被调用的方法名称被作为第二个参数 
        */  
        function associateObjWithEvent(obj, methodName) {  
            /*返回的内部函数被用来作为一个DOM元素的事件处理器*/  
            return (function (e) {  
                /* 
                事件对象在DOM标准的浏览器中将被转换为e参数, 
                如果没有传递参数给事件处理内部函数,将统一处理成IE的事件对象 
                */  
                e = e || window.event;  
                /* 
                事件处理器调用obj对象上的以methodName字符串标识的方法 
                并传递两个对象:通用的事件对象,事件处理器被订阅的元素的引用 
                这里this参数能够使用,因为内部函数已经被执行作为事件处理器所在元素的一个方法 
                */  
                return obj[methodName](e, this);  
            });  
        }  
        /* 
        这个构造器函数,通过将元素的ID作为字符串参数传递进来, 
        来创建将自身关联到DOM元素上的对象, 
        对象实例想在对应的元素触发onclick、onmouseover、onmouseout事件时 
        对应的方法被调用。 
        */  
        function DhtmlObject(elementId) {  
            /* 
            调用一个方法来获得一个DOM元素的引用 
            如果没有找到,则为null 
            */  
            var el = getElementWith(elementId);  
            /* 
            因为if语句块,el变量的值在内部进行了类型转换,变成了boolean类型 
            所以当它指向一个对象,结果就为true,如果为null则为false 
            */  
            if (el) {  
                /* 
                为了给元素指定一个事件处理函数,调用了associateObjWithEvent函数, 
                利用它自己(this关键字)作为被调用方法的对象,并且提供方法名称 
                */  
                el.onclick = associateObjWithEvent(this, "doOnClick");  
                el.onmouseover = associateObjWithEvent(this, "doOnMouseOver");  
                el.onmouseout = associateObjWithEvent(this, "doOnMouseOut");  
            }  
        }  
        DhtmlObject.prototype.doOnClick = function (event, element) {  
            //doOnClick body  
        }  
        DhtmlObject.prototype.doMouseOver = function (event, element) {  
            //doMouseOver body  
        }  
        DhtmlObject.prototype.doMouseOut = function (event, element) {  
            //doMouseOut body  
        }

Any instance of DhtmlObject can associate themselves with the DOM elements they are interested in, without having to worry about how these elements will be processed by other code, "polluted" by the global namespace or related to the global namespace. Other instances of DhtmlObject conflict.

Scenario 3: Encapsulating related feature sets

Closures can create additional scopes, which can be used to combine related or dependent code. This way the hazards of code interference can be minimized. Suppose, a function is used to create a string and avoid repeated concatenation operations (such as creating a series of intermediate strings). One idea is to use an array to store parts of the string sequentially, and then use the Array.prototype.join method to output the result (using an empty string as its argument). The array will play the role of the output buffer, but defining it locally will cause it to be created again every time the function is executed. This would be a bit overkill if this array were just assigned as the only variable to every function call.

One solution is to promote the array to a global variable so that it can be used again without having to be created again. But the result is not as simple as you think. In addition, if a global variable is associated with the function that uses the buffer array, there will be a second global attribute (the function itself is also an attribute of the window object) associated with the array, which will make the code lose certain controllability. Because if it is used elsewhere. The creator of this code had to remember the definition of the included function as well as the logic of the array definition. It also makes the code less easy to integrate with other code, because instead of just needing to determine whether the function name is unique in the global namespace, it becomes necessary to determine whether the name of the array associated with the function is unique in the global namespace. .

A closure allows the buffer array to associate (cleanly include) the functions it depends on, while maintaining the buffer array's property names as if they were allocated in the global space, while avoiding name conflicts and code interactions. Danger of interference.

One trick here is to create an additional execution context by executing an inline function expression and have that function expression return an inline function that is used by external code. The buffer array is defined as a local variable in the function expression executed inline. It is only called once, so the array is only created once. But the array is always accessible to functions that depend on it, and can be reused.

The following code creates a function that will return an HTML string, part of which is unchanged, but those unchanged strings need to be interspersed with the variables passed in as parameters.

一个内联执行的函数表达式返回了内部函数对象的一个引用。并且分配了一个全局变量,让它可以被作为一个全局函数来调用。而缓冲数组作为一个局部变量被定义在外部函数表达式中。它没有被扩展到全局命名空间中,并且无论函数什么时候使用它都不需要被再次创建。

/* 
         定义一个全局变量:getImgInPositionedDivHtml 
         被赋予对外部函数表达式一次调用返回的一个内部函数表达式 
         内部函数返回了一个HTML字符串,代表一个绝对定位的DIV 
         包裹这一个IMG元素,而所有的变量值都被作为函数调用的参数 
*/  
        var getImgInPositionedDivHtml = (function () {  
            /* 
            buffAr 数组被定义在外部函数表达式中,作为一个局部变量 
            它只被创建一次。数组的唯一实例对内部函数是可见的, 
            所以它可以被用于每一次的内部函数执行 
            空字符串仅仅被用来作为一个占位符,它将被内部函数的参数代替 
            */  
            var buffAr = [  
                 &#39;<div id="&#39;,  
                &#39;&#39;,   //index 1, DIV ID attribute  
                &#39;" style="position:absolute;top:&#39;,  
                &#39;&#39;,   //index 3, DIV top position  
                &#39;px;left:&#39;,  
                &#39;&#39;,   //index 5, DIV left position  
                &#39;px;width:&#39;,  
                &#39;&#39;,   //index 7, DIV width  
                &#39;px;height:&#39;,  
                &#39;&#39;,   //index 9, DIV height  
                &#39;px;overflow:hidden;\"><img src=\"&#39;,  
                &#39;&#39;,   //index 11, IMG URL  
                &#39;\" width=\"&#39;,  
                &#39;&#39;,   //index 13, IMG width  
                &#39;\" height=\"&#39;,  
                &#39;&#39;,   //index 15, IMG height  
                &#39;\" alt=\"&#39;,  
                &#39;&#39;,   //index 17, IMG alt text  
                &#39;\"><\/div>&#39;  
            ];  
            /* 
            返回一个内部函数对象,他是函数表达式执行返回的结果 
            */  
            return (function (url, id, width, height, top, left, altText) {  
                /* 
                分配各种参数给对应的数组元素 
                */  
                buffAr[1] = id;  
                buffAr[3] = top;  
                buffAr[5] = left;  
                buffAr[13] = (buffAr[7] = width);  
                buffAr[15] = (buffAr[9] = height);  
                buffAr[11] = url;  
                buffAr[17] = altText;  
                /* 
                返回连接每个元素后创建的字符串 
                */  
                return buffAr.join(&#39;&#39;);  
            });  
        })();

如果一个函数依赖另一个或几个函数,但那些其他的函数并不期望与任何其他的代码产生交互。那么这个简单的技巧(使用一个对外公开的函数来扩展那些函数)就可以被用来组织那些函数。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

JS取得最小公倍数与最大公约数

JS实现数组去重算法

使用JS实现购物车功能步骤详解

The above is the detailed content of What are the common scenarios in which closures can be exploited in JS? (Picture and text tutorial). For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Is JavaScript Written in C? Examining the EvidenceIs JavaScript Written in C? Examining the EvidenceApr 25, 2025 am 12:15 AM

Yes, the engine core of JavaScript is written in C. 1) The C language provides efficient performance and underlying control, which is suitable for the development of JavaScript engine. 2) Taking the V8 engine as an example, its core is written in C, combining the efficiency and object-oriented characteristics of C. 3) The working principle of the JavaScript engine includes parsing, compiling and execution, and the C language plays a key role in these processes.

JavaScript's Role: Making the Web Interactive and DynamicJavaScript's Role: Making the Web Interactive and DynamicApr 24, 2025 am 12:12 AM

JavaScript is at the heart of modern websites because it enhances the interactivity and dynamicity of web pages. 1) It allows to change content without refreshing the page, 2) manipulate web pages through DOMAPI, 3) support complex interactive effects such as animation and drag-and-drop, 4) optimize performance and best practices to improve user experience.

C   and JavaScript: The Connection ExplainedC and JavaScript: The Connection ExplainedApr 23, 2025 am 12:07 AM

C and JavaScript achieve interoperability through WebAssembly. 1) C code is compiled into WebAssembly module and introduced into JavaScript environment to enhance computing power. 2) In game development, C handles physics engines and graphics rendering, and JavaScript is responsible for game logic and user interface.

From Websites to Apps: The Diverse Applications of JavaScriptFrom Websites to Apps: The Diverse Applications of JavaScriptApr 22, 2025 am 12:02 AM

JavaScript is widely used in websites, mobile applications, desktop applications and server-side programming. 1) In website development, JavaScript operates DOM together with HTML and CSS to achieve dynamic effects and supports frameworks such as jQuery and React. 2) Through ReactNative and Ionic, JavaScript is used to develop cross-platform mobile applications. 3) The Electron framework enables JavaScript to build desktop applications. 4) Node.js allows JavaScript to run on the server side and supports high concurrent requests.

Python vs. JavaScript: Use Cases and Applications ComparedPython vs. JavaScript: Use Cases and Applications ComparedApr 21, 2025 am 12:01 AM

Python is more suitable for data science and automation, while JavaScript is more suitable for front-end and full-stack development. 1. Python performs well in data science and machine learning, using libraries such as NumPy and Pandas for data processing and modeling. 2. Python is concise and efficient in automation and scripting. 3. JavaScript is indispensable in front-end development and is used to build dynamic web pages and single-page applications. 4. JavaScript plays a role in back-end development through Node.js and supports full-stack development.

The Role of C/C   in JavaScript Interpreters and CompilersThe Role of C/C in JavaScript Interpreters and CompilersApr 20, 2025 am 12:01 AM

C and C play a vital role in the JavaScript engine, mainly used to implement interpreters and JIT compilers. 1) C is used to parse JavaScript source code and generate an abstract syntax tree. 2) C is responsible for generating and executing bytecode. 3) C implements the JIT compiler, optimizes and compiles hot-spot code at runtime, and significantly improves the execution efficiency of JavaScript.

JavaScript in Action: Real-World Examples and ProjectsJavaScript in Action: Real-World Examples and ProjectsApr 19, 2025 am 12:13 AM

JavaScript's application in the real world includes front-end and back-end development. 1) Display front-end applications by building a TODO list application, involving DOM operations and event processing. 2) Build RESTfulAPI through Node.js and Express to demonstrate back-end applications.

JavaScript and the Web: Core Functionality and Use CasesJavaScript and the Web: Core Functionality and Use CasesApr 18, 2025 am 12:19 AM

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

MantisBT

MantisBT

Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

Atom editor mac version download

Atom editor mac version download

The most popular open source editor