【颠覆认知的JS】- 5. 参数默认值、递归、预编译、暗示全局变量

85 阅读2分钟

参数默认值

  • 初始化参数

  • ES6:

  • function test(a = 1, b = 2) {console.log(a, b)}

  • 调用函数时如何只给b赋值

  • test(undefined, 'b')

  • ES6之前如何初始化参数

  • function test2(a, b) {var = arguments[0] || 1; console.log(a)}

  • function test2(a, b) {var = typeof(arguments[0]) !== 'undefined' ? arguments[0] : 1; console.log(a)}

递归

  • intro:经典递归法求阶乘
  • 递归只是一种函数调用的方式
  • js栈小,递归容易暴栈;慎用
  • 总是在出口时才一步一步向上返回

预编译

js代码是怎么跑起来的

  1. 先检查语法错误
  2. 预编译过程
  3. 解释一行,执行一行

函数声明整体提升,变量只有声明提升,赋值是不提升的:

test() // 1
function test()
{
    console.log(1)
}

console.log(a) // undefined
var a = 1

预编译参考之前的笔记:juejin.cn/post/723934…

函数预编译

  • 函数执行之前的步骤:AO 函数上下文

  • 创建AO对象 AO = {}

  • 寻找(定义声明)函数1.形参及2.变量声明

  • 形参变量放入AO中,初始化undefiend

  • 将实参赋值给形参

  • 寻找(定义声明)函数,赋值函数体

  • 执行函数

  • Summary:

  • 定义变量

  • 实参变量赋值

  • 定义函数

  • 执行函数

  • 题例

    function test(a, b) { console.log(a); // 1 c = 0; var c; a = 5; b = 6; console.log(b); // 6 function b(){} function d(){} console.log(b); // 6 } test(1);

    AO = { a: undefined -> 1 -> 5 b: b(){} -> 6 c: 0, d: d(){} }

  • GO 全局上下文:window

  • 上面的AO只是在函数内部执行时底层原理,GO是全局代码执行时(不包含函数执行时AO部分)的预编译相关过程

  • 实际上就等于在GO的第三阶段(执行期间)碰到函数执行了就进入AO部分

  1. 定义变量
  2. 定义函数
  3. 执行(不一定是函数)
  • 题例

    console.log(a, b); // function a(){} undefined function a() {} var b = function(){}

综合题例

a = 1;
function test(e) {
  function e(){}
  arguments[0] = 2;
  console.log(e); // 2
  if(a) {
    var b = 3;
  }
  var c;
  a = 4;
  var a;
  console.log(b); // undefined
  f = 5;
  console.log(c); // undefined
  console.log(a); // 4
}
var a;
test(1);
console.log(a); // 1
console.log(f); // 5