JavaScript递归原理
JavaScript递归是除了闭包以外,函数的又一特色呢.很多开发新手都很难理解递归的原理,我在此总结出自己对递归的理解.
所谓递归,可以这样理解,就是一个函数在自身的局部环境里通过自身函数名又调用,如此反复,直到条件不满足,返回最终结果的一种情形.最简单的一个示例代码如下:
function fn(a){
return a <= 1 ? a = 1 : a * fn(a - 1);
}
这也是一个最经典的递归阶乘函数了,虽然这行代码表面上看起来没什么问题,但在执行如下代码,则会出现错误.
var otherfn = fn; fn = null; otherfn(5);//出错,fn is not a function
以上将定义的递归阶乘函数fn()保存在变量otherfn中,然后将fn()函数设置为null,也就是说,这样就断掉了对原始函数fn()的引用,因此在调用otherfn()函数时候就会报错.毕竟调用otherfn()实际上就相当于是调用fn()函数,而fn()函数已经被解除了引用,所以自然会报一个fn 不是一个函数的错误呢.
那么,有没有办法解决呢?
JavaScript的arguments.callee就可以解决这个问题.argumens.callee实际上就是指向一个函数的指针,因此,只要将以上代码修改成如下所示:
function fn(a){
return a <= 1 ? a = 1 : a * arguments.callee(a - 1);
}
这样,通过arguments.callee代替了函数名fn,就保证了引用不会被解除,因此无论怎么调用该函数就不会出问题了.
因此,在编写递归函数时,使用arguments.callee总是比直接用函数名更好一点.
不过,使用arguments.callee有个缺点,那就是在严格模式下,是无非访问arguments.callee的,因此就需要使用命名函数表达式来达到与这个指针带来的效果呢.代码如下:
var fn = (function f(a){
return a <= 1 ? a = 1 : a * f(a - 1);
});
以上代码创建了一个命名为f的函数表达式,然后将它赋值给一个fn变量.因此即便把这个函数表达式赋值给另一个变量,这个函数也仍然可以正常调用.而且这种做法不仅在适合非严格模式,也同样适合严格模式.
JavaScript递归原理的更多相关文章
- JavaScript内部原理实践——真的懂JavaScript吗?(转)
通过翻译了Dmitry A.Soshnikov的关于ECMAScript-262-3 JavaScript内部原理的文章, 从理论角度对JavaScript中部分特性的内部工作机制有了一定的了解. 但 ...
- How Javascript works (Javascript工作原理) (一) 引擎,运行时,函数调用栈
个人总结:该系列文章对JS底层的工作原理进行了介绍. 这篇文章讲了 运行时:js其实是和AJAX.DOM.Settimeout等WebAPI独立分离开的 调用栈:JavaScript的堆内存管理 和 ...
- How Javascript works (Javascript工作原理) (五) 深入理解 WebSockets 和带有 SSE 机制的HTTP/2 以及正确的使用姿势
个人总结: 1.长连接机制——分清Websocket,http2,SSE: 1)HTTP/2 引进了 Server Push 技术用来让服务器主动向客户端缓存发送数据.然而,它并不允许直接向客户端程序 ...
- How Javascript works (Javascript工作原理) (十一) 渲染引擎及性能优化小技巧
个人总结:读完这篇文章需要20分钟,这篇文章主要讲解了浏览器中引擎的渲染机制. DOMtree ----| |----> RenderTree CSSOMtree ----| ...
- JavaScript 工作原理之十一-渲染引擎及性能优化小技巧
原文请查阅这里,略有删减,本文采用知识共享署名 4.0 国际许可协议共享,BY Troland. 本系列持续更新中,Github 地址请查阅这里. 这是 JavaScript 工作原理的第十一章. 迄 ...
- JavaScript作用域原理(三)——作用域根据函数划分
一.一个for实例 <p id="scope3" style="color:red"></p> var pscope3 = docume ...
- JavaScript作用域原理(二)——预编译
JavaScript是一种脚本语言, 它的执行过程, 是一种翻译执行的过程.并且JavaScript是有预编译过程的,在执行每一段脚本代码之前, 都会首先处理var关键字和function定义式(函数 ...
- JavaScript作用域原理(一)——作用域链
一.作用域的描述 JavaScript权威指南中对作用域有一句很精辟的描述:“JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里.” 在JavaScript中,作用域的 ...
- 深入理解JavaScript Hijacking原理
最近在整理关于JavaScript代码安全方面的资料,在查关于JavaScript Hijacking的资料时,发现关于它的中文资料很少,故特意整理一下. 一.JavaScript Hijacking ...
随机推荐
- tp5命令行基础
命令行工具需要在命令行下面执行,请先确保你的php.exe已经加入了系统环境变量Path. 要执行命令,首先进入命令行,并切换当前目录到应用的根目录(也就是think文件所在目录)下面,执行: php ...
- Asp.net mvc 中View 的呈现(二)
[toc] 上一节介绍了 Asp.net mvc 中除 ViewResult 外的所有的 ActionResult,这一节介绍 ViewResult. ViewResultBase ViewResul ...
- 包装类和基本类型区别?(integer和int取值范围一样大)
1.声明方式不同,int不需要new .Integer需要new 2.性质上根本不同点:int是基本数据类型.Integer是引用数据类型,它有自己的属性,方法 3.存储位置和方式不同:int是存储在 ...
- 03_Linux文件和目录
一.Linux目录结构 /:根目录,一般根目录下只存放目录,在Linux下有且只有一个根目录.所有的东西都是从这里开始.当你在终端里输入"/home",你其实是在告诉电脑,先从/( ...
- .NET Core 2.0 问题杂记
一. Ubuntu 14.04 安装 1.安装之前请先删除之前的.net core 版本 命令如下: 1.1 获取安装的.net core 版本 sudo apt --installed list | ...
- BZOJ 2734: [HNOI2012]集合选数 [DP 状压 转化]
传送门 题意:对于任意一个正整数 n≤100000,如何求出{1, 2,..., n} 的满足若 x 在该子集中,则 2x 和 3x 不能在该子集中的子集的个数(只需输出对 1,000,000,001 ...
- CF 235C. Cyclical Quest [后缀自动机]
题意:给一个主串和多个询问串,求询问串的所有样子不同的周期同构出现次数和 没有周期同构很简单就是询问串出现次数,|Right| 有了周期同构,就是所有循环,把询问串复制一遍贴到后面啊!思想和POJ15 ...
- Golang Linux Shell编程(一)
1.调用系统命令 exec包执行外部命令,它将os.StartProcess进行包装使得它更容易映射到stdin和stdout,并且利用pipe连接i/o func Command(name stri ...
- ubuntu下smb的配置
PS: 转自Ubuntu中文论坛 -------------------------------------------------------------------------------- ...
- Windows 桌面和文件夹的右键->打开命令行窗口
Windows 桌面和文件夹的右键->打开命令行窗口 1.先按下shift,再点鼠标右键运行CMD,(不是管理员权限) 上图是我已经加了右键的,并且 系统设置了 ps代替cmd,所以是“在此处 ...