函数表达书-读书笔记

定义函数的方式有两种:一种是函数声明,另一种就是函数表达式。函数声明的语法如下:

function functionName(arg0,arg1,arg2){//函数体
}

函数声明,有一个重要特征就是函数声明提升。也就是在执行代码之前会先读取函数声明,也就意味着可以把函数声明放在调用它的语句后面。

sayHi();
function sayHi(){console.log("Hi!");
}

下面介绍函数表达式的语法:

var functionName = function(arg0,arg1,arg2){//函数体  
}

这种看起来好像常规的变量赋值语句,就是创建一个函数并将它赋值给变量functionName,这样的函数就是匿名函数,注意function关键字后面没有标识符,匿名函数的name属性是空字符串。

函数表达式和其他表达式一样,在使用之前必须先赋值。

sayHi(); //错误:函数还不存在
var sayHi = function(){alert("Hi!");
};

一、闭包

闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。栗如:

function createComparisonFunction(propertyName) {return function(object1, object2){var value1 = object1[propertyName];var value2 = object2[propertyName];if (value1 < value2){return -1;} else if (value1 > value2){return 1;} else {return 0;}};
}

在函数执行过程中,为读取和写入变量的值,需要在作用域链中查找变量,栗如:

function compare(value1, value2){if (value1 < value2){return -1;} else if (value1 > value2){return 1;} else {return 0;}
}
var result = compare(5, 10);

上面代码先定义了compare()函数,然后又在全局作用域调用了它,当调用compare()时,会创建一个包含arguments、value1、value2的活动对象。全局执行环境的变量对象在compare()执行环境的作用域链中则处于第二位,如图:

在另一个函数内部定义的函数会将包含函数(即外部函数)的活动对象添加到它的作用域链中。因此,在createComparisonFunction()函数内部定义的匿名函数的作用域链中,实际上将会包含外部函数createComparisonFunction()的活动对象。

var compare = createComparisonFunction("name");
var result = compare({ name: "Nicholas" }, { name: "Greg" });

在匿名函数从createComparisonFunction()中被返回后,它的作用域链被初始化为包含createComparisonFunction()函数的活动对象和全局变量对象。这样,匿名函数就可以访问在createComparisonFunction()中定义的所有变量。更为重要的是,createComparisonFunction()函数在执行完毕后,其活动对象也不会被销毁,因为匿名函数的作用域链仍然在引用这个活动对象。换句话说,当createComparisonFunction()函数返回后,其执行环境的作用域链会被销毁,但它的活动对象仍然会留在内存中;直到匿名函数被销毁后,createComparisonFunction()的活动对象才会被销毁。

//创建函数
var compareNames = createComparisonFunction("name");
//调用函数
var result = compareNames({ name: "Nicholas" }, { name: "Greg" });
//解除对匿名函数的引用(以便释放内存)
compareNames = null;

首先,创建的比较函数被保存在变量compareNames中,通过设置compareNames为null解除该函数的引用,就等于通知垃圾回收机制将其清除。匿名函数的作用域链被销毁,其他作用域(除了全局作用域)也都可以安全地销毁了。

作用域链带来了一个副作用,闭包只能取得包含函数中任何变量的最后一个值。闭包所保存的是整个变量对象,而不是某个特殊的变量。举栗:

function createFunctions(){var result = new Array();for (var i=0; i < 10; i++){result[i] = function(){return i;};}return result;
}

这个函数会返回一个函数数组,表面上看,似乎每个函数都有自己的索引值,即位置0的函数返回0,位置1的函数返回1,以此类推。但实际上,每个函数都返回10。因为每个函数的作用域链中凑保存着createFunctions()函数的活动对象,所以它们引用的都是同一个变量i。当createFunctions()函数返回后,变量i的值是10,此时每个函数都引用着保存变量i的同一个变量对象,所以在每个函数内部i的值都是10。

我们可以通过创建另一个匿名函数强制让闭包的行为符合预期。

function createFunctions(){var result = new Array();for (var i=0; i < 10; i++){result[i] = function(num){return function(){return num;};}(i);}return result;
}

