js中的继承和重载
js中有三种继承方式:一、通过原型(prototype)实现继承
二、借用构造函数式继承,可分为通过call()方法实现继承和通过apply()方法实现继承
仅仅通过原型继承我们可以发现在实例化子类时无法向父类构造函数中传递参数,call()方法存在于Function对象实例中的原型对象属性中。
var Person = function(name,age,sex){ this.name = name; this.age = age; this.sex = sex; } Person.prototype = { eat:function(){ console.log("吃饭"); }, say:function(){ console.log("说话"); } } // var person = new Person("张三",18,"男"); // console.log(person); var Programmer = function(name,sex,age){ this.hobby = ["看书","FQ"]; } Programmer.prototype = new Person(); Programmer.prototype.wirteCode = function(){ console.log("写代码"); } var prm = new Programmer("李四",18,"男"); console.log(prm);
call()方法作用:1、可以让调用call()方法的对象实例执行(分辨是谁调用就看 "." 前面的对象是谁)。
2、call方法会用其第一个实参替换被调用函数内部中的this指向。
3、call方法可以将其除第一个实参以外的参数传递给被调用函数中。
call()方法和apply()方法区别:1、call()向被调用函数中传递参数须将参数逐个传递;
2、apply()向被调用函数中传递参数需要传递一个数组或者argument对象。
注意:这两个方法功能相同,都是将被调用函数中的this变为第一个实参。
var fn1 = function(name,age){ this.name = name; this.age = age; } fn1.prototype = { eat:function(){ console.log("OK"); } } var fn2 = function(name,age,sex){ fn1.call(this,name,age); //fn1.apply(this,arguments); this.sex = sex; } var f2 = new fn2("张三",18,"男"); console.dir(f2);
var a = {0:"A",1:"B",2:"C",length:3}; var newa = Array.prototype.slice.call(a); console.log(newa); var arr = new Array(); var arr = [1,2,3]; var arr1 = [3,4,5]; var minNum = Math.min.apply(null,[5,2,3,5]); console.log(minNum);
三、组合式继承(也叫组合寄生式继承):即原型继承+call()或者apply()继承。
var extend = function(obj1,obj2){ for(var attrName in obj2){ //obj1.prototype[attrName] = obj2.prototype[attrName]; obj1[attrName] = obj2[attrName]; } return obj1; }; var fn1 = function(name,age){ this.name = name; this.age = age; } fn1.prototype = { eat:function(){ console.log("OK"); } }
其优点也很明显,就是在实例化子类时可以向父类构造函数中传递参数,并且父类构造函数只会执行一次(这一次是继承实例属性时发生的)。
var fn2 = function(name,age,sex){ //用call方法继承实例属性 //借用构造函数式继承 fn1.call(this,name,age); this.sex = sex; } //用重写原型属性继承原型属性 //当使用借用构造函数式继承和原型式继承时称为组合式继承 //组合寄生式继承,如下: object(fn2,fn1); // var object = function(super,sub){ // sub.prototype = extend(sub.prototype,super.prototype); // } fn2.prototype = { say:function(){ console.log("说话"); } }
重载就是通过参数类型不同或参数个数不同可以让方法实现的功能不同,需要注意的是JS中其实没有真正意义上的重载,但是可以用typeof或argument来进行模拟,从而体现出JS面向对象思想中的重载特性。
由于使用原型式继承时,会覆盖子类原型中原有的属性,所以利用对象循环遍历属性实现属性浅拷贝的功能来解决属性覆盖问题。浅拷贝方法具体看extend函数。另外可以看一下深拷贝的相关内容。
fn2.prototype = extend(fn2.prototype,fn1.prototype); var f2 = new fn2("张三",18,"男"); //console.log(f2.eat()); console.dir(f2);