一、继承


通过 new 实例化出来的对象继承构造函数的原型。

  1. function Person() {}
  2. Person.prototype.name = 'Lucy';
  3. var p = new Person();
  4. console.log(p);

image.png

通过更改构造函数 prototype 属性可以实现继承。
但这种继承没有那么完美,Student继承了Professor、Teacher的所有属性,有些是Student不需要的,如果新建实例对象占用内存也大

  1. Professor.prototype = {
  2. name: 'Mr. Zhang',
  3. tSkill: 'JAVA'
  4. }
  5. function Professor() {}
  6. var professor = new Professor();
  7. Teacher.prototype = professor;
  8. function Teacher() {
  9. this.name = 'Mr. Wang';
  10. this.mSkill = 'JS/JQ';
  11. }
  12. var teacher = new Teacher();
  13. Student.prototype = teacher;
  14. function Student() {
  15. this.name = 'Mr. Li';
  16. this.pSkill = 'HTML/CSS';
  17. }
  18. var student = new Student();
  19. console.log(student);

image.png

原型继承特点


1.Target.prototype = Origin.prototype 只会继承 Origin 构造函数原型上的属性和方法。
2.不会继承 Orgin 构造函数自身的属性和方法。
3.在 Target.prototype 上面新增属性和方法,Origin.prototype 也会同步更改(指向同一对象)。

  1. //公共原型
  2. function Teacher() {
  3. this.name = 'Mr. Li';
  4. this.tSkill = 'JAVA';
  5. }
  6. Teacher.prototype = {
  7. pSkill: 'JS/JQ'
  8. }
  9. var t = new Teacher();
  10. console.log(t);
  11. function Student() {
  12. this.name = 'Mr. Wang';
  13. }
  14. Student.prototype = Teacher.prototype;
  15. Student.prototype.age = 18;
  16. var s = new Student();
  17. console.log(s);

image.png

二、call_apply


通过 call、apply 借用其它构造函数的属性和方法,但无法继承该构造函数原型上的属性和方法
这不是继承这是借用,Studnet借用Teacher中的函数与方法

  1. Teacher.prototype.wife = 'Ms. Liu';
  2. function Teacher(name, mSkill) {
  3. this.name = name;
  4. this.mSkill = mSkill;
  5. }
  6. function Student(name, mSkill, age, major) {
  7. Teacher.apply(this, [name, mSkill]);
  8. //通过改变this的指向,返回Student的this,而不是Teacher中的this
  9. this.age = age;
  10. this.major = major;
  11. }
  12. var student = new Student('Mr. Zhang', 'JS/JQ', 18, 'Computer');
  13. console.log(student);

image.png

三、圣杯模式

还是不好,改变Teacher的原型就改变了Student的原型,改了Student就改了Teacher
因为它们俩的原型指向同一个空间,储存地址一样
image.png

  1. function Teacher() {
  2. this.name = 'Mr. Li';
  3. this.tSkill = 'JAVA';
  4. }
  5. Teacher.prototype = {
  6. pSkill: 'JS/JQ'
  7. }
  8. var t = new Teacher();
  9. console.log(t);
  10. function Student() {
  11. this.name = 'Mr. Wang';
  12. }
  13. Student.prototype = Teacher.prototype;
  14. Student.prototype.age = 18;
  15. var s = new Student();
  16. console.log(s);

image.png

1.创建 Buffer 构造函数。
2.Buffer 构造函数继承 Origin 构造函数。
3.Target 构造函数继承 Buffer 构造函数实例化后的对象。
4.此时 Target 构造函数原型和 Origin 构造函数原型就不再指向同一对象。
5.实例化后的 target 对象继承了 Origin 构造函数原型上的属性和方法。

利用Buffer的实例对象,实例对象是新的空间
Student实例对象->Student.prototype(Buffer实例对象)->Buffer.prototype(Teacher.prototype)->Object.prototype

  1. function Teacher() {
  2. this.name = 'Mr. Li';
  3. this.tSkill = 'JAVA';
  4. }
  5. Teacher.prototype = {
  6. pSkill: 'JS/JQ'
  7. }
  8. var t = new Teacher();
  9. console.log(t);
  10. function Student() {
  11. this.name = 'Mr. Wang';
  12. }
  13. function Buffer() {}
  14. Buffer.prototype = Teacher.prototype;
  15. var buffer = new Buffer();
  16. Student.prototype = buffer;
  17. //Student.prototype = new Buffer();//也行
  18. Student.prototype.age = 18;
  19. var s = new Student();
  20. console.log(s);

image.png

