js继承
- 定义实例的方法主要有两种:this.XXX = function(){} 和 function.prototype.XXX= function(){}
- 都相当于类的实例方法,只有new后才能使用,那有什么区别呢?
- 假如这两种方式定义的是同名函数,那么优先执行this定义的函数
- 但作为实例函数,如果定义在构造函数内部,每次实例化都要执行,显然在浪费内存,也不合理
- 如果要直接访问私有字段,应该使用特权方法
- 相反,如果不需要直接访问私有字段,应该使用prototype定义的方法,而且应该定义在构造函数外部。
原型链继承的特点
将父类的实例作为子类的原型
缺点:
- 来自原型对象的引用属性是所有实例共享的
- 创建子类实例时,无法向父类构造函数传参
其他:
- 构造继承:使用父类的构造函数来增强子类实例 =复制父类的实例属性给子类
- Animal.call(this);
缺点:
- 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
组合起来
优点:
- 既是子类的实例,也是父类的实例
- 可传参
- 函数可复用
// Animal(构造函数) function Animal(info){ if(!info){return;} this.init(info); }; Animal.prototype={ constructor:Animal, init:function(info){ this.name = info.name; }, sleep:function(){ console.log(this.name+" is sleeping "); } } // Cat function Cat (){ Animal.call(this); this.name =(name)?name:'tom'; // this.sleep = function(){ // console.log(this.name+" is sleeping111111111 "); // } }; // 将父类的实例作为子类的原型 var info ={name:'Animal'}; Cat.prototype = new Animal(info); //实例化1次 // test code var cat = new Cat();//实例化2次 // cat.name; console.log(cat.name); cat.sleep(); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); //true
听说比较完美的做法
// Animal(构造函数) function Animal(info){ var info = (info)?info:{name:'Animal'}; this.init(info); }; Animal.prototype={ constructor:Animal, init:function(info){ this.name = info.name; }, sleep:function(){ console.log(this.name+" is sleeping "); } } // Cat function Cat (){ Animal.call(this); // this.name =(name)?name:'tom'; // this.sleep = function(){ // console.log(this.name+" is sleeping111111111 "); // } }; // 只执行一次 (function(){ // 创建一个没有实例方法的类 var Super = function(){}; Super.prototype = Animal.prototype; Cat.prototype = new Super(); })(); // test code var cat = new Cat();//实例化2次 // cat.name; console.log(cat.name); cat.sleep(); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); //true