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(继承)的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript笔试题(js高级代码片段)

小程序各种功能代码片段整理---持续更新

js简洁代码片段

使用带有渲染功能的 Vue.js 3 片段

JS常用代码片段-127个常用罗列-值得收藏

JS面向对象三大特征:封装、继承、多态