JavaScript递归中的作用域问题
需求是这样的,从子节点寻找指定className的父节点,一开始就想到递归(笨!),Dom结构如下:
<div class="layer_1">
<div class="layer_2">
<div class="layer_3">
<div id="layer_4"></div>
</div>
</div>
</div>
先通过id获得layer_4的div,然后逐层向上寻找最外层的layer_1,一开始我试图用如下递归获取:
function getNode(){
var child = $("#layer_4");
var parent = getParent(child);
return parent;
}
function getParent(el){
var result;
result = el.parentNode;
if(!el || el === document.documentElement || el.parentNode === document.documentElement){
return;
}else if(result && result.className === "layer_1"){
return result;
}else{
getParent(result);
}
return result;
}
getNode(); //undefined
结果返回的是undefined!
本来是一最基本的递归,为什么会出现这种结果?
其实修改这个问题很简单,目前我只想到一个办法:将result声明为全局变量!
当然这个方法的缺点是造成了memory leak,折中的解决办法是在获取到result后将result =null。
可能有朋友看到这里就已经知道这个问题的原因了,那就是:JavaScript中function的作用域问题-闭包!下面详细解释一下。
如果按照上面的写法,
1、每次递归调用getParent()方法是都会声明一个局部变量result,同时因为闭包的缘故,每次的gerParent()的运行作用域又保留着上次getParent()的作用域,所以每次都会覆盖上层同名的result,作为一个当前函数域的局部变量;
2、当找到layer_1后,result更新,return result得到了我们想要的结果,跳出本次函数域,进入上层函数域,但此时的上层函数域中result并未更新(因为被下层函数域的同名result屏蔽了),所以此时最外层的result仍然是undefined!
所以最终将的到undefined!
这个问题同样引出了以前遇到的关于return的bug,当时把return想象的太强大了,以为return会跳出整条作用域链,上述问题证明了return只能跳出当前作用域,以后注意!
补充:谢谢亮哥的指导,用全局变量解决确实是最笨的法子了,以下是改进办法:
function getParent(el){
var result;
result = el.parentNode;
if(!el || el === document.documentElement || el.parentNode === document.documentElement){
return;
}else if(result && result.className === "layer_1"){
return result;
}else{
return getParent(result);
}
}
在每次递归调用时用return跳出当前函数域,之后进入下层函数时result获取后直接返回,而不用回到最外层函数域。避免了全局变量,同时优化了递归运算。
JavaScript递归中的作用域问题的更多相关文章
- 【授课录屏】JavaScript高级(IIFE、js中的作用域、闭包、回调函数和递归等)、MySQL入门(单表查询和多表联查)、React(hooks、json-server等) 【可以收藏】
一.JavaScript授课视频(适合有JS基础的) 1.IIFE 2.js中的作用域 3.闭包 4.表达式形式函数 5.回调函数和递归 资源地址:链接:https://pan.baidu.com/s ...
- JavaScript中的作用域
很多(JavaScript)开发者都在讨论"作用域",但它是什么?它们在JavaScript中的任何地方!我发现很多年轻的开发者不知道作用域是什么.他们中大多数人可以用jQuery ...
- 浅谈javascript中的作用域
首先说明一下:Js中的作用域不同于其他语言的作用域,要特别注意 JS中作用域的概念: 表示变量或函数起作用的区域,指代了它们在什么样的上下文中执行,亦即上下文执行环境.Javascript的作 ...
- 【翻译】JavaScript中的作用域和声明提前
原文:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ===翻译开始=== 你知道下面的JavaScript脚本执 ...
- JavaScript中的作用域和声明提前
[翻译]JavaScript中的作用域和声明提前 原文:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ===翻译 ...
- 认识javascript中的作用域和上下文
javascript中的作用域(scope)和上下文(context)是这门语言的独到之处,这部分归功于他们带来的灵活性.每个函数有不同的变量上下文和作用域.这些概念是javascript中一些强大的 ...
- javascript学习中自己对作用域和作用域链理解
在javascript学习中作用域和作用域链还是相对难理解些,下面我关于javascript作用域和作用域链做一下详细介绍,给各位初学者答疑解惑. 首先我们介绍一下什么是作用域? 从字面上理解就是起 ...
- 漫谈JavaScript中的作用域(scope)
什么是作用域 程序的执行,离不开作用域,也必须在作用域中才能将代码正确的执行. 所以作用域到底是什么,通俗的说,可以这样理解:作用域就是定义变量的位置,是变量和函数的可访问范围,控制着变量和函数的可见 ...
- 深入理解JavaScript中的作用域和上下文
介绍 JavaScript中有一个被称为作用域(Scope)的特性.虽然对于许多新手开发者来说,作用域的概念并不是很容易理解,我会尽我所能用最简单的方式来解释作用域.理解作用域将使你的代码脱颖而出,减 ...
随机推荐
- 【第一次作业】&&软件工程大一班---甘昀
这个作业属于哪个课程: <课程的链接点这里> 这个作业要求在哪里: <作业要求的链接点这里> 我在这个课程的目标是: 学会软件开发的流程和思想 这个作业在哪个具体方面帮助我 ...
- Python 的经典设计格言,格言来源于 Python 但不限于 Python
The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Si ...
- Open quote is expected for attribute "{1}" associated with an element type "column".
这个的错误的意思很简单:就是自己的配置文件是否缺少""号
- Golang之路【目录】
我正在写一套使用Golang全栈开发的教程,名字暂叫“Golang之路”,希望大家多提建议. 目录如下: Golang之路[第一篇]:Golang简介和入门Golang之路[第二篇]:Golang基础 ...
- 口试Linq题
LINQ to SQL与IQueryable 理解IQueryable的最简单方式就是,把它看作一个查询,在执行的时候,将会生成结果序列. LINQ to Object和LINQ to SQL有何区别 ...
- Codeforces 863 简要题解
文章目录 A题 B题 C题 D题 E题 F题 G题 传送门 简要题解?因为最后一题太毒不想写了所以其实是部分题解... A题 传送门 题意简述:给你一个数,问你能不能通过加前导000使其成为一个回文数 ...
- tp5 数据库
连接数据库: 在config下面的database.php里. 查找数据: halt(Db::name('studys')->column('name','age')); 也可以用find fi ...
- redis学习-散列表常用命令(hash)
redis学习-散列表常用命令(hash) hset,hmset:给指定散列表插入一个或者多个键值对 hget,hmget:获取指定散列表一个或者多个键值对的值 hgetall:获取所欲哦键值以及 ...
- ES6使用fetch请求数据
ie是完全不支持fetch的. fetch(url,{method:"get/post"}).then(res=>{ }) 如果请求返回的status是200,body是 ...
- Chrome 的 PNaCl 还活着么?
WebAssembly Migration Guide Given the momentum of cross-browser WebAssembly support, we plan to focu ...