重写了createFunctions()函数后,每个函数就会返回各自不同的索引值了。在这里,我们没有直接把闭包赋值给数组,而是定义了一个匿名函数,并立即执行该匿名函数的结果赋给数组。这里的匿名函数有一个参数num,也就是最终的函数要返回的值。

在调用每个匿名函数时,我们传入了变量i。由于函数参数是按值传递的,所以就会将变量i的当前值复制给参数num。而在这个匿名函数内部,又创建并返回一个访问num的闭包。这样一来,result数组中的每个函数都有自己num变量的一个副本,因此就可以参会各自不同的数值了。

 

参考资料

《javascript高级程序设计(第3版)》第7章 函数表达式

转载于:https://www.cnblogs.com/winteronlyme/p/6723234.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/396145.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue截取一个字符串_vue 截取字符串

let str abcdef;// 0str str.slice(0);//返回整个字符串 abcdefstr str.substring(0);//返回整个字符串 abcdefstr str.substr(0);//返回整个字符串 abcdef// 使用一个参数str str.slice(2);//截取第二个之后所有的字符 cdefstr str.substring(2);//截取第二个之后所有的…

网络工程师需要哪些知识_成长工程师可以教给我们哪些工程知识

网络工程师需要哪些知识I’ve been working as an engineer on the growth team at Airbnb for a couple of months now.我已经在Airbnb的成长团队担任工程师几个月了。 Since I’m in an environment full of passionate developers, I wanted to share some of the good eng…

linux父进程循环,LINUX C 父进程建立多个子进程循环非堵塞回收列子

下面 代码主要用于复习&#xff0c;留于此点击(此处)折叠或打开/*************************************************************************> File Name: fork5.c> Author: gaopeng QQ:22389860 all right reserved> Mail: gaopp_200217163.com> Created Time: …

服务器自动运行python_在虚拟主机中安装了python程序,如何使它在服务器上自动运行?...

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":3,"count":3}]},"card":[{"des":"IP地理位置库(GeoIP Databases)是对运营商分…

模拟测试

题解&#xff1a; 3道水题。。 1。生活大爆炸版剪刀石头布 忘记怎么打f[5][5]{}这个了。。 然后发现里面啥都不加也可以 加的话要是{} 2.送礼物 双向搜 有点卡常数。。 我没写dfs 写了dp求多少&#xff08;好智障啊。。 访问数组挺慢的所以应该速度差不多。。&#xff09; lowb…

javascript闭包_通过邮寄包裹解释JavaScript闭包

javascript闭包by Kevin Kononenko凯文科诺年科(Kevin Kononenko) 通过邮寄包裹解释JavaScript闭包 (JavaScript Closures Explained by Mailing a Package) 如果您以前寄过包裹或信件&#xff0c;那么您可以了解JavaScript中的闭包。 (If you have mailed a package or lette…

linux 加入ad 用ssh,使用samba验证AD用户,允许AD用户登录到linux

使用samba验证AD用户&#xff0c;允许AD用户登录到linux2007年06月26日 星期二 14:101、先把samba加入到AD域中2、在smb.conf中添加一行&#xff0c;让登录进来的用户使用bashtemplate shell /bin/bash3、运行authconfig&#xff0c;在验证中选择 使用smb和kerberos,winbind验…

体会日子

体会日子 开通了博客园&#xff0c; 日子要记录一下。 以后要好好上进了。 posted on 2016-05-01 23:16 体会日子 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/yukunshi/p/5451485.html

selenium 难定位元素、时间插件

关于frame: 1. 如果网页存在iframe的话&#xff0c;传统的定位有时候找不到元素&#xff0c;需要切换frame&#xff1b; # 切换到leftFrame定位“测井设计” driver.switch_to_frame("leftFrame") driver.find_element_by_link_text(u"设计").click() # 切…

python kmeans聚类 对二维坐标点聚类_Kmeans均值聚类算法原理以及Python如何实现

