Javascript高级编程学习笔记(23)—— 函数表达式(1)递归
前面的文章中,我在介绍JS中引用类型的时候提过,JS中函数有两种定义方式
第一种是声明函数,即使用function关键字来声明
第二种就是使用函数表达式,将函数以表达式的形式赋值给一个变量,这个变量就保存了对这个函数的引用
function与表达式的区别前文也已经详细分析过,这里就大概讲解一下
虽然两者在写法上没有什么不同,但是function关键字作为函数声明的时候,与var一样会有变量提升的效果
其本质是在JS创建执行环境的时候,就完成了对函数的声明,所以访问该函数的代码在函数声明语句前就可以使用
但是函数表达式不一样,在JS中 = 后面的内容会被归为表达式上下文,而这种上下文中 function 关键字并没有变量提升的特权
因为,这段表达式的代码,会在执行上下文创建完成后才,会被执行
函数表达式定义函数
var a = function(){
// 代码块
}
上面这种定义函数的方式,也是我们最常用的函数表达式的定义方式
我们在这种情况下没必要给函数一个名字,因为已经有一个变量保存了对该函数的引用。
和函数名的作用一样,所以没必要重复创建
PS.这种没有标识符的函数叫匿名函数,也叫拉姆达函数,函数的name属性为空字符串
在流程控制语句中使用函数表达式
可能许多小伙伴听过一个说法,那就是不要在 if for while 中声明函数
这是为什么呢?
首先我们应该明确,这里指的声明是指使用 function 关键字进行函数声明,而不是使用函数表达式
不让大家在流程控制语句中进行函数声明的主要原因就是,这种写法虽然在逻辑上没有问题,但是在JS解析时会出现错误
我们刚才说过,使用function 关键字声明的函数会有个变量提升的过程
在创建执行上下文的时候,函数的定义就已经完成了
那么问题来了
流程控制语句在代码执行时才会进行判断,而你的声明在判断之前就已经完成了
所以在大部分浏览器中你的流程控制语句并不会有任何作用
但在小部分浏览器,比如火狐针对这一问题是可以按照逻辑完成声明的
所以我们不应该在流程控制语句中进行函数声明
但是话又说回来,万一我就是要在流程控制语句中按照情况来定义函数呢?
那么函数表达式就是你的理想选择
因为不让用的原因就是 function 的变量提升,而函数表达式又不会变量提升,当然就可以安全地使用了
除此而外,当我们需要将函数作为值传递的时候,函数表达式依然是你的首选(避免一些奇奇怪怪的错误)
递归
我的这系列文章,主要是记录自己在学习JS中的一些知识点
所以并不会在这里讲递归算法
主要是说一下递归中存在的问题
抛开ES6中的尾调用优化不谈
在ES5中,我们平时习以为常的递归写法很可能存在一些隐患
function factorial(num){
if(num <= 1){
return 1;
}else{
return num * factorial(num-1);
}
}
上方是一个经典的阶乘递归函数
小伙伴们觉得有啥问题么?
没看出来,没关系
看看下面的代码
var anotherFactorial = factorial;
factorial = null;
anohterFactorial(5); // 报错
我先用一个变量来保存对这个递归函数的引用
然后去掉它原本的引用
但我通过新的引用执行函数时,js报错了
为啥?
因为我们的递归使用的是原来的引用来进行递归调用的
而我们已经切断了原来的引用,所以函数执行时报错
换句话说,这种递归函数的写法耦合度较高
那么怎么解决呢?
function factorial(num){
if(num <= 1){
return 1;
}else{
return num * arguments.callee(num-1);
}
}
之前我们说过,arguments有个callee属性指向函数本身
这里用这种方法就可以解决之前的问题
但是这种方法还有一个问题,在严格模式下不可用
怎么办呢?
var factorial = function f(num){
if(num <= 1){
return 1;
}else{
return num * f(num-1);
}
};
当然是使用函数表达式啦,这种方式在严格模式下依然可用
以上就是函数表达式关于递归的内容啦,明天更闭包的内容,不见不散
Javascript高级编程学习笔记(23)—— 函数表达式(1)递归的更多相关文章
- Javascript高级编程学习笔记(25)—— 函数表达式(3)模仿块级作用域
昨天写了闭包 今天就来聊聊块级作用域的事情 在绝大多数编程语言中,都有块级作用域这个概念 什么是块级作用域呢? 前面我们在刚开始讲的时候说过,JS中的大括号(不在赋值运算符的后面)表示代码块 块级作用 ...
- Javascript高级编程学习笔记(26)—— 函数表达式(4)私有变量
私有变量 严格来讲,JS中没有私有成员的概念,所有对象属性都是公有的. 但是JS中有私有变量的概念 所有在函数中定义的变量都可以认为是私有变量,因为不能在函数外部进行访问 私有变量包括 1.函数参数 ...
- Javascript高级编程学习笔记(24)—— 函数表达式(2)闭包
昨天的文章中主要记录了,函数表达式与函数声明的区别 以及在JS中如何安全地使用递归 那么既然要深入地理解JS中的函数,闭包就是一个绕不开的概念 闭包 JS高编一书中对闭包的概念定义如下: 闭包是指有权 ...
- 《JavaScript高级程序设计》笔记:函数表达式(七)
递归 function factorial(num){ if(num<=1){ return 1; }else { return num * arguments.callee(num-1); } ...
- Javascript高级编程学习笔记(16)—— 引用类型(5) Function类型
JS中许多有趣的地方都和函数脱不了联系 那么是什么让JS中的函数这么有趣呢? 我们一起来看看吧 Function类型 在JS中函数实际上就是对象,每个函数都是Function类型的实例,和JS的其他引 ...
- Javascript高级编程学习笔记(7)—— 函数
前几天有事耽搁了,今天继续更新 今天的主要内容是JS中的函数 这一篇主要讲函数的定义等内容,至于变量提升.执行环境.闭包.内存回收等内容在后面讲,高玩们可以不用看下面的正文了. 函数 首先来讲,函数对 ...
- JavaScript高级编程学习笔记(第三章之一)
继续记笔记,JavaScript越来越有意思了. 继续... 第三章:JavaScript基础 ECMAScript语法在很大程度上借鉴了C和其它类似于C的语言,比如Java和Perl. 大小写敏感: ...
- Javascript高级编程学习笔记(6)—— 流程控制语句
话不多说,我们直接开始进入今天的主题 流程控制语句 首先什么是流程控制语句呢? 顾名思义,就是控制流程的语句. 在JS中语句定义了ECMAScript中的主要语法,让我们可以使用一系列的关键字来完成指 ...
- Javascript高级编程学习笔记(3)—— JS中的数据类型(1)
前一段时间由于事情比较多,所以笔记耽搁了一段时间,从这一篇开始我会尽快写完这个系列. 文章中有什么不足之处,还望各位大佬指出. JS中的数据类型 上一篇中我写了有关JS引入的Script标签相关的东西 ...
随机推荐
- 20164319 刘蕴哲 Exp3 免杀原理与实践
[实验内容] 1.1 正确使用msf编码器(0.5分),msfvenom生成如jar之类的其他文件(0.5分),veil-evasion(0.5分),加壳工具(0.5分),使用shellcode编程( ...
- layui与echarts
https://pan.baidu.com/s/1qM5ybqD-wAQNnWubdegBiA 在此感谢Layui给我这种不懂前端的人很大的帮助
- 面试简单整理之web
63.servlet是什么?运行过程? Servlet是一门用于开发动态web资源的技术. 运行过程: Servlet程序是由WEB服务器调用,web服务器收到客户端的Servlet访问请求后: ①W ...
- postma概念与使用
Postman是google开发的一款功能强大的网页调试与发送网页HTTP请求,并能运行测试用例的的Chrome插件.Postman作为一个chrome的插件,你可以打开chrome,在chrome ...
- Linux sleep 语句以及循环 测试负载
sleep 命令 sleep 1 睡眠1秒sleep 1s 睡眠1秒sleep 1m 睡眠1分sleep 1h 睡眠1小时 总代码 #!/bin/bash for i in {1. ...
- AX_Unit
UnitConvert::qty(_deliverNow, salesLine.SalesUnit, salesLine.inventTable().inventUnitId(), ...
- 描点的改进:运用chart画图。
主要是利用Chart画图: 通过选中一部分曲线进行图像的放大和缩小,最小值为1格. 先计算最大值和最小差值.然后赋值给AxisY.Minimum 和AxisY.Maximum.x轴初始显示数目:Axi ...
- easy-ui treegrid 实现分页 并且添加自定义checkbox
首先第一点easy-ui treegrid 对分页没有好的实现, 因为在分页的过程中是按照 根节点来分页的 后台只能先按照 根节点做分页查询 再将子节点关联进去, 这样才能将treegrid 按 ...
- 使用kbmmw中的随机数替换delphi 10.3 自带的随机数
我们在开发中经常会使用随机数模拟各种随机条件,例如生成唯一的密码和令牌. 在计算机中,一般采用PRNG(伪随机序列发生器)模拟真实随机数.既然是随机,就要要没有任何规律, 在取值范围内均匀.独立.以确 ...
- xml文档格式学习笔记
xml入门经典 (pdf书籍) https://www.cnblogs.com/zhaopengcheng/p/6848802.html