首先来看一段代码:
function Person(){
}
function Student(){
}
Student.prototype = Person.prototype;//第一种方式
Student.prototype = new Person();//第二种方式
Student.prototype = Object.create(Person.prototype)//第三种方式
第一种方式(不可取):
可以实现继承,但是在改变Student的同时也会相应的改变Person,这很显然不是我们所需要的,所以此种继承方案不可取,是错误的。
第二种方式(原型继承):
new Person()调用构造函数得到了一个Person的实例,并且这个实例指向了Person的prototype,所以这里实现了继承。但是就是因为调用了构造函数,所以这样可能会有问题,比如说,Person的构造函数是需要传递参数的function Person(name,age)等,那么在实例化的时候需要传递什么参数进去呢?很显然,不管传递什么都是很别扭的,所以此种方案使用的也不多。
第三种方式(Object.ceate):
此方案是最为理想的方案。使用Object.create()方法创建一个空的对象,并且这个对象的原型指向了Person.prototype,这样我们既保证了我们可以继承Person.prototype上面的方法,并且Student.prototype又有自己的一个空的对象,所以Student的修改不会影响到原型链上面的方法。
但是这里也有一个问题,就是Object.create()方法是在ES5之后才有的方法,那么在之前的版本我们可以用另一个方法来模拟一下代替:
if(!Object.create){
Object.create = function(proto){
funtion F(){} //临时的空函数
F.prototype = proto; //将空函数的prototype属性复制给我们想要作为原型的对象
return new F; //new一个构造器,那么就会创建一个对象,这个对象的原型指向构造器的prototype
}
}
另外还有一种方式,使用call和apply:
function Person(name,age,love){
this.name=name;
this.age=age;
this.love=love;
this.say=function say(){
alert("姓名:"+name);
}
}
//call方式
function student(name,age){
Person.call(this,name,age);
}
//apply方式
function teacher(name,love){
Person.apply(this,[name,love]);
//Person.apply(this,arguments); //跟上句一样的效果,arguments
}
//call与aplly的异同:
//1,第一个参数this都一样,指当前对象
//2,第二个参数不一样:call的是一个个的参数列表;apply的是一个数组(arguments也可以)