第一步.随机生成质心由于这是一个无监督学习的算法&#xff0c;因此我们首先在一个二维的坐标轴下随机给定一堆点&#xff0c;并随即给定两个质心&#xff0c;我们这个算法的目的就是将这一堆点根据它们自身的坐标特征分为两类&#xff0c;因此选取了两个质心&#xff0c;什么时…

HDU 2544最短路dijkstra模板题

最短路 Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 33657 Accepted Submission(s): 14617Problem Description在每年的校赛里&#xff0c;全部进入决赛的同学都会获得一件非常美丽的t-shirt。可是每当我们…

我为期一个月的GitHub的经验教训

by JS由JS 我为期一个月的GitHub的经验教训 (Lessons from my month-long GitHub commit streak) “I want to learn JavaScript. Like, really learn it. Like, truly understand it.” — me in November 2016“我想学习JavaScript。 喜欢&#xff0c;真正地学习它。 喜欢&a…

安装itunes需要管理员身份_ITUNES无法安装,提示没有权限如何解决?

展开全部注意机器一定要登陆管理员系统&#xff0c;如果现在不是&#xff0c;可以注62616964757a686964616fe78988e69d8331333365646263销&#xff0c;切换一下用户。还有计算机不要有漏洞&#xff0c;如果有的话修复一下。打开开始运行,输入regedit,点击确认打开注册表编辑器,…

vs2012新建项目产生的问题

当用vs新建web项目时遇到 只需下载一个vs2012的更新插件 http://download.microsoft.com/download/A/0/2/A02C37E0-77F7-448A-BD5C-F66AB1F78DBC/VS11-KB3002339.exe 点击安装更新即可. 转载于:https://www.cnblogs.com/GreenLeaves/p/5452073.html

zoj4062 Plants vs. Zombies 二分+模拟(贪心的思维)

题目传送门 题目大意&#xff1a;有n个植物排成一排&#xff0c;标号为1-n&#xff0c;每株植物有自己的生长速度ai&#xff0c;每对植物浇一次水&#xff0c;该株植物就长高ai&#xff0c;现在机器人从第0个格子出发&#xff0c;每次走一步&#xff0c;不能停留&#xff0c;每…

MyBatis注解模式批量insert方法

2019独角兽企业重金招聘Python工程师标准>>> 方法一:script标签方式 Insert("<script>insert into xxx (channelId,siteId) " "values " "<foreach collection\"list\" item\"item\" index\"index\&quo…

尚硅谷学费有住宿么_我在12个小时的住宿期间了解到的硅谷知识

尚硅谷学费有住宿么by Sahil Khoja由Sahil Khoja 我在12个小时的住宿期间了解到的硅谷知识 (What I learned about Silicon Valley during my 12 hour stay) #1 Unless you’re a designer or a developer, the billboards are pure gibberish.&#xff03;1除非您是设计师或开…

以下属于linux文件系统认为的文件是,信息安全技术题库:在Linux系统中,图形文件、数据文件、文档文件等都属于()。...

相关题目与解析Linux中图像文件属于()。A、文本文件B、连接文件C、特殊文件D、二进制文件主要用于Linux系统中进程间相互传递数据。A&#xff0e;FIFO文件B&#xff0e;设备文件C&#xff0e;链接文件D&#xff0e;目录文件关于Linux文件组织方式的说法中&#xff0c;(32)是错误…

关于eclipse中文注释乱码的问题

今天打开了一个以前的android项目&#xff0c;发现中文注释都成乱码啦&#xff01;&#xff01;&#xff01; 后来在网上找了一会解决方法&#xff0c;知道了中文的编码大体是两种&#xff1a;GBK(汉字内码扩展规范)和UTF-8(8-bit Unicode Transformation Format)。 因此问题的…

园林系统优秀党员推荐材料_园林绿化公司党员先进个人事迹材料

第1页共5页三一文库(www.31doc.com)〔园林绿化公司党员先进个人事迹材料〕我于年月踏出校门来到建设公司。初到公司&#xff0c;我被分配到分公司卉丰园林绿化公司工作。我努力学习公司各项规章制度和相关业务知识&#xff0c;多了解树木、绿化的有关情况。在此期间&#xff0c…