javascript原型继承笔记

继承

虽然已经ES6,7,8时代了,但是今天重翻《JavaScript高级程序设计》继承这一块的知识,慢慢看,认真思考,看到组合继承时怀疑调用两遍函数,有点疑惑,后来发现寄生组合式继承改变了这个问题,带给我的思考挺多的,还是要多想,思考是最重要的。

原型链继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Parent() {
this.colors = ['red','blue','yellow'];
}

function Child() {}

Child.prototype = new Parent();
Child.prototype.constructor = Child;

var child1 = new Child();

child1.colors.push('orange');

console.log(child1.colors); //  ["red", "blue", "yellow", "orange"]

var child2 = new Child();

console.log(child2.colors); // ["red", "blue", "yellow", "orange"]

问题:1.引用类型的属性被所有实例共享 2.在创建 Child 的实例时,不能向Parent传参

借用构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Parent(name) {
this.name = name;
this.colors = ['red','blue','yellow'];
}

function Child(name) {
Parent.call(this,name);
}

var child1 = new Child("gzl1");

child1.colors.push('orange');

console.log(child1.colors); //  ["red", "blue", "yellow", "orange"]
console.log(child1.name); // gzl1

var child2 = new Child("gzl2");

console.log(child2.colors); // ["red", "blue", "yellow"]
console.log(child2.name); // gzl2

问题:方法都在构造函数中定义,每次创建实例都会创建一遍方法

组合继承

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
function Parent(name) {
this.name = name;
this.colors = ['red','blue','yellow'];
}

function Child(name,age) {
Parent.call(this,name);
this.age = age;
}

Child.prototype = new Parent();
Child.prototype.constructor = Child;

var child1 = new Child("gzl1",18);

child1.colors.push('orange');

console.log(child1.colors);//  ["red", "blue", "yellow", "orange"]
console.log(child1.name); // gzl1
console.log(child1.age); // 18

var child2 = new Child("gzl2",19);

console.log(child2.colors);// ["red", "blue", "yellow", "orange"]
console.log(child2.name); // gzl2
console.log(child2.age); // 19

问题:会调用两次父构造函数,且child1,2的原型中会有colors

原型式继承

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
function createObj(o) {
function F(){}
F.prototype = o;
return new F();
}
//ES5 Object.create 的模拟实现,将传入的对象作为创建的对象的原型
var person = {
name: 'gzl',
friends: ['x', 'y']
}

var person1 = createObj(person);
person1.name = 'gzl1'; // 并非修改了原型上的 name 值
person1.friends.push('z');

var person2 = createObj(person);
person2.name = 'gzl2'; // 并非修改了原型上的 name 值
person2.friends.push('c');


console.log(person1.name); // gzl1
console.log(person1.friends); // ["x", "y", "z", "c"]

console.log(person2.name); // gzl2
console.log(person2.friends); // ["x", "y", "z", "c"]

问题:包含引用类型的属性值始终都会共享相应的值,这点跟原型链继承一样

寄生式继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function createObj (o) {
var clone = Object.create(o);
clone.sayName = function () {
console.log(this.friends);
}
return clone;
}

var person = {
name: 'gzl',
friends: ['x', 'y']
}

var person1 = createObj(person);
person1.sayName(); //  ["x", "y"]

问题:跟借用构造函数模式一样,每次创建对象都会创建一遍方法。

寄生组合式继承

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
function Parent (name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}

Parent.prototype.getName = function () {
console.log(this.name)
}

function Child (name, age) {
Parent.call(this, name);
this.age = age;
}

inheritPrototype(Child,Parent);

function obj(o) {
function F() {}
F.prototype = o;
return new F();
}

function inheritPrototype(child, parent) {
var prototype = obj(parent.prototype);
prototype.constructor = child;
child.prototype = prototype;
}

var child1 = new Child("gzl1",18);
child1.colors.push('orange');
console.log(child1.colors); // ["red", "blue", "green", "orange"]

var child2 = new Child("gzl2",19);
console.log(child2.colors); // ["red", "blue", "green"]