Justin's Words

JavaScript 继承

call & apply

callapply 作用基本相同,都可以让一个对象引用另一个对象或它的方法,两者唯一的不同call 接受函数参数的方式是一个个列出来,apply 接受函数参数的方式是一个数组。

call定义

1
fun.call(thisArg[, arg1[, arg2[, ...]]])

apply定义

1
fun.apply(thisArg, [argsArray])

call 的继承

1
2
3
4
5
6
7
8
9
10
11
12
13
function Animal(name){
this.name = name;
this.showName = function(){
alert(this.name);
}
}

function Cat(name){
Animal.call(this, name);
}

var cat = new Cat("Black Cat");
cat.showName();

apply 的继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Class0() {
this.showSub = function(a,b) {
alert(a-b);
}
}

function Class1() {
this.showAdd = function(a,b) {
alert(a+b);
}
}

function Class2() {
Class10.apply(this);
Class11.apply(this);
}

callapply 的继承方法都不能继承原型链。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Animal(name){
this.name = name;
this.showName = function(){
alert(this.name);
}
}

Animal.prototype.say = function() {
console.log('Hello ' + this.name);
}

function Cat(name){
Animal.call(this, name);
}

var cat = new Cat("Black Cat");
cat.say(); // Uncaught TypeError: cat.say is not a function

原型继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var Mammal = function(name) {
this.name = name;
}
Mammal.prototype.greeting = function() {
console.log('Hello ' + this.name + "!");
}

var Cat = function(name) {
this.name = name;
}
Cat.prototype = new Mammal();
Cat.prototype.constructor = Cat; // 否则 Cat 的实例的构造函数将会是 Mammal 的构造函数

var cat = new Cat('Garfield');
cat.greeting();

复杂点例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function Mammal(name) {
this.name = name;
this.offspring = [];
}
Mammal.prototype.haveABaby = function() {
var newBaby = new Mammal("Baby " + this.name);
this.offspring.push(newBaby);
return newBaby;
}
Mammal.prototype.toString = function() {
return '[Mammal "' + this.name + '"]';
}

Cat.prototype = new Mammal();
Cat.prototype.constructor = Cat;

function Cat(name) {
this.name = name;
}
Cat.prototype.toString = function() {
return '[Cat "' + this.name + '"]';
}

haveABaby 继承还可以这样写:

1
2
3
4
5
6
7
8
9
10
11
12
Mammal.prototype.haveABaby = function() {
var newBaby = new this.constructor("Baby " + this.name);
this.offspring.push(newBaby);
return newBaby;
}

// 这里的 this.parent 类似典型 OO 语言中的 super
Cat.prototype.parent = Mammal.prototype;
Cat.prototype.haveABaby = function() {
var theKitten = this.parent.haveABaby.call(this);
return theKitten;
}

Object.create()

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
// Shape - superclass
function Shape() {
this.x = 0;
this.y = 0;
}

// superclass method
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info('Shape moved.');
};

// Rectangle - subclass
function Rectangle() {
Shape.call(this); // call super constructor.
}

// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype)
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

rect instanceof Rectangle; // true
rect instanceof Shape; // true
rect.move(1, 1) // Outputs, 'Shape moved.'

自制继承方法

来自 OOP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Function.prototype.inheritsFrom = function(parentClassOrObject) {
if (parentClassOrObject.constructor == Function) {
//Normal Inheritance
this.prototype = new parentClassOrObject;
this.prototype.constructor = this;
this.prototype.parent = parentClassOrObject.prototype;
} else {
//Pure Virtual Inheritance
this.prototype = parentClassOrObject;
this.prototype.constructor = this;
this.prototype.parent = parentClassOrObject;
}
return this;
}

Cat.inheritsFrom(Mammal);

参考: