JS实用篇复习笔记(11)

142 阅读2分钟

1、迭代思想 vs 递归思想

1、

  • 递归 当函数调用自身时
  • 迭代 正常一步一步来

2、举例说明

  • 这是实现乘方思想
pow(2, 2) = 4
pow(2, 3) = 8
pow(2, 4) = 16
1、迭代思想
    //迭代
function pow(x, n) {
  let result = 1;
  for (var i = 0; i < n; i++) {
    result *= x;
  }
  return result;
}
console.log(pow(2, 3)); // 8


  2、递归思想 
  function pow(x, n) {
  if (n == 1) return x;
  return x * pow(x, n - 1);
}
console.log(pow(2, 3)); // 8
    
    

pow(x, n)被调用时,执行分为两个分支:

              if n==1  = x
             /
pow(x, n) =
             \
              else     = x * pow(x, n - 1)
   3、进一步简化一下 
   
 function pow(x, n) {
  return n == 1 ? x : x * pow(x, n - 1);
}
console.log(pow(2, 3)); // 8 注意 函数结构需要 return 出去      
  • 注意 递归有层数限制, 深层多次递归会影响 性能

2、执行上下文和堆栈

1、 所有函数的过程都是相同的:

  1. 当前上下文在堆栈顶部“记住”。
  2. 为子调用创建新上下文。
  3. 当子调用完成时——从堆栈中弹出前一个上下文,并继续执行

2、举例说明 常用且重要的部分 递归遍历

如果想把 number 加起来 怎么处理? 多个层级的 问题

  let company = {
      sales: [
        {
          name: "skt",
          sum: 120,
        },
        {
          name: "dk",
          number: 100,
        },
      ],

      development: {
        frontend: [
          {
            name: "dev1",
            number: 200,
          },
          {
            name: "dev2",
            number: 190,
          },
        ],

        backend: [
          {
            name: "jiwan",
            number: 130,
          },
        ],
      },
    };
  • 使用递归遍历
    function sum1(dep) {
      if (Array.isArray(dep)) {
        return dep.reduce((prev, cur) => prev + cur.number, 0);
      } else {
        let sum = 0;
        for (let item of Object.values(dep)) {
          sum += sum1(item);
        }
        return sum;
      }
    }
    alert(sum1(company)); // 740
  • 非常nice

3、let的块级 作用域

1、 其实 函数本身有作用域

  • 在两块内 可以work
{
  // show message
  let message = "Hello";
  alert(message);
}

{
  // show another message
  let message = "Goodbye";
  alert(message);
}
  • 放一起
// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);

2、for while if 也有块级

if (true) {
  let phrase = "Hello!";

  alert(phrase); // Hello!
}

alert(phrase); // Error, no such variable!

3、经典 函数嵌套

  • 内层 返回一个函数
function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2

4、最简单函数过程

image.png

5、函数名称 name

  • 下面都可 打印出 name 常规声明 + 函数表达式
function sayHi() {
  alert("Hi");
}

alert(sayHi.name); // sayHi
let sayHi = function() {
  alert("Hi");
};

alert(sayHi.name); // sayHi (there's a name!)
  • 下面 这个也可
function f(sayHi = function() {}) {
  alert(sayHi.name); // sayHi (works!)
}

f();
let user = {

  sayHi() {
    // ...
  },

  sayBye: function() {
    // ...
  }

}

alert(user.sayHi.name); // sayHi
alert(user.sayBye.name); // sayBye
// function created inside array
let arr = [function() {}];

alert( arr[0].name ); // <empty string>

6、函数长度 length 表示函数参数的长度

  • ...more 并未 算在 length内
function f1(a) {}
function f2(a, b) {}
function many(a, b, ...more) {}

alert(f1.length); // 1
alert(f2.length); // 2
alert(many.length); // 2

7、基本的垃圾收集

function f() {
  let value = 123;

  return function() {
    alert(value);
  }
}

let g = f(); // while g function exists, the value stays in memory

g = null; // ...and now the memory is cleaned up

6、几个题目

let name = "John";

function sayHi() {
  alert("Hi, " + name);
}

name = "Pete";

sayHi(); // what will it show: "John" or "Pete"?   // Pete
function makeWorker() {
  let name = "Pete";

  return function() {
    alert(name);
  };
}

let name = "John";

// create a function
let work = makeWorker();

// call it
work(); // what will it show?  Pete 块级 

7、call/apply/bind ?

func.call(context, ...args);
func.apply(context, args); // args是个数组
  • 延迟 ms 后 执行
    // 延迟 xx ms 后执行 函数
    function delay(fn, ms) {
      return function (...args) {
        setTimeout(() => {
          fn.apply(this, arguments);
        }, ms);
      };
    }

    //test
    let fn1000 = delay(alert, 1000);
    fn1000("test");