在java开发中关于继承的概念是父类和子类,JS也是一门面向对象的语言,因此绕不过继承的概念,而JS的设计者则给出的是原形及原型链的概念,我对此的简单理解就是为了能够实现继承,实现java中访问父类属性的概念,参考下述简单示例
var father = { name: 'fa', age: 45, skill: function(){ console.log('I can work') } } var child = { name: 'child', age: 15 } child.prototype = father //实现child继承father child.prototype.skill() //I can work console.log(child.name) //child console.log(child.prototype.name) //fa
回到创建实例对象的几种方法,当使用构造函数时,如果存在相同的方法,则每个实例对象会存在方法的重复,而使用原型时,则共用的方法则不会占用多余内存,如下示例:
//1.工厂创建对象: 存在不能够确定对象类型的问题 function Cat(name){ return { name: name, say: function(){ console.log(this.name) } } } var cat = Cat('heimao') console.log(cat instanceof Cat) //false //2.构造函数: 存在方法的重复 function Cat(name){ this.name = name this.say = function(){ console.log(this.name) } } var cat1 = new Cat("baimao") var cat2 = new Cat("heimao") console.log(cat2 instanceof Cat) //true //3.使用原型 function Cat(name) { this.name = name; } Cat.prototype.say = function(){ console.log(this.name) } var cat1 = new Cat("baimao") var cat2 = new Cat("heimao") console.log(cat2 instanceof Cat) //true
使用原型实现一个继承
function Animal(){ this.type = '动物' } function Cat(name){ this.name = name } Cat.prototype = new Animal() var cat1 = new Cat("小花") console.log(cat1.name, cat1.type) //小花 动物
构造器实现继承
function Animal(){ this.type = '动物' } function Cat(name){ Animal.apply(this) //把父类属性复制过来 this.name = name } var cat1 = new Cat("小白") console.log(cat1.name, cat1.type) //小白 动物组合继承(原型+构造器):调用了两次父类构造器
function Person(name){ this.skill = 'eat' this.name = name } Person.prototype.showName = function(){ //在Person的原型中增加一个方法 console.log(this.name) } function Teacher(name, course){ Person.call(this, name) //第二次调用,把Person中的属性拷贝一份到Teacher中 this.course = course } Teacher.prototype = new Person() //第一次调用,把Teacher的原型指向Person,也就是让Teacher继承Person var t1 = new Teacher('老刘', '语文') console.log(t1.course, t1.name, t1.skill) //语文 老刘 eat t1.showName() //在Teacher对象中找不到这个方法,则去原型(父类)中找,依然没有,则去Person的原型(父类)中找
组合继承(原型+构造+寄生)
function Person(name){ this.skill = 'eat' this.name = name } Person.prototype.showName = function(){ //在Person的原型中增加一个方法 console.log(this.name) } function Teacher(name, course){ Person.call(this, name) //把Person中的属性拷贝一份到Teacher中 this.course = course } function extend(subObj, superObj){ //创建一个空对象,将空对象的原型指向superObj的原型 var proObj = Object.create(superObj.prototype) subObj.prototype = proObj } extend(Teacher, Person); var t1 = new Teacher('老汪', '数学') console.log(t1.course, t1.name, t1.skill) //数学 老汪 eat t1.showName() //对于这种方式的理解: //对比上面原型+构造的方式,让Teacher继承自Person,则需要先创建一个Person实例, //而这种方式只需创建一个空对象作为中间人把两者继承关系关联起来,形成原型链(继承链) //根据JS高程书中的解释: //上述原型+构造中,第一次调用时在teacher的原型中创建了name和skill的属性, //第二次调用时则把原型中的属性又复制到了teacher中,增加了内存的消耗