封装原型继承

  1. function inherit(Target, Origin) {
  2. function Buffer() {}
  3. Buffer.prototype = Origin.prototype;
  4. Target.prototype = new Buffer();
  5. Target.prototype.constructor = Target;
  6. Target.prototype.super_class = Origin;
  7. }
  8. function Teacher() {}
  9. function Student() {}
  10. inherit(Student, Teacher);
  11. var s = new Student();
  12. var t= new Teacher();
  13. console.log(s);
  14. console.log(t);
  1. function inherit(Target, Origin) {
  2. function Buffer() { }
  3. Buffer.prototype = Origin.prototype;
  4. Target.prototype = new Buffer();
  5. Target.prototype.constructor = Target;
  6. Target.prototype.super_class = Origin;
  7. }
  8. // function Teacher() { }
  9. // function Student() { }
  10. function Teacher() {
  11. this.name = 'Mr. Li';
  12. this.tSkill = 'JAVA';
  13. }
  14. function Student() {
  15. this.name = 'Mr. Wang';
  16. }
  17. inherit(Student, Teacher);
  18. var s = new Student();
  19. var t = new Teacher();
  20. console.log(s);
  21. console.log(t);

image.png

IIFE实现封装继承方法

Buffer形成闭包,但Buffer虽然没有重置,但这里面不受影响

  1. var inherit = (function () {
  2. var Buffer = function () { }
  3. return function (Target, Origin) {
  4. Buffer.prototype = Origin.prototype;
  5. Target.prototype = new Buffer();
  6. Target.prototype.constructor = Target;
  7. Target.prototype.super_class = Origin;
  8. }
  9. })();
  10. Teacher.prototype.name = 'Mr. Zhang';
  11. function Teacher() { }
  12. function Student() { }
  13. inherit(Student, Teacher);
  14. Student.prototype.age = 18;
  15. var s = new Student();
  16. var t = new Teacher();
  17. console.log(s);
  18. console.log(t);

image.png

四、模块化


1.防止全局污染。
2.利于后期维护。
3.二次开发。

返回构造函数在外部使用,Programmer不返回

  1. var inherit = (function () {
  2. var Buffer = function () { }
  3. return function (Target, Origin) {
  4. Buffer.prototype = Origin.prototype;
  5. Target.prototype = new Buffer();
  6. Target.prototype.constructor = Target;
  7. Target.prototype.super_class = Origin;
  8. }
  9. })();
  10. var initProgrammer = (function () {
  11. var Programmer = function () {}
  12. Programmer.prototype = {
  13. name: '程序员',
  14. tool: '计算机',
  15. work: '编写应用程序',
  16. duration: '10个小时',
  17. say: function () {
  18. console.log('我是一名' + this.myName + this.name + ', 我的工作是用' + this.tool + this.work + ', 我每天工作' + this.duration + ',我的工作需要用到' + this.lang.toString() + '。');
  19. }
  20. }
  21. function FrontEnd() {}
  22. function BackEnd() {}
  23. inherit(FrontEnd, Programmer);
  24. inherit(BackEnd, Programmer);
  25. FrontEnd.prototype.lang = ['HTML', 'CSS', 'JavaScript'];
  26. FrontEnd.prototype.myName = '前端';
  27. BackEnd.prototype.lang = ['Node', 'Java', 'SQL'];
  28. BackEnd.prototype.myName = '后端';
  29. return {
  30. FrontEnd: FrontEnd,
  31. BackEnd: BackEnd
  32. }
  33. })();
  34. var frontEnd = new initProgrammer.FrontEnd();
  35. var backEnd = new initProgrammer.BackEnd();
  36. frontEnd.say();
  37. backEnd.say();

总结

image.png

  1. var func1 = (function () {
  2. var a = 1;
  3. console.log('a',a)
  4. return function () {
  5. a = 2
  6. console.log('a',a)
  7. }
  8. })();
  9. console.log(window)

func1未使用,但里面的方法运行了,打印window有,func1是返回的函数
image.png
image.png
打印
说明函数运行了

  1. var func1 = (function () {
  2. var a = 1;
  3. console.log('a', a)
  4. // return function () {
  5. // a = 2
  6. // console.log('a', a)
  7. // }
  8. })();
  9. console.log(window)

image.png

五、作业


使用模块化开发实现以下功能:
1.打印一个参数值以内能被3或5或7整除的数。
2.打印斐波那契数列的第N位。
3.打印从0到一个数的累加值。

  1. window.onload = function () {
  2. console.log(initFib(10));
  3. console.log(initDiv(100));
  4. console.log(initSum(100));
  5. }
  6. var initFib = (function () {
  7. function fib(n) {
  8. if (n <= 0) {
  9. return 0;
  10. }
  11. if (n <= 2) {
  12. return 1;
  13. }
  14. return fib(n - 1) + fib(n - 2);
  15. }
  16. return fib;
  17. })();
  18. var initDiv = (function () {
  19. function div(n) {
  20. var arr = [];
  21. for (var i = 0; i <= n; i++) {
  22. if (i % 3 === 0 || i % 5 === 0 || i % 7 === 0) {
  23. arr.push(i);
  24. }
  25. }
  26. return arr;
  27. }
  28. return div;
  29. })();
  30. var initSum = (function () {
  31. function sum(n) {
  32. var sum = 0;
  33. for (var i = 0; i <= n; i++) {
  34. sum += i;
  35. }
  36. return sum;
  37. }
  38. return sum;
  39. })();