Javascript继承

Javascript对象继承有很多种方法,但各有缺陷,这里只介绍一种经典的没有缺陷(不会引起被继承对象改变)的方法。

在three.js源码中摘出的几行代码如下:

THREE.InstancedBufferAttribute = function ( array, itemSize, meshPerAttribute ) {

	THREE.BufferAttribute.call( this, array, itemSize ); // 继承1

	this.meshPerAttribute = meshPerAttribute || 1;

};

THREE.InstancedBufferAttribute.prototype = Object.create( THREE.BufferAttribute.prototype ); // 继承2
THREE.InstancedBufferAttribute.prototype.constructor = THREE.InstancedBufferAttribute; // 继承3

 js继承最重要的就是如上3步操作。

我们使用一个简单的例子来说明:

function Animal(name, age) { // 构造函数
  this.name = name;
  this.age = age;
  this.showName = function () {
    console.log('in Animal:' + this.name);
  }
}
Animal.prototype.showAge = function() {
	console.log('in Animal:'+ this.age);
}
function Cat(name, age) { // 构造函数
  Animal.call(this, name, age); // 继承1
}
Cat.prototype = Object.create(Animal.prototype);  // 继承2
Cat.prototype.constructor = Cat;  // 继承3

var cat = new Cat('Black Cat', 2);
cat.showName();
cat.showAge();
console.log(cat.constructor);

var animal = new Animal('animal', '15');

animal.showAge();

 上面的代码放到一个html页面中的<script></script>标签内,在控制台输出:

in Animal:Black Cat
in Animal:2
Cat(name, age) {
  Animal.call(this, name, age);
}

in Animal:15

这里解释一下这三步操作。

继承1:

调用了js的call方法,call([thisObj[,arg1[, arg2[, [,.argN]]]]]),用法是父类.call(this,参数1,参数2,...)。作用是更改子类内部指针this指向父类,这样一来,子类就拥有了父类的所有方法,但只包括父类构造函数function 父类名(){}中的方法,不包含父类.prototype.xxx(){}方法。比如上面例子中:showName 方法被继承。而prototype.showAge 方法并没有,所以需要继承2.

继承2:

继承2则使得prototype.showAge 方法被继承。但由于使用了继承2,Cat类的prototype.constructor也就被改变了,所以需要继承3.

继承3:

还原Cat类的constructor。这个步骤省略了不会有任何不良影响,因为Cat的prototype是利用Object.create创建的,这是对Animal.prototype的一份拷贝。唯一不同的只是Cat的所有实例的constructor都指向了Animal而已,而对象实例化的时候,无论是Cat的构造函数还是Animal的构造函数,都会得到执行。

相关推荐