JS函数与DOM

函数的基本使用

  1. 函数的参数和返回值
    • 参数可多可少,用逗号分开
    • 函数体内可以使用 return 关键词表示 “函数的返回值”
    • 调用一个有返回值的函数,可以被当做一个普通纸,从而可以出现在哪任何可以书写值的地方
    • 调用函数时,一旦遇见 return 语句则会立即退出函数,将执行权还给调用者
  2. 函数的定义和调用
    • 和变量相似,函数必须先定义然后才能使用
    • 使用 function 关键词定义函数,function 是“功能”的意思
    • 函数名,必须符合JS标识符的命名规则
  3. 什么是函数
    • 函数就是语句的封装,可以让这些代码方便的被复用
    • 函数具有“一次定义,多次调用”的优点
    • 使用函数,可以简化代码,让代码更具有可读性
  4. 函数声明的提升(面试题)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    fun()
    // 函数表达式
    var fun = function () {
    console.log("A")
    }

    function fun() {
    console.log("B")
    }
    fun()

    // B A
    • 和变量声明提升类似,函数声明也可以被替身,函数表达式不能提升
    • 变量的提升,只提升定义,不提升值。
    • 函数优先提升,然后再提升变量。

函数算法题

  1. 函数算法题1
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    /**
    * 【阿姆斯特朗数】 数字是 n 位数 , 该数字的每一位的 n 次方之和等于该数字本身
    * 阿姆斯特朗数是指上述条件成立的任意位数的数字 水仙花数是指上述条件成立的 3 位数
    */
    function factorial(n) {
    let result = 1
    for (let i = 1; i <= n; i++) {
    result *= i
    }
    return result
    }

    for (let i = 100; i <= 999; i++) {
    var str = i.toString();
    var a = Number(str[0]);
    var b = Number(str[1]);
    var c = Number(str[2]);

    if (factorial(a) + factorial(b) + factorial(c) == i) {
    console.log("i", i)
    }
    }
  2. 函数算法题2
    • 函数是JS的一等公民,它可以当做参数传入另一个函数
    • sort()函数 这个函数中的a,b分别表示数组中靠前和靠后的项,如果需要将它们交换位置,则返回任意整数,否则返回负数
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      var arr = [33, 22, 55, 11];
      arr.sort(function (a, b) {
      // if (a > b) {
      // return 1
      // } else {
      // return -1
      // }
      return b-a
      })
      console.log("arr", arr)

递归

  1. 什么是递归
    • 函数的内部语句可以调用这个函数自身,从而发起对函数的一次迭代,在新的迭代中,又会执行调用函数自身的语句,从而又产生一次迭代,当函数执行到某一次时,不在进行新的迭代,函数被一层一层返回,函数被递归。
    • 递归是一种较为高级的编程技巧,它把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
    • 递归的要素
      • 边界条件:确定递归到何时终止,也称为递归出口
      • 递归模式:大问题是如何分解为小问题的,也称为 递归体
  2. 递归常见算法题
    • 斐波那契数列
      1
      2
      3
      4
      function fib(n) {
      if (n == 0 || n == 1) return 1;
      return fib(n - 1) + fib(n - 2)
      }
    • 阶乘
      1
      2
      3
      4
      5
      6
      7
      function test(n) {
      console.log("n:",n)
      if (n == 1) return 1;
      console.log("123")
      return n * test(n - 1)
      }
      test(3)
  3. 实现深克隆
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var arr1 = [12, 34, 12, 45, [12, 44]];
    function deepClone(arr) {
    var result = [];
    for (let i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i])) {
    result.push(deepClone(arr[i]))
    } else {
    result.push(arr[i])
    }
    }
    return result;
    }
    var arr2 = deepClone(arr1);

作用域和闭包

  1. 全局变量和局部变量
    • JavaScript 是 函数作用域编程语言:变量只在其定义时所在的function内部有意义。
    • 如果变量不定义在函数的内部,此时这个变量就是全局变量
    • 遮蔽效应
      • 如果函数中也定义了和全局同名的变量,则函数内的变量会将全局的变量 “遮蔽”
    • 形参也是局部变量
      1
      2
      3
      4
      5
      6
      7
      var a = 10;
      function fun(a) {
      a++
      console.log(a)
      }
      fun(7)
      console.log(a)
    • 函数的嵌套
      • 一个函数内部也可以定义一个函数。和局部变量类似,定义在一个函数内部的函数时局部函数
    • 不加 var 将定义全局变量
  2. 作用域链
    • 就是这个变量会被一层一层的(从内层到外层),去寻找它的作用域
  3. 闭包
    • 什么是闭包
      • Javascript 中函数会产生闭包(closure)。闭包是函数本身和该函数声明时所处的环境状态的组合。
      • 函数能够“记忆住”其定义时所处的环境,即使函数不在其定义的环境中被调用,也能访问定义时所处环境的变量。
    • 观察闭包现象
      • 在JavaScript中,每次创建函数时都会创建闭包。但是,闭包特性往往需要将函数“换一个地方”执行,才能观察出来
    • 闭包非常实用
      • 因为它允许我们将数组与操作改数组的函数关联起来,这与“面向对象编程”有少许相似之处
    • 闭包的功能
      • 记忆性
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        function createCheckTemp(standardTemp) {
        return function checkTemp(n) {
        if (n <= standardTemp) {
        alert('你的体温正常')
        } else {
        alert('你的体温偏高')
        }
        }
        }

        var area1 = createCheckTemp(37.1)
        var area2 = createCheckTemp(38.1)
        area1(38)
        area2(38)
        • 当闭包产生时,函数所处环境的状态会始终保持在内存中,不会在外层函数调用后被自动清除。这就是闭包的记忆性
      • 模拟私有变量
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        function fun() {
        var a = 1;
        return {
        getA: function () {
        return a
        },
        add: function () {
        return a++
        },
        pow: function () {
        return a *= 2
        }
        };
        }
        var obj = fun()
        obj.pow()
        obj.add()
        alert(obj.getA())
      • 使用闭包的注意点
        • 不能滥用闭包,否则会造成网页的性能问题,严重时可能导致内存泄漏。所谓内存泄漏是指程序中以动态分贝的内存由于某种原因未释放或无法释放
      • 闭包面试题
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        function addCount() {
        var count = 0;
        return function () {
        count = count + 1;
        console.log(count)
        }
        }
        var fun1 = addCount()
        var fun2 = addCount()
        fun1()
        fun2()
        fun2()
        fun1()

立即执行函数

  1. 立即执行函数 IIFE
  2. 立即调用函数,一旦被定义,就立即被调用
  3. 形成IIFE的方法
    1
    2
    3
    4
    5
    // 运行函数 
    +function fun1(){ alert('立即调用1'); }()
    -function fun2(){ alert('立即调用2'); }()
    ~function fun3(){ alert('立即调用3'); }()
    !function fun4(){ alert('立即调用4'); }()
    • 函数必须转为“函数表达式”才能被调用
  4. IIFE的作用
    • 为变量赋值
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      var age = 28;
      var sex = '女';
      var title = (function () {
      if (age < 18) {
      return '小朋友'
      } else {
      if (sex == '男') {
      return '先生'
      } else {
      return '女士'
      }
      }
      })()
      alert(title)
    • 将全局变量变为局部变量
      1
      2
      3
      4
      5
      6
      7
      8
      9
      var arr = []
      for (var i = 0; i < 5; i++) {
      (function (i) {
      arr.push(function () {
      alert(i)
      })
      })(i)
      }
      arr[1]()