前言:
眼前我们对“js闭包示例”都比较着重,大家都想要剖析一些“js闭包示例”的相关内容。那么小编同时在网上网罗了一些关于“js闭包示例””的相关知识,希望我们能喜欢,同学们一起来学习一下吧!发展至2020年,前端开发的运用也越加的广,包括了游戏、网页、⼩程序、APP、跨端开发以及新技术应用方面等各个方面。
企业对优质前端开发人才的需求量更是日渐增长!想要掌握好过硬的前端技术点,多多少少都绕不开JavaScript。
今天要讲的知识点,就是JavaScript闭包!
闭包可以让JavaScript程序员编写更好的代码。创意满满、印象深刻又简洁。
我们经常在JavaScript中使用闭包,无论你的JavaScript经验多少,总会遇到它们。
也许,闭包可能看起来很复杂,但阅读完这篇文章后,就会容易理解很多。
什么是闭包?关于闭包的产生闭包的构成助于理解的案例什么是闭包?
闭包是一个内部函数,可以访问外部(封闭)函数的变量范围链。
闭包有三个范围链:它可以访问自己的范围(在大括号之间定义的变量),它可以访问外部函数的变量,并且它可以访问全局变量。
内部函数不仅可以访问外部函数的变量,还可以访问外部函数的参数。需要注意的是:即使可以直接调用外部函数的参数,内部函数仍然不能调用外部函数的参数对象。
闭包的产生
Javascript的运行在运行过程中有变量具有局部作用域和全局作用域的区分局部作用域内可以访问全局作用域的变量 反之不可当局部作用域变量被保存到外部 能够被访问到则闭包形成
闭包的形成和Javascript的作用域以及作用域链(Chain scope)密不可分,闭包的形成其实就是作用域链没有被释放,因此会造成内存泄露。
闭包的构成
从名字上来看闭包肯定是闭合包裹的一个东西,其实就是用一个函数来包裹需要return给外部的内容(可以是变量、函数等任何你想保存的东西),利用的就是函数的作用域和作用域链。
通过在另一个函数中添加一个函数来创建一个闭包。
JavaScript闭包的基本示例:
function showName (firstName, lastName) { var nameIntro = "Your name is "; //这个内部函数可以访问外部函数的变量,包括参数 function makeFullName () { return nameIntro + firstName + " " + lastName; } return makeFullName ();}showName ("Michael", "Jackson"); //你的名字是迈克尔杰克逊
闭包在Node.js中广泛使用; 它们是Node.js的异步,非阻塞架构中的主轴。闭包也经常用在jQuery和JavaScript代码中。
闭包的经典jQuery示例:
$(function() { var selections = []; $(".niners").click(function() { // 此闭包可以访问选择变量 selections.push (this.prop("name")); // 更新外部函数作用域中的选择变量 });});闭包规则和副作用
1、闭包可以访问外部函数的变量:
闭包最显著的特征就是闭包可以访问到外部函数变量,即使外部函数变量已经被返回。JavaScript中的函数执行都是相同的作用域链(函数可以从内往外访问)。因此,您可以稍后在程序中调用内部函数。
此示例演示:function celebrityName (firstName) { var nameIntro = "This celebrity is "; // 这个内部函数可以访问外部函数的变量,包括参数 function lastName (theLastName) { return nameIntro + firstName + " " + theLastName; } return lastName; } var mjName = celebrityName ("Michael"); // 此时celebrityName外部函数返回。 //闭包(lastName)在外部函数返回后调用 //然而,闭包仍然可以访问到外部函数的变量和参数 mjName ("Jackson"); // 这个名人是迈克尔·杰克逊
2、闭包引用外部函数的变量存储,不存储实际值。
当外部函数的变量的值在调用闭包之前改变时,闭包变得更有趣。
这个强大的功能可以创造性的利用,看下面代码:
function celebrityID () { var celebrityID = 999; //用内部函数返回一个对象 //所有的内部函数可以访问外部函数的变量 return { getID: function () { //这个内部函数将返回更新celebrityID变量 return celebrityID; //它将返回celebrityID的当前值,即使changeTheID函数更改 },setID: function (theNewID) { //这个内部函数会随时改变外部函数的变量 celebrityID = theNewID; } } } var mjID = celebrityID (); // 此时,该celebrityID外部函数返回。mjID.getID(); // 999 mjID.setID(567); // 改变外部函数变量 mjID.getID(); // 567
3、闭包缓存
由于闭包可以访问外部函数的变量的更新值,当用一个for循环改变外部函数的变量时,也可能导致错误。从而:// 这个例子的细节下面会说 function celebrityIDCreator (theCelebrities) { var i; var uniqueID = 100; for (i = 0; i < theCelebrities.length; i++) { theCelebrities[i]["id"] = function () { return uniqueID + i; } } return theCelebrities; } var actionCelebs = [ {name:"Stallone", id:0}, {name:"Cruise", id:0}, {name:"Willis", id:0} ]; var createIdForActionCelebs = celebrityIDCreator (actionCelebs); var stalloneID = createIdForActionCelebs [0]; console.log(stalloneID.id()); // 103
在前面的例子中,在调用匿名函数时,i的值为3(数组的长度,然后递增)。数字3已添加到uniqueID以为所有名人ID创建103。因此返回的数组中的每个位置都得到 id = 103,而不是预期的100,101,102。
发生这种情况的原因是,正如我们之前例子中讨论的,闭包(本例中的匿名函数)可以通过参数访问外部函数的变量,而不是一个值。
因此,正如前面的例子所示,我们可以使用闭包访问更新的变量,这个例子类似地访问i变量改变时,因为外部函数运行整个for循环并返回i的最后一个值,即103。
要解决在闭包这个副作用(错误),你可以使用一个立即调用函数表达式(IIFE):
function celebrityIDCreator (theCelebrities) { var i; var uniqueID = 100; for (i = 0; i < theCelebrities.length; i++) { theCelebrities[i]["id"] = function (j) { //参数j是i通过这个IIFE调用 return function () { return uniqueID + j; //for循环的每个迭代通过i的当前值到这个IIFE并且保存当前值到数组 } () //通过这个函数的末尾的(),我们将立即执行, 并返回UNIQUEID + j的值,而不是返回一个函数。 } (i); //立即调用函数传递变量i作为参数 } return theCelebrities;}var actionCelebs = [ {name:"Stallone", id:0}, {name:"Cruise", id:0}, {name:"Willis", id:0} ];var createIdForActionCelebs = celebrityIDCreator (actionCelebs);var stalloneID = createIdForActionCelebs [0];console.log(stalloneID.id); // 100var cruiseID = createIdForActionCelebs [1];console.log(cruiseID.id);// 101
随着JavaScript 的飞速发展,前端开发变得越来越有趣,新的库、框架层出不穷,同时,如果没有不断去提升自己的开发人员只会越来越感到心力交瘁。
所以,无论你是编程新手,还是经验丰富的开发人员,我们必须保持学习,才能跟上技术的快速变化。
千锋重庆HTML5大前端开发培训机构课程坚持采用“授课+项目实战教学”模式,促成学员高薪就业。
助力课程每年实时更新,涵盖了以响应式Web应用开发、微信公众平台开发、跨平台混合应用等等。全面培养千锋学员全栈开发能力,做现代企业需求的人才。
标签: #js闭包示例