JS基础-02:继承
常用继承方式
概要内容
方式一:调整类型原型的__proto__ 、 Object.setPrototypeOf 、Object.create
jsx
function Animal(name){
this.name = name;
this.arr = [1,2,3];
}
Animal.prototype.address = {location:"山里"};
function Tiger(name){
this.name = name;
this.age = 10;
Animal.call(this,this.name);
}
Tiger.prototype.__proto__ = Animal.prototype;
// 等同 es7 方法:Object.setPrototypeOf(Tiger.prototype,Animal.prototype);
// or Tiger.prototype = Object.create(Animal.prototype);
Tiger.prototype.say = function(){
return "说话";
}
let tiger = new Tiger("xxx");
console.log(`父类实例属性:${tiger.arr}`);//父类实例属性:1,2,3
console.log(`父类原型属性:${JSON.stringify(tiger.address)}`);//父类原型属性:{"location":"山里"}
console.log(`子类实例属性:${tiger.age}`);//子类实例属性:10
console.log(`子类原型属性:${tiger.say()}`);//子类原型属性:说话
方法二:利用自定义createObject
jsx
function Animal(name){
this.name = name;
this.arr = [1,2,3];
}
Animal.prototype.address = {location:"山里"};
function Tiger(name){
this.name = name;
this.age = 10;
Animal.call(this,this.name);
}
function createObject(parentPrototype){
function Fn(){}
Fn.prototype = parentPrototype;
return new Fn();
}
Tiger.prototype = createObject(Animal.prototype);
Tiger.prototype.say = function(){
return "说话";
}
let tiger = new Tiger("xxx");
console.log(`父类实例属性:${tiger.arr}`);//父类实例属性:1,2,3
console.log(`父类原型属性:${JSON.stringify(tiger.address)}`);//父类原型属性:{"location":"山里"}
console.log(`子类实例属性:${tiger.age}`);//子类实例属性:10
console.log(`子类原型属性:${tiger.say()}`);//子类原型属性:说话
方式三:利用ES6 Class extends
jsx
class Animal {
address = {location:"山里"};
constructor(name){
this.name = name;
this.arr = [1,2,3];
}
}
class Tiger extends Animal {
constructor(name){
super(name);
this.age = 10;
}
say(){
return "说话";
}
}
let tiger = new Tiger("xxx");
console.log(`父类实例属性:${tiger.arr}`);//父类实例属性:1,2,3
console.log(`父类原型属性:${JSON.stringify(tiger.address)}`);//父类原型属性:{"location":"山里"}
console.log(`子类实例属性:${tiger.age}`);//子类实例属性:10
console.log(`子类原型属性:${tiger.say()}`);//子类原型属性:说话
子类不写constructor时,创建子类实例时,会默认调用父类构造方法
jsxclass Animal { constructor() { console.log("Animal.constructor"); } } class Person extends Animal { } let p = new Person(); //输出:Animal.constructor
子类写了构造函数,然后继承了父类, 就必须在构造函数调用super or 返回一个对象
jsxclass Animal { constructor() { console.log("Animal.constructor"); } } class Person extends Animal { //! 说明:子类不写constructor时,创建子类实例时,会默认调用父类构造方法 constructor() { //console.log(this); //! 子类写了构造函数,然后继承了父类, 就必须在构造函数调用super //! 注意:super之前不要引用this, 否则会报错:Must call super constructor in derived class before accessing 'this' or returning from derived constructor super(); console.log("Person.constructor") //! 或者:返回一个对象 // return { name: "Person" } } } let p = new Person();
总结
- 推荐使用es6的class来进行继承(注意:继承链不宜过长,否则会导致性能问题。更多细节:继承与原型链)
- 不推荐通过改变类型原型的__proto__指向的方式(兼容性不好,而且将
__proto__
设置为非对象的值会静默失败,不会抛出错误。更多细节:继承与原型链)
...
以上:如发现有问题,欢迎留言指出,我及时更正