js 的继承以及 call && apply
在 js 中 es6 新增了 class 然后通过 extends 来实现继承的方式,但其原理都是在 es5 的基础上实现的,在 es5 中大致存在这几种继承的方式:
1、原型继承
例如 function dog () {
this.classType = '犬科';
this.className = '狗';
}
function yellowDog () {
this.name = '黄狗';
}
yellowDog.prototype = new dog();
此时,dog 就成为了 yellowDog 的原型,yellowDog 也具有了 classType 以及 className 的属性;
2、构造继承
构造继承是指在构造函数中去继承
例如 function dog () { }
function yellowDog () {
dog.call(this);
this.name = '黄狗
}
此时,dog 的 classType 等属性并不是作为 yellowDog 原型链的属性,而是成为了 yellowDog 的属性;
3、实例继承
例如: function animal () { this.classType = '犬科' }
function yellowDog () {
var obj = new animal()
obj.name = '黄狗'
return obj
}
继承的方式基本就这三种,在这三种的基础上还可以去延伸更过的方法,比如将以上方法组合,或者利用 for ... in ... 遍历一个构造函数,然后去赋值给其中的一个构造函数的原型等等;
在继承中我们经常要考虑的一个问题就是 this 转向的问题,进行 this 转向的时候用到的方法基本就是 call 和 apply;
call 和 apply 方法其实来源本身就都是继承于 Funcition.prototype ,所以在 数组、对象、函数中是都可以使用 call 和 apply 的;
call 和 apply 的作用都是指定函数内部的 this,进行 this 转向新的实例对象;区别就在于,call 方法除了接收 this 参数外,还可以接收很多的参数,而 apply 除了接收 this 参数外,其余的参数需要通过数组的形式进行传递;例如:
parament.call(this, 2, 3, 4) parament.apply(this, [ 2, 3, 4])
例如: es5原型以及原型链
function objParent () { this.nationality = 'China'; } objParent.prototype.objParentType = _ =>'原型 of parent'; var objParentA = new objParent(); // 通过原型链继承 function objChild (name) { this.name = name; this.age = 10; this.sex = '男'; this.indocFn = function () { return 'my name is child, and I am is a student in shenglilu school.' } } objChild.prototype = new objParent(); // 通过 call 继承,和原型链继承的区别就是不能继承父类的原型 // function objChild (name) { // objParent.call(this); // 继承objParent // this.name = name; // this.age = 10; // this.sex = '男'; // this.indocFn = function () { // return 'my name is child, and I am is a student in shenglilu school.' // } // } objChild.prototype.address = '上海市徐汇区'; // 定义objChild 的原型 var objChildA = new objChild('child-A'); console.log(objChildA.__proto__.__proto__.objParentType()); // 原型 of parent
es6 的原型以及原型链
class objParent { constructor (x, y) { this.nationality = 'China'; } objParentType () { return '原型 of parent'; } } var objParentA = new objParent(); console.log(objParentA); class objChild extends objParent { constructor(x, y, name) { super(x, y); // 将this 指向 objChild 的同时,向父类中传递参数 this.name = name; this.age = 10; this.sex = '男'; } indocFn () { return 'my name is child, and I am is a student in shenglilu school.' } } var objChildA = new objChild( 'x', 'y','child-A'); console.log(objChildA.__proto__.__proto__.objParentType()); // 原型 of parent