首先来看一段代码:
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也可以)
本文详细介绍了JavaScript中三种实现继承的方式:直接赋值原型、通过new调用父类构造函数及使用Object.create方法。对比分析了各种方法的优缺点,并探讨了在不同ES版本中的适用性。
76

被折叠的 条评论
为什么被折叠?



