一、函数

函数: 在计算机语言中,函数是拥有固定功能和逻辑的代码块。它只需要声明一次,然后就可以无限次执行。在面向对象(OOP,Object-Oriented-Programming)的语言也叫做方法。

1.1 理解函数意义

先来考虑这样一个需求:

需求:有一个数total,值是10,;
1、给total加上10,
2、再给total除以2,
3、再给total再乘以3,
4、再给total加上5
5、最后再把total的结果输出到控制台
6、以上功能重复3次

  1. var total = 10;
  2. total += 10;
  3. total /= 2;
  4. total *= 3;
  5. total += 5;
  6. console.log(total);
  7. var total = 10;
  8. total += 10;
  9. total /= 2;
  10. total *= 3;
  11. total += 5;
  12. console.log(total);
  13. var total = 10;
  14. total += 10;
  15. total /= 2;
  16. total *= 3;
  17. total += 5;
  18. console.log(total);

上面的代码有一个坏处,这样的方式会导致页面中存在大量的重复的代码,也降低了开发效率。
这样的情况,我们发现这些代码都相同,干的事情也一样,我们能不能有个东西,把这些代码存起来,然后等需要的时候把这个东西拿出来跑一下子,就能这样的功能呢?这个东西就是函数。

  1. function fn() {
  2. var total = 10;
  3. total += 10;
  4. total /= 2;
  5. total *= 3;
  6. total += 5;
  7. console.log(total);
  8. }
  9. fn();
  10. fn();
  11. fn();

1.2 函数语法

标准函数语法:
函数能发挥作用,是由两部分组成:

  1. 函数声明
    1.1 使用 function 关键字声明函数变量,fn 也是变量,函数变量叫做函数名; function fn
    1.2 书写形参入口的小括号 function fn ()
    1.3 书写函数体的花括号 function fn () {}
    1.4 把具体的逻辑写在花括号里面,花括号叫做函数体
  2. 函数执行(调用)
    函数执行就是函数名后面紧跟着一个小括号,形如 fn();
    函数执行除了表示让函数执行,还代表着得到函数执行的结果,这个结果叫做函数的【返回值】。例如isNaN(‘abc’),就是函数名和小括号的组合的意思是:isNaN 这个函数执行,同时获取了 isNaN 这个函数执行的结果,这个结果就是 判断 字符串 ‘abc’ 转换成数字后是不是 NaN 的结果,这个结果是 true,就是说 isNaN(‘abc’) 也表示 这个结果 true,及 isNaN(‘abc’) 的返回值是 true。

1.3 函数的参数机制

参数就是函数的入口,当我们在函数中封装一个功能,我们希望我们给他什么,它帮我们处理啥。配合函数的定义和执行两部分;参数对应这两个部分,也有两部分构成:

  • 函数声明阶段: 形参,形参是函数内部的变量,它也是用来代表和存储值的;
  • 函数执行阶段:实参,实参是给形参赋值的具体值。就是说函数执行时,形参所代表的具体的值。
  1. // 求和函数
  2. function sum(a, b) {
  3. // a, b都是形参
  4. console.log(a, b);
  5. var total = 0;
  6. total = a + b;
  7. console.log(total);
  8. }
  9. sum(10, 20); // 10 和 20 是实参,当函数执行时,函数的形参 a 本次拿到的值是10,b 本次拿到20;实参的位置和形参是一一对应的。
  10. sum(1); // 1是实参,a 本次拿到的是1,另一个没传,如果没传是 b 获取到时默认值 undefined
  11. sum(); // 没有实参,此时 a,b 都是 undefined
  12. sum(4, 5, 6); // 4, 4, 6都是实参,a 是 4, b 是 5,没有人接收 6

1.4 函数的返回值机制

1.4.1 函数返回值机制

函数除了我们给他啥,它帮我们处理啥,还有一个重要的事情就是,把处理结果给我们。例如 isNaN(),会把函数执行的结果返回给我们。我们写的函数也该有这样的功能。

我们这里有一个求和函数,我们希望求和完成后可以拿到求得的两数之和:

  1. function sum(a, b) {
  2. var total = 0;
  3. total = a + b;
  4. console.log(total)
  5. }
  6. var result = sum(1, 2);
  7. console.log(result) // undefined
  8. console.log(total); // Uncaught ReferenceError: ...

引发报错的原因:total 是在函数体内部声明的变量,这种声明在函数体内部的变量称为私有变量,而私有变量在函数外部是无法访问的,这是由于闭包机制导致的。

