继承深入、call_apply、圣杯模式、模块化(十二)

2020/6/12 JS

# 一、继承

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

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

通过更改构造函数prototype属性可以实现继承。

Professor.prototype = {
  name: 'Mr. Zhang',
  tSkill: 'JAVA'
}
function Professor() {}

var professor = new Professor();

Teacher.prototype = professor;
function Teacher() {
  this.name = 'Mr. Wang';
  this.mSkill = 'JS/JQ';
}

var teacher = new Teacher();

Student.prototype = teacher;
function Student() {
  this.name = 'Mr. Li';
  this.pSkill = 'HTML/CSS';
}

var student = new Student();
console.log(student);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 原型继承特点

  1. Target.prototype = Origin.prototype 只会继承Origin构造函数原型上的属性和方法。
  2. 不会继承Orgin构造函数自身的属性和方法。
  3. 在Target.prototype上面新增属性和方法,Origin.prototype也会同步更改(指向同一对象)。
//公共原型
function Teacher() {
  this.name = 'Mr. Li';
  this.tSkill = 'JAVA';
}

Teacher.prototype = {
  pSkill: 'JS/JQ'
}

var t = new Teacher();
console.log(t);

function Student() {
  this.name = 'Mr. Wang';
}

Student.prototype = Teacher.prototype;
Student.prototype.age = 18;

var s = new Student();

console.log(s);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 二、call_apply

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

Teacher.prototype.wife = 'Ms. Liu';

function Teacher(name, mSkill) {
  this.name = name;
  this.mSkill = mSkill;
}

function Student(name, mSkill, age, major) {
  Teacher.apply(this, [name, mSkill]);
  this.age = age;
  this.major = major;
}

var student = new Student('Mr. Zhang', 'JS/JQ', 18, 'Computer');
console.log(student);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 三、圣杯模式

  1. 创建Buffer构造函数。
  2. Buffer构造函数继承Origin构造函数。
  3. Target构造函数继承Buffer构造函数实例化后的对象。
  4. 此时Target构造函数原型和Origin构造函数原型就不再指向同一对象。
  5. 实例化后的target对象继承了Origin构造函数原型上的属性和方法。
function Teacher() {
  this.name = 'Mr. Li';
  this.tSkill = 'JAVA';
}

Teacher.prototype = {
  pSkill: 'JS/JQ'
}

var t = new Teacher();
console.log(t);

function Student() {
  this.name = 'Mr. Wang';
}

function Buffer() {}
Buffer.prototype = Teacher.prototype;
var buffer = new Buffer();
Student.prototype = buffer;
Student.prototype.age = 18;

var s = new Student();
console.log(s);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 封装原型继承

function inherit(Target, Origin) {
  function Buffer() {}
  Buffer.prototype = Origin.prototype;
  Target.prototype = new Buffer();
  Target.prototype.constructor = Target;
  Target.prototype.super_class = Origin;
}

function Teacher() {}
function Student() {}
inherit(Student, Teacher);
var s = new Student();
var t= new Teacher();

console.log(s);
console.log(t);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# IIFE实现封装继承方法

var inherit = (function () {
  var Buffer = function () { }
  return function (Target, Origin) {
    Buffer.prototype = Origin.prototype;
    Target.prototype = new Buffer();
    Target.prototype.constructor = Target;
    Target.prototype.super_class = Origin;
  }
})();

Teacher.prototype.name = 'Mr. Zhang';
function Teacher() { }
function Student() { }
inherit(Student, Teacher);
Student.prototype.age = 18;
var s = new Student();
var t = new Teacher();

console.log(s);
console.log(t);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 四、模块化

  1. 防止全局污染。
  2. 利于后期维护。
  3. 二次开发。
var initProgrammer = (function () {
  var Programmer = function () {}
  Programmer.prototype = {
    name: '程序员',
    tool: '计算机',
    work: '编写应用程序',
    duration: '10个小时',
    say: function () {
      console.log('我是一名' + this.myName + this.name + ', 我的工作是用' + this.tool + this.work + ', 我每天工作' + this.duration + ',我的工作需要用到' + this.lang.toString() + '。');
    }
  }

  function FrontEnd() {}
  function BackEnd() {}

  inherit(FrontEnd, Programmer);
  inherit(BackEnd, Programmer);

  FrontEnd.prototype.lang = ['HTML', 'CSS', 'JavaScript'];
  FrontEnd.prototype.myName = '前端';

  BackEnd.prototype.lang = ['Node', 'Java', 'SQL'];
  BackEnd.prototype.myName = '后端';

  return {
    FrontEnd: FrontEnd,
    BackEnd: BackEnd
  }
})();

var frontEnd = new initProgrammer.FrontEnd();
var backEnd = new initProgrammer.BackEnd();
frontEnd.say();
backEnd.say();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Last Updated: 2022/7/21 10:52:53
Genshin Impact bgm
Genshin Impact