js注意事项3(继承)
Posted 嘿起屁儿整
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js注意事项3(继承)相关的知识,希望对你有一定的参考价值。
原型链继承
缺点:引用类型共享。(每个子实例对基本类型进行操作互相没有影响。但是每个子实例对引用类型进行操作,会同步操作其他子实例的引用类型)
//父类
function Person() {}
//子类
function Student() {}
//原型链继承(Student的原型对象属于Person实例)
Student.prototype = new Person();
//父类
function Person(name,age){
this.name = 'personname' || 'unknow'
this.age = age || 0
}
Person.prototype.say = function(){
console.log('i am a person');
}
//子类
function Student(name){
this.name = name
this.score = 80
}
//继承
Student.prototype = new Person();
Student.prototype.study = function(){
console.log('i am studing');
}
var stu = new Student('lucy');
console.log(stu.name); //lucy --子类覆盖父类的属性
console.log(stu.age); // 0 --父类的属性
console.log(stu.score); // 80 --子类自己的属性
stu.say(); // i am a person --继承自父类的方法
stu.study(); // i am studing --子类自己的方法
但是原型链继承有个缺点:如果属性是引用类型,会共享。改变一个实例的属性另一个实例的属性也会改变
//父类
function Person() {
this.names = ['张三', '李四']
}
//子类
function Student() {}
//继承
Student.prototype = new Person();
var stu1 = new Student();
var stu2 = new Student();
stu1.names.push('王五');
console.log(stu1.names); // ["张三", "李四", "王五"]
console.log(stu2.names); // ["张三", "李四", "王五"]
构造函数继承
- 缺点:引用类型不共享。(每个子实例对基本类型进行操作互相没有影响。对引用类型操作也互相没有影响。但是引用类型中的函数虽然值一样,但是===号不一样,因为每次创建子实例都要复制一遍函数)
解决了原型链继承,如果属性是引用类型。一个实例的属性改变另一个实例的属性也会跟着改变的问题。
//父类
function Person() {
this.names = ['张三', '李四']
}
//子类
function Student() {
//构造函数继承。在Student子类中将Person的this绑定为Student
Person.call(this)
}
var stu1 = new Student();
var stu2 = new Student();
stu1.names.push('王五');
console.log(stu1.names); // ["张三", "李四"]
console.log(stu2.names); // ["张三", "李四", "王五"]
注意构造函数继承不用prototype
//父类
function Person(name){
this.name = name;
}
//子类
function Student(name){
Person.call(this,name);
}
var stu1 = new Student('lucy');
var stu2 = new Student('lili');
console.log(stu1.name); // lucy
console.log(stu2.name); // lili
但是构造函数继承也有缺点:函数也是引用类型,每个Student的实例函数虽然功能一样,但是不是同一个函数(相当于每实例化一个子类,就要复制一遍函数)
//父类
function Person(name) {
this.say = function () {console.log(111)};
}
//子类
function Student(name) {
Person.call(this, name);
}
var stu1 = new Student('lucy');
var stu2 = new Student('lili');
console.log(stu1.say) //ƒ () {console.log(111)}
console.log(stu2.say) //ƒ () {console.log(111)}
console.log(stu1.say === stu2.say); // false
组合继承
- 同时使用原型链继承,构造函数继承。刚好互补引用类型共享问题
解决了构造函数继承,如果属性是引用类型的函数。虽然值相等,但是地址不同,===为false的,即每次子实例都要复制一遍函数的问题
//父类
function Person(name) {
this.names = ['张三', '李四'];
}
Person.prototype.say = function () {
console.log('i am a person');
}
//子类
function Student(name) {
Person.call(this); //构造函数继承(继承属性)
}
Student.prototype = new Person(); //原型继承(继承方法)
var stu1 = new Student('lucy');
var stu2 = new Student('lili');
stu1.names.push('王五');
console.log(stu1.names); // ["张三", "李四", "王五"]
console.log(stu2.names); // ["张三", "李四"]
console.log(stu1.say === stu2.say); // true
但是组合继承也有缺点:由于每次子实例会调用两次父类,会创建两个子实例。不过这个影响不大。如果要做到完美,可以再使用寄生组合继承 或者 es6新出的class继承
es6的class继承
这个也是完美的继承
class People {
constructor(name = 'wang', age = '27') {
this.name = name;
this.age = age;
}
eat() {
console.log(`${this.name} ${this.age} 喜欢吃豆制品`)
}
}
//继承父类
class Woman extends People {
constructor(name = 'ren', age = '18') {
//继承父类属性
super(name, age);
}
eat() {
//继承父类方法
super.eat()
}
}
let wonmanObj = new Woman("fish");
wonmanObj.eat();
//fish 18 喜欢吃豆制品
以上是关于js注意事项3(继承)的主要内容,如果未能解决你的问题,请参考以下文章