闭包(closure):函数会保护函数体内部的变量不被外界所干扰的机制成为闭包;

? 这个时候怎么拿到total? 这个时候就需要函数的返回值机制了: 函数的返回值机制:把函数的运行结果(或者函数中某些信息)指定为函数的返回结果给到函数外部。在函数中使用 return 关键字指定函数返回值。

修改后的求和函数代码:

  1. function sum(a, b) {
  2. var total = 0;
  3. total = a + b;
  4. return total;
  5. }
  6. var result = sum(1, 2);
  7. console.log(result); // 3
  8. console.log(sum(1, 2));

1.4.2 函数返回值的细节问题:

  1. return 用于指定函数返回值,那么 return 啥函数返回值是啥
  2. 如果函数内部没有 return 或者 return 后面啥也没写,那么函数的返回值是 undefined
  3. return 关键字还有一个重要作用————强制结束 return 后面的代码。(return后面的代码不执行)
  4. return 永远返回一个值,如果是一个表达式,return 会等着表达式求值完成,然后再把值返回。

二、选项卡

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>珠峰-选项卡</title>
  6. <style>
  7. * {
  8. margin: 0;
  9. padding: 0;
  10. }
  11. ul, li {
  12. list-style: none;
  13. }
  14. .wrapper {
  15. margin: 30px auto;
  16. width: 800px;
  17. }
  18. .header {
  19. width: 602px;
  20. border: 1px solid #000;
  21. }
  22. .header:after {
  23. display: block;
  24. content: '';
  25. visibility: hidden;
  26. clear: both;
  27. }
  28. .header li {
  29. float: left;
  30. width: 200px;
  31. height: 40px;
  32. line-height: 40px;
  33. text-align: center;
  34. font-size: 18px;
  35. cursor: pointer;
  36. }
  37. .header li.active {
  38. background: yellow;
  39. }
  40. .header li:nth-child(2) {
  41. border-left: 1px solid #000;
  42. border-right: 1px solid #000;
  43. }
  44. .wrapper div {
  45. display: none;
  46. height: 200px;
  47. width: 602px;
  48. border: 1px solid #000;
  49. line-height: 200px;
  50. text-align: center;
  51. font-size: 20px;
  52. }
  53. .wrapper div.active {
  54. display: block;
  55. }
  56. </style>
  57. </head>
  58. <body>
  59. <div class="wrapper" id="wrapper">
  60. <ul id="header" class="header">
  61. <li class="active">实事</li>
  62. <li>音乐</li>
  63. <li>时尚</li>
  64. </ul>
  65. <div class="active">实事</div>
  66. <div>音乐</div>
  67. <div>时尚</div>
  68. </div>
  69. <script src="js/7-4-tab之函数封装.js"></script>
  70. </body>
  71. </html>
  1. var wrapper = document.getElementById('wrapper');
  2. var header = document.getElementById('header');
  3. var tabList = header.getElementsByTagName('li');
  4. var divList = wrapper.getElementsByTagName('div');
  5. // 1. 自定义属性方式解决问题
  6. for (var i = 0; i < tabList.length; i++) {
  7. // 在点击事件触发时,i 已经变成了它 tabList.length,但是再循环的过程中第几轮循环 i 就是几,所以我们应该把i存起来。存在哪里呢?因为没给 li 都是一个元素对象,而我们说对象可以添加属性存储信息,存在每个 li 元素身上;
  8. tabList[i].myIndex = i;
  9. // i = 0时 tabList[i] 代表第一个 li 元素,所以给它记录一下自己的索引 0
  10. // i = 1时 tabList[i] 代表第二个 li 元素,它记录自己的索引 1
  11. // i = 2时 tabList[i] 代表第三个 li 元素,它记录自己的索引 2
  12. tabList[i].onclick = function () {
  13. for (var j = 0; j < tabList.length; j++) {
  14. tabList[j].className = '';
  15. divList[j].className = '';
  16. }
  17. // 上面我们记录了每个 li 的索引,在这里需要取出来?这里有一个关键点,就是我们点击的哪一个,然后就取哪一个的 myIndex 属性
  18. // 在事件函数中,this 代表本次触发事件的元素对象
  19. var myIndex = this.myIndex;
  20. tabList[myIndex].className = 'active';
  21. divList[myIndex].className = 'active';
  22. }
  23. }