📌 函数参数默认值

初始化参数 默认值:undefined

  • ES6支持形参赋默认值写法 ```javascript // ES6 支持直接在形参赋默认值

function test(a = 1, b ){ console.log(a); console.log(b) }
test(undefined,2) // 打印结果:1 2


function test(a = undefined, b ){ console.log(a); console.log(b) }
test(1,2) // 打印结果:1 2

  1. ** ****形参不设默认值即undefined,通过实参赋值****;****实参undefined,会使用形参设置的默认值 **<br />**
  2. - **ES5默认值写法**
  3. ```javascript
  4. // ES5 设置初始化值方法-----------------------------
  5. //短路运算写法
  6. function test(a, b){
  7. var a = arguments[0] || 'a设默认值',
  8. b = arguments[1] || 'b设默认值';
  9. console.log(a, b)
  10. }
  11. test();
  12. //使用typeof() 方法------------------------------
  13. function test(a, b){
  14. var a = typeof(arguments[0]) == 'undefined' ? 'a设默认值' : arguments[0],
  15. b = typeof(arguments[1]) == 'undefined' ? 'a设默认值' : arguments[1];
  16. console.log(a, b)
  17. }
  18. test();

📌 递归函数

递归函数实现形式 递归函数就是在函数体内部调用自己,使用时要注意函数终止条件,避免死循环 递归两个必要因素:递归方程,递归结束条件

  1. function getSum(x) {
  2. if (x==1) return 1
  3. return x + getSum(x - 1);
  4. };
  5. getSum(5)
  6. getSum(5) = 5 + getSum(5 - 1)
  7. getSum(4) = 4 + getSum(4 - 1)
  8. getSum(3) = 3 + getSum(3 - 1)
  9. getSum(2) = 2 + getSum(2 - 1)
  10. getSum(1) = 1 ——>当x == 1时,通过if条件直接返回数值1
  11. //解析
  12. getSum(5) = (5 + (4 + (3 + (2 + getSum(1))))
  13. getSum(5) = 5 + (4 + (3 + (2 + 1)))
  14. 结果:15

递归技巧

  • 假设递归函数已经写好
  • 寻找递推关系
  • 将递推关系的结构转换为递归体
  • 将临界条件加入到递归体中


小试牛刀——递归函数实现深拷贝

  1. // 使用递归方式,实现深拷贝
  2. //【深拷贝】:将数据的所有引用结构都拷贝一份, 数据在内存中独立
  3. //【浅拷贝】:只针对当前对象的属性进行拷贝, 属性引用类型不考虑
  4. 1.假设已经实现 clone ( o1, o2),将对象 o2 的成员拷贝一份交给 o1
  5. 2.寻找递推关系
  6. function clone( o1, o2){
  7. for(var key in o2){
  8. o1[key] = o2[key]; //需要考虑o2[key]时引用类型,再次使用clone函数,否则直接赋值
  9. }
  10. }
  11. 3.临界条件: 因为时for in 循环,没有成员遍历,自动结束
  12. 4.递归函数
  13. function clone(o1,o2){
  14. for(var key in o2){
  15. if(typeof o2[key] == 'object'){
  16. o1[key] = {};
  17. clone(o1[key],o2[key])
  18. }else{
  19. o1[key] = o2[key];
  20. }
  21. }
  22. }

📌 预编译

JavaScript运行三部曲
**

  • 语法分析:通篇检查低级语法错误,不执行
  • 预编译:内存中开辟空间,存放一些变量与函数
  • 解释执行:解释一行,执行一行

JavaScript预编译分析

预编译不仅仅发生在script内代码块执行前,大部分会发生在函数执行前


  • 页面产生便创建了GO全局对象【Global Object】—— window对象
  • 第一个脚本文件加载至完成
  • 通篇分析语法是否合法
  • 开始进行预编译GO【脚本代码块script执行前】

1、查找全局变量声明(包括隐式全局变量声明),变量名作为全局对象GO属性,值赋予undefined
2、查找function函数声明,函数名作为全局对象GO属性,值赋予函数体

  • 函数调用AO【函数执行前】

1、创建AO对象【Active Object】
2、查找函数形参即函数内变量声明,形参名即变量名作为AO对象属性,值为undefined
3、实参形参相统一,实参值赋给形参
4、查找函数声明,函数名作为AO对象属性,值赋予函数体
**

📌 暗示全局变量

暗示全局变量基于JavaScript 的两个特性

  • 可直接使用变量,甚至无需声明
  • 任何变量,如果未经声明,就为全局对象所有
  1. var a = 1; //函数体外声明的变量称为全局变量
  2. b = 2; // 无论函数体外或函数体内未声明的变量都称为暗示全局变量
  3. function fn() {
  4. var c = 3; //函数体内声明的变量称为局部变量
  5. d = 4; // 暗示全局变量
  6. }
  7. fn(); // 若不执行函数,则不会进行函数预编译,d 就不会提升为全局变量
  8. console.log(c); // error: c is not defined
  9. console.log(d); // 4


暗示全局变量与明确定义全局变量的不同之处?**

  • 使用var声明创建的全局变量,不能删除
  • 暗示全局变量,可以删除

暗示全局变量非变量:严格来讲暗示全局变量不是真正的变量,而是全局对象属性,属性可以通过delete操作符删除,但变量不可以

  1. 1 var global_var = 1;
  2. 2 global_novar = 2;
  3. 3 (function(){
  4. 4 global_fromfunc = 3;
  5. 5 });
  6. 6
  7. 7 //企图删除
  8. 8 delete global_var; //false
  9. 9 delete global_novar; //true
  10. 10 delete global_fromfunc; //true
  11. 11
  12. 12 typeof global_var; //"number"
  13. 13 typeof global_novar; //"undefined"
  14. 14 typeof global_fromfunc; //"undefined"

📋 课后作业

分析下列代码预编译过程

  1. 【题一】------------------------------------------------------------------
  2. function test() {
  3. return a;
  4. a = 1;
  5. function a() { }
  6. var a = 2;
  7. }
  8. console.log(test());
  9. 【分析过程】:
  10. GO:{
  11. testfunction test(){.....}
  12. test-AO:{
  13. a: undefined ——> function a(){}
  14. }
  15. }
  16. 【结果】:"function a(){}"
  17. return后面的a的赋值操作不执行
  18. 【题二】--------------------------------------------------------------------
  19. function test() {
  20. a = 1;
  21. function a() { }
  22. var a = 2;
  23. return a;
  24. }
  25. console.log(test());
  26. 【分析过程】:
  27. GO:{
  28. testfunction test(){...}
  29. test-AO:{
  30. a: undefined ——> function a(){} ——> 1 ——> 2
  31. }
  32. }
  33. 【结果】:2
  34. 1-执行test()函数会在GO中创建testAO局部作用域,开始进行预解析
  35. 2-首先将var声明的a变量提升当前AO顶部,赋值undefined
  36. 3-其次将声明的a函数作为值,赋给已声明的a变量,开始执行当前AO代码
  37. 4-自上而下,首相将1赋值给变量a,其次又将2赋值给变量2
  38. 5-最终a变量的值为2return变量a的值为2
  39. 【题三】--------------------------------------------------------------------------
  40. a = 1;
  41. function test(e) {
  42. function e() {}
  43. arguments[0] = 2;
  44. console.log(e);
  45. if (a) {
  46. var b = 3;
  47. }
  48. var c;
  49. a = 4;
  50. var a;
  51. console.log(b);
  52. f = 5;
  53. console.log(c);
  54. console.log(a);
  55. }
  56. var a;
  57. test(1)
  58. console.log(a);
  59. console.log(f);
  60. 【分析过程】:
  61. GO:{
  62. aundefined ——> 1
  63. f: 5
  64. test: function test(e) {...}
  65. test-AO:{
  66. b: undefined
  67. c: undefined
  68. a: undefined ——> 4
  69. e: undefined ——> 1 ——> function e() {} ——> 2
  70. }
  71. }
  72. 【结果】:2
  73. undefined
  74. undefined
  75. 4
  76. 1
  77. 5