js注意事项3(继承)

Posted 嘿起屁儿整

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js注意事项3(继承)相关的知识,希望对你有一定的参考价值。

js继承

原型链继承

缺点:引用类型共享。(每个子实例对基本类型进行操作互相没有影响。但是每个子实例对引用类型进行操作,会同步操作其他子实例的引用类型)

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

实验7

泛型,JDK5新特性,List集合子实现类,Map集合,Set/TreeSet集合,asList

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

9模板语言继承使用

本周推荐 | 表达式引擎的组合子实现方案

肾结石