zoukankan      html  css  js  c++  java
  • 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,一开始我试图用如下递归获取:

     1 function getNode(){
     2     var child = $("#layer_4");
     3     var parent = getParent(child);
     4     return parent;
     5 }
     6 
     7 function getParent(el){
     8     var result;
    result = el.parentNode;
    9 if(!el || el === document.documentElement || el.parentNode === document.documentElement){ 10 return; 11 }else if(result && result.className === "layer_1"){ 12 return result; 13 }else{ 14 getParent(result); 15 } 16 return result; 17 } 18 19 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获取后直接返回,而不用回到最外层函数域。避免了全局变量,同时优化了递归运算。

  • 相关阅读:
    虚树入门
    378. 骑士放置(最大独立集)
    377. 泥泞的区域(最大点集)
    352. 闇の連鎖
    P2680 运输计划
    Linux下的段错误(Segmentation fault)
    Acwing 98-分形之城
    快速幂 和 快速乘
    P1308-道路修建 (noi 2011)
    洛谷 P1070 道路游戏(noip 2009 普及组 第四题)
  • 原文地址:https://www.cnblogs.com/ihardcoder/p/3723853.html
Copyright © 2011-2022 走看看