一、函数的三种角色

  1. /*
  2. * 目标:
  3. * 1. 理解函数的三种角色;
  4. * 2. 学习利用函数的三种角色解决问题
  5. *
  6. * */
  7. // 在 js 中函数有三种角色的:
  8. // 1. 普通函数(函数名、形参、实参、返回值)
  9. function sum (a, b) {
  10. return a + b;
  11. } // 函数定义
  12. var result = sum(1, 2); // 函数执行
  13. console.log(result);
  14. // 普通函数执行的过程:
  15. // 1.1 新开辟私有作用域
  16. // 1.2 形参赋值(形参也是私有作用域中的私有变量)
  17. // 1.3 私有作用域中变量提升(变量只发生在当前作用域)
  18. // 1.4 函数代码执行
  19. // 1.5 私有作用域销毁(注意特殊情况作用域不销毁)
  20. // 2. 构造函数、类(new 构造函数):必须通过 new 调用时,函数才能成为构造函数;
  21. function Teacher(name, age, subject, from = '珠峰') {
  22. this.name = name;
  23. this.age = age;
  24. this.subject = subject;
  25. this.from = from;
  26. }
  27. let t1 = new Teacher('马宾', 27, 'JS'); // 此时 Teacher 被 new 调用,Teacher 才是真正成为一个构造函数
  28. // let t2 = Teacher('mabin', 27, 'JS'); 普通调用时,Teacher 还是普通函数
  29. // new 调用构造函数执行过程:
  30. // 2.1 新开私有作用域
  31. // 2.2 形参赋值
  32. // 2.3 私有作用域变量提升
  33. // 2.4 隐式的创建一个实例对象,把当前作用域中的 this 指向这个实例对象
  34. // 2.5 执行函数中代码 ;this.xxx = xxx 给实例添加私有属性
  35. // 2.6 隐式返回 this实例
  36. // 2.7 销毁私有作用域
  37. // 3. 对象,和普通对象一样,键值对的集合(操作起来和普通对象一样)
  38. function minus(a, b) {
  39. return a - b;
  40. }
  41. // console.dir(minus);
  42. // length: 函数形参个数
  43. // name: "minus" 函数的名字
  44. console.log(minus.name); // "minus"
  45. console.log(minus.length); // 2
  46. minus.by = '马宾';
  47. minus.getName = function () {
  48. console.log('my name is mabin');
  49. };
  50. console.dir(minus);
  51. minus.getName();
  52. // 我们把函数当成一个普通对象时,通过 函数名.属性名 = 属性值 的方式添加的属性都是函数对象的私有属性;
  53. // 当你需要访问这些属性时,只能通过 函数名.属性名 的方式;
  54. function Fn() {
  55. this.name = 'boy';
  56. }
  57. Fn.getName = function () {
  58. console.log('MY_NAME');
  59. }; // 把Fn当成一个对象添加一个私有属性
  60. // Fn.prototype.xxx = xxx; // 只有通过 Fn.prototype.xxx = xxx 这样的形式才是给 Fn 的原型添加
  61. let f1 = new Fn();
  62. // f1.getName(); // 实例能够使用的属性要么是私有属性(在构造函数中 this.xxx = xxx 得来的),要么就是实例所属类的原型(链)上的属性;
  63. Fn.getName(); //
  64. // 向上面这样把函数当成一个普通对象,给其添加的属性和方法称为 静态属性或方法;
  65. // 内置类 Array 的一个静态方法:
  66. // Array.isArray() 把 Array 当做普通对象使用,isArray 是一个静态方法;判断一个值是否是一个数组,如果是数组返回 true,不是数组返回 alse
  67. // ES6 新增的,注意老旧浏览器不兼容
  68. console.log(Array.isArray(1)); // false
  69. console.log(Array.isArray([1, 2])); // true

函数的三种角色.png

二、Object 和 Function 的关系

  1. // Object 和 Function 的关系
  2. // 1. Object 是 Function 的实例,所以 Object.__proto__ 指向 Function.prototype
  3. console.log(Object.__proto__ === Function.prototype); // true
  4. // 2. Function 是一个类,但是 Function.prototype 是一个对象,所以 Function.prototype 也有一个
  5. __proto__ 的属性,它的值指向 Object.prototype
  6. console.log(Function.prototype.__proto__ === Object.prototype);
  7. // __proto__ 是实例用来找原型的,Object 是构造函数,Object.__proto__ 找原型,Object 是谁的实例呢,是 Function 的实例,Object.__proto__ 找的就是 Function 的 prototype
  8. // Function.prototype 是对象,
  9. // 所以 Function.prototype.__proto__ 是在 prototype 的原型,
  10. // 就是在找对象的所属类的原型,对象所属类是 Object
  11. // 所以找到的 Object.prototype
  12. // Function 是一个类,也是一个函数,所以 Function 是自己的实例
  13. console.log(Function.__proto__ === Function.prototype); // true
  14. console.log(Function instanceof Function); // true

函数的三种角色2.png