JavaScript 闭包与递归函数

332 阅读1分钟

闭包:指的是能够访问另一个函数作用域的变量的函数 递归函数:就是在函数体内调用本函数。使用递归函数一定要注意,处理不当就会进入死循环。递归函数只有在特定的情况下使用

闭包

使用函数自我调用实现闭包

var add = (function () {
  var counter = 0;
  return function () { return counter += 1; }
})();

add()
add();
add();
console.log(add());

image.png**提升: **闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。 直观的说就是形成一个不销毁的栈环境, 闭包实现了传递值和功能的调用

闭包点赞

<!DOCTYPE html>
<html>

  <head>
    <meta charset="UTF-8">
    <title></title>
    <script src="js/Call.js" type="text/javascript" charset="utf-8"></script>
  </head>
  <style type="text/css">
    #box ul {
      width: 450px;
      display: flex;
      flex-direction: row;
      justify-content: space-between;
      list-style: none;
    }

    #box ul li {
      display: flex;
      flex-direction: column;
      align-items: center;
      height: 180px;
      justify-content: space-between;
    }

    img {
      width: 200px;
    }
  </style>

  <body id="box">
      <ul>
        <li><img src="img/ly.jpg" /><input type="button" id="btn1" value="赞(1)" /></li>
        <li><img src="img/lyml.jpg" /><input type="button" id="btn2" value="赞(1)" /></li>
      </ul>
  </body>
    <script type="text/javascript">
      function support() {
        var value = 1;
        return function () {
          this.value = "赞(" + (++value) + ")";
        }
      }
      var btnObj = document.getElementsByTagName("input")
      for (var i = 0; i < btnObj.length; i++) {
        btnObj[i].onclick = support();
      }
    </script>
</html>

递归

arguments.callee()

arguments.callee()可以调用自身函数

function geteverySum(x) {
  if (x < 10) {
    return x
  }
  return x % 10 + parseInt(arguments.callee(x / 10))
}
console.log(geteverySum(512)) //8

⚠️**注意: **函数中调用函数自己,此时就是递归,递归一定要有结束的条件

斐波那契数列

function getFbnq(x) {
  if (x < 3) return 1
  return getFbnq(x - 1) + getFbnq(x - 2)
}
console.log(getFbnq(12)) //144

计算数字每项相加的和

function geteverySum(x) {
  if (x < 10) { return x; }
  return x % 10 + parseInt(geteverySum(x / 10));
}
console.log(geteverySum(512));  //8

遍历DOM树

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>遍历DOM树</title>
</head>
<body>
  <h1></h1>
</body>
</html>

<script>
  function forDOM(root, fn) {
  var children = root.children
  for (var i = 0; i < children.length; i++) {
    var child = children[i] //每个子节点
    fn(child) //调用显示每个子节点的名字方法
    child.children && forDOM(child, fn) //递归:有子节点,就继续的遍历
  }
}
var root = document.documentElement //函数调用,传入html根节点
forDOM(root, function (node) {
  console.log("节点的名字:" + node.nodeName)
})
</script>

递归深拷贝

var obj1 = {
  age: 10,
  car: ["奔驰", "宝马", "特斯拉", "奥拓"],
  dog: { name: "大黄", age: 5, color: "黑白色" }
}

var obj2 = {}
function extend(a, b) {
  for (var key in a) {
    var item = a[key]

    if (item instanceof Array) {
      b[key] = []
      extend(item, b[key])
    }

    else if (item instanceof Object) {
      b[key] = {}
      extend(item, b[key])
    }

    else {
      b[key] = item
    }
  }
}

extend(obj1, obj2)
console.dir(obj1)
console.dir(obj2)

深拷贝就算拷贝的对象的数据(存放在堆里面的数据)变了,也不会影响到拷贝后的内容

浅拷贝 浅拷贝就是直接复制,就是把一个对象的地址给了另一个对象,他们指向的相同,两个对象之间有共同的属性或者方法

var obj1 = {
  age: 10,
  car: ["奔驰", "宝马", "特斯拉", "奥拓"]
}
var obj2 = {}

function extend(a, b) {
  for (var key in a) {
    b[key] = a[key]
  }
}

extend(obj1, obj2)
obj2.car[0] = "保时捷"

console.dir(obj2)
console.dir(obj1)
/* 
{ age: 10, car: ['保时捷', '宝马', '特斯拉', '奥拓'] }
{ age: 10, car: ['保时捷', '宝马', '特斯拉', '奥拓'] } 
*/