- 通过call,apply(缺点只能继承父类的属性不能继承父类的方法)
function Person(name, sex){
this.name = name;
this.sex = sex;
this.indroduce = function(){
console.log(`my name is ${this.name}`)
}
}
function Student(name, sex){
Person.call(this,name, sex);
//Person.apply(this,[name, sex]);
}
var xiaoMing = new Student('小明','boy')
console.log(xiaoMing.name) // output 小明 name属性来自Person构造函数
- 父类实例化对象赋值给子类的prototype(实例化了两次,而且代码不严谨)
function Person(name, sex){
this.name = name;
this.sex = sex;
this.indroduce = function(){
console.log(`my name is ${this.name}`)
}
}
function Student(parnentName){
this.parnentName = parnentName;
}
Student.prototype = new Person('小明','boy')
var xiaoMing = new Student('大明');
console.log(xiaoMing.name,xiaoMing.parnentName); // output 小明 大明
xiaoMing.indroduce(); // output my name is 小明
- 父类实例化对象赋值给子类的prototype,并使用call或apply(实例化了两次,而且代码不严谨)
function Person(name, sex){
this.name = name;
this.sex = sex;
this.indroduce = function(){
console.log(`my name is ${this.name}`)
}
}
function Student(name, sex, parnentName){
Person.call(this,name, sex)
this.parnentName = parnentName;
}
Student.prototype = new Person('小明','boy')
var xiaoMing = new Student('小明1','boy', '大明');
console.log(xiaoMing.name,xiaoMing.parnentName); //
xiaoMing.indroduce(); //
- 父类实例化对象赋值给子类的prototype,并使用call或apply(但子类构造函数指向父类构造函数)
function Person(name, sex){
this.name = name;
this.sex = sex;
this.indroduce = function(){
console.log(`my name is ${this.name}`)
}
}
function Student(name, sex, parnentName){
Person.call(this,name, sex)
this.parnentName = parnentName;
}
Student.prototype = Person.prototype
var xiaoMing = new Student('小明','boy', '大明');
console.log(xiaoMing.name,xiaoMing.parnentName); // output 小明 大明
xiaoMing.indroduce(); // my name is 小明
console.log(Student.prototype.constructor)
// output ƒ Person(name, sex){
// this.name = name;
// this.sex = sex;
// this.indroduce = function(){
// console.log(`my name is ${this.name}`)
}
}
- 父类实例化对象赋值给子类的prototype,并使用call或apply(优化方法三,MDN上推荐的做法)
function Person(name, sex){
this.name = name;
this.sex = sex;
this.indroduce = function(){
console.log(`my name is ${this.name}`)
}
}
function Student(name, sex, parnentName){
Person.call(this,name, sex)
this.parnentName = parnentName;
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student
var xiaoMing = new Student('小明','boy', '大明');
console.log(xiaoMing.name,xiaoMing.parnentName); // output 小明 大明
xiaoMing.indroduce(); // my name is 小明
console.log(Student.prototype.constructor)
// output ƒ Student(name, sex, parnentName){
//Person.call(this,name, sex)
//this.parnentName = parnentName;
//}
下面这段内容是复制到mdn网站上的
网址为:
https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Objects/Inheritance
何时在 JavaScript 中使用继承?
特别是在读完这段文章内容之后,您也许会想 “天啊,这实在是太复杂了”. 是的,您是对的,原型和继承代表了JavaScript这门语言里最复杂的一些方面,但是JavaScript的强大和灵活性正是来自于它的对象体系和继承方式,这很值得花时间去好好理解下它是如何工作的。
在某种程度上来说,您一直都在使用继承 - 无论您是使用WebAPI的不同特性还是调用字符串、数组等浏览器内置对象的方法和属性的时候,您都在隐式地使用继承。
就在自己代码中使用继承而言,您可能不会使用的非常频繁,特别是在小型项目中或者刚开始学习时 - 因为当您不需要对象和继承的时候,仅仅为了使用而使用它们只是在浪费时间而已。但是随着您的代码量的增大,您会越来越发现它的必要性。如果您开始创建一系列拥有相似特性的对象时,那么创建一个包含所有共有功能的通用对象,然后在更特殊的对象类型中继承这些特性,将会变得更加方便有用。
注: 考虑到JavaScript的工作方式,由于原型链等特性的存在,在不同对象之间功能的共享通常被叫做 委托 - 特殊的对象将功能委托给通用的对象类型完成。这也许比将其称之为继承更为贴切,因为“被继承”了的功能并没有被拷贝到正在“进行继承”的对象中,相反它仍存在于通用的对象中。
在使用继承时,建议您不要使用过多层次的继承,并仔细追踪定义方法和属性的位置。很有可能您的代码会临时修改了浏览器内置对象的原型,但您不应该这么做,除非您有足够充分的理由。过多的继承会在调试代码时给您带来无尽的混乱和痛苦。
总之,对象是另一种形式的代码重用,就像函数和循环一样,有他们特定的角色和优点。如果您发现自己创建了一堆相关的变量和函数,还想一起追踪它们并将其灵活打包的话,对象是个不错的主意。对象在您打算把一个数据集合从一个地方传递到另一个地方的时候非常有用。这些都可以在不使用构造器和继承的情况下完成。如果您只是需要一个单一的对象实例,也许使用对象常量会好些,您当然不需要使用继承。