首先定义一个父类:
function Animal(name) { this.name = name || '动物' this.sleep = function () { console.log(this.name + '正在睡觉!') } } Animal.prototype.eat = function (food) { console.log(this.name + '正在吃:' + food) }
特点: 1、子类的原型指向父类的实例 缺点: 1、无法多继承 2、无法向父类的构造传参 3、来自原型对象的引用属性是所有实例共享的
function Cat() { } Cat.prototype = new Animal() Cat.prototype.name = '猫' // Test code const cat = new Cat() console.log(cat.name) // 猫 cat.eat('鱼') // 猫正在吃:鱼 cat.sleep() // 猫正在睡觉! console.log(cat instanceof Cat) // true console.log(cat instanceof Animal) // true
特点: 1、子类的构造中进行父类构造的调用 优点: 1、实现了多继承,想继承哪个直接在子类构造里面call或者apply哪个就行 2、避免所有子类实例共享父类引用属性问题 3、创建子类实例时,可以向父类传递参数 缺点: 1、没用到原型,只是单纯继承了父类的实例属性及方法 2、没继承原型上的属性及方法 3、每个子类都有父类方法属性的副本,影响性能,没有实现父类函数复用
function Dog(name) { Animal.call(this) this.name = name || '狗' } // Test code const dog = new Dog() console.log(dog.name) // 狗 dog.sleep() // 狗正在睡觉! // dog.eat('粑粑') 不能继承原型上的eat console.log(dog instanceof Dog) // true console.log(dog instanceof Animal) // false,等于是复制父类的实例属性给子类,没用到原型
特点: 1、子类的构造中返回父类的实例 优点: 1、可以继承原型上的属性或方法 缺点: 1、实例为父类实例,而非子类实例 2、不能实现多继承
function Pig(name) { const instance = new Animal() instance.name = name || '猪' return instance } // Test code const pig = new Pig() console.log(pig.name) // 猪 pig.sleep() // 猪正在睡觉! pig.eat('菠菜叶子') // 猪正在吃:菠菜叶子 console.log(pig instanceof Pig) // false console.log(pig instanceof Animal) // true
特点: 1、子类的构造中强制拷贝父类原型上的属性或方法 优点: 1、可以多重继承 缺点: 1、效率较低,内存占用高 2、不能继承父类不可枚举的属性(不能用for in遍历的)
function Rabbit(name) { const animal = new Animal() // 多重继承直接new多个遍历 for (let i in animal) { Rabbit.prototype[i] = animal[i] } Rabbit.prototype.name = name || '兔子' } // Test code const rabbit = new Rabbit('傻兔子') console.log(rabbit.name) // 傻兔子 rabbit.sleep() // 傻兔子正在睡觉! rabbit.eat('胡萝卜') // 傻兔子正在吃:胡萝卜 console.log(rabbit instanceof Rabbit) // true console.log(rabbit instanceof Animal) // false
同构造继承
function Mouse(name) { this.method = Animal this.method(name) delete this.method } // Test code const mouse = new Mouse('老鼠') console.log(mouse.name) // 老鼠 mouse.sleep() // 老鼠正在睡觉! // mouse.eat('大米') // 继承不到原型上的属性 console.log(mouse instanceof Mouse) // true console.log(mouse instanceof Animal) // false
特点: 1、组合构造继承和原型链继承 优点: 1、可以继承实例属性/方法,也可以继承原型属性/方法 2、既是子类的实例,也是父类的实例 3、不存在引用属性共享问题 4、可传参 5、函数可复用 缺点: 1、调用了两次父类构造函数
function Duck(name) { Animal.call(this, name) } Duck.prototype = new Animal() Duck.prototype.say = function () { // 新增的say方法 console.log(this.name + '正在说话!') } // Test code const duck = new Duck('鸭子') console.log(duck.name) // 鸭子 duck.sleep() // 鸭子正在睡觉! duck.eat('虫子') // 鸭子正在吃:虫子 console.log(duck instanceof Duck) // true console.log(duck instanceof Animal) // true
特点: 1、使用中间函数对象避免父类构造被两次调用的问题 优点: 1、完美 缺点: 1、写起来费劲
function Snake(name) { Animal.call(this, name) } const Super = function () { } Super.prototype = Animal.prototype Snake.prototype = new Super() // Test code const snake = new Snake('蛇') console.log(snake.name) // 蛇 snake.sleep() // 蛇正在睡觉! snake.eat('小鸟') // 蛇正在吃:小鸟 console.log(snake instanceof Snake) // true console.log(snake instanceof Animal) // true
class Point { constructor(x, y) { //constructor 构造方法 this.x = x this.y = y } toString() { return this.x + ', ' + this.y } static hello() { console.log('hello world!') } } class ColorPoint extends Point { constructor(x, y, color){ super(x, y) // 必须先调用super,否则子类的this不可用 this.color = color } toString() { return this.color + ',' + super.toString() } } // Test code const cp = new ColorPoint(25, 8, 'green') console.log(cp instanceof ColorPoint) // true console.log(cp instanceof Point) // true ColorPoint.hello() // hello world!
本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。
我来说两句