zoukankan      html  css  js  c++  java
  • JavaScript中的继承模式总结(九)

    一、总结:

    //js中的几种继承
    //原型链的问题,包含引用类型的原型属性会被实例共享,子类型无法给超类型传递参数
    function SuperType() {
    	this.colors = ["red","blue","green"];
    }
    
    function SubType() {	
    }
    
    SubType.prototype = new SuperType();
    var instance1 = new SubType();
    instance1.colors.push("black");
    //alert(instance1.colors);//red,blue,green,black
    var instance2 = new SubType();//red,blue,green,black
    //alert(instance2.colors);
    

      

    //1.借用构造函数
    //在构造函数中定义属性,而不是在原型对象中定义属性
    function SuperType() {
    	this.colors = ["red","blue","green"];
    	function getColors() {
    		return colors;
    	}
    }
    
    function SubType() {
    	//每个实例都会有一个colors属性的副本
    	SuperType.call(this);//构造函数中继承了SuperType
    }
    
    //SubType.prototype = new SuperType();
    //SuperType.prototype.getColors = function() {
    //	return this.colors;
    //};
    var instance1 = new SubType();
    instance1.colors.push("black");
    alert(instance1.colors);//red,blue,green,black
    //alert(instance1.getColors());//red,blue,green,black
    var instance2 = new SubType();
    alert(instance2.colors);//red,blue,green
    //alert(instance2.getColors());//red,blue,green
    

      

    //2.组合继承 最常用的继承模式
    //也叫伪经典继承,组合了原型链和借用构造函数的技术的一种继承方式
    //通过结合构造函数定义属性的方式,还可以为超类型传递参数;采用原型链就不用将方法写在构造函数里面
    function SuperType(name) {
    	this.colors = ["red","blue","green"];
    	this.name = name;
    	//alert("我被调用");
    }
    
    function SubType(name) {
    	//每个实例都会有一个colors属性的副本
    	SuperType.call(this,name);//第二次调用SuperType()
    }
    
    SubType.prototype = new SuperType();//第一次调用SuperType()
    SuperType.prototype.getColors = function() {
    	return this.colors;
    };
    var instance1 = new SubType("youyi");
    //alert(instance1.name);//youyi
    var instance2 = new SubType("xiaobai");
    //alert(instance2.name);//xiaobai
    

      

    //3.原型式继承
    //没有严格意义上的构造函数,借用原型基于已有的对象创建新对象
    function object(o) {
    	function F(){}
    	F.prototype = o;
    	return new F();
    }
    
    //var person = {
    //	name: "youyi",
    //	friends: ["小花","小白","小明"]
    //};
    //
    //var anotherPerson1 = object(person);
    //anotherPerson1.name = "王宝强";
    //anotherPerson1.friends.push("小马");
    //
    //var anotherPerson2 = object(person);
    //anotherPerson2.name = "陈思成";
    //anotherPerson2.friends.push("宝宝");
    
    //console.log(person.friends);//["小花", "小白", "小明", "小马", "宝宝"]
    //console.log(person.name);//youyi
    
    //与object()方法行为相同的object.create()
    var person = {
    	name: "youyi",
    	friends: ["小花","小白","小明"]
    };
    
    var anotherPerson1 = Object.create(person);
    anotherPerson1.name = "王宝强";
    anotherPerson1.friends.push("小马");
    
    var anotherPerson2 = Object.create(person);
    anotherPerson2.name = "陈思成";
    anotherPerson2.friends.push("宝宝");
    
    //console.log(person.friends);//["小花", "小白", "小明", "小马", "宝宝"]
    console.log(anotherPerson1.name);//王宝强
    console.log(person.name);//youyi
    
    //object.create()方法的第二个参数是通过自己的描述符定义的,该属性会覆盖原型对象上的同名属性
    var person = {
    	name: "youyi",
    	friends: ["小花","小白","小明"]
    };
    
    var anotherPerson1 = Object.create(person,{
    	name: {
    		value: "王宝强"
    	}
    });
    
    anotherPerson1.friends.push("小马");
    
    var anotherPerson2 = Object.create(person);
    anotherPerson2.name = "陈思成";
    anotherPerson2.friends.push("宝宝");
    console.log(person.friends);//["小花", "小白", "小明", "小马", "宝宝"]
    console.log(anotherPerson1.name);//王宝强
    console.log(person.name);//youyi
    

      

    //4.寄生式继承
    //缺点是,因为函数不能复用而降低效率,这点与构造函数模式类似
    function createAnother(original) {
    	var clone = object(original);
       //var clone = {};
    	clone.sayHi = function() {
    		console.log("hi");
    	};
    	return clone;
    }
    
    //没有严格意义上的构造函数,借用原型基于已有的对象创建新对象
    function object(o) {
    	function F(){}
    	F.prototype = o;
    	return new F();
    }
    
    var person = {
    	name: "youyi",
    	friends: ["小花","小白","小明"]
    };
    
    var anotherPerson3 = createAnother(person);
    anotherPerson3.sayHi();//hi
    

      

    //5.寄生组合式继承  
    //效率更高的一种继承模式,通过构造函数来继承属性,通过原型链的混成形式来继承方法
    //组合继承中会两次调用SuperType()
    //寄生组合式继承相当于是对组合继承模式的一种优化
    
    //原理还是要让子类型的原型等于一个超类型的实例
    function inheritPrototype(subType,superType) {
    	var  prototype = object(superType.prototype);
    	prototype.constructor = subType;
    	subType.prototype = prototype;
    }
    
    //没有严格意义上的构造函数,借用原型基于已有的对象创建新对象
    function object(o) {
    	function F(){}
    	F.prototype = o;
    	return new F();
    }
    
    function SuperType(name) {
    	this.colors = ["red","blue","green"];
    	this.name = name;
    	alert("我被调用2");
    }
    
    function SubType(name) {
    	//每个实例都会有一个colors属性的副本
    	SuperType.call(this,name);//调用SuperType() 只调用一次
    }
    
    //SubType.prototype = new SuperType();//第一次调用SuperType()
    //优化上面的方法
    inheritPrototype(SubType,SuperType);
    
    SuperType.prototype.getColors = function() {
    	return this.colors;
    };
    var instance1 = new SubType("youyi");
    alert(instance1.name);//youyi
    //var instance2 = new SubType("xiaobai");
    //alert(instance2.name);
    

      

     es6中通过extends实现继承

    es5和es6实现继承的区别:es5主要是先创建子类的实例对象的this,然后再将父类方法添加到this上;而es6相反,所以在子类构造函数中必须先调用super,将父类实例对象的属性和方法添加到this上,然后再用子类的构造函数修改this。

  • 相关阅读:
    推销员问题
    string类实现
    链表倒数第k个节点
    设计模式之单例模式大全
    空类 sizeof 为什么是1
    类的三种继承方式
    单例模式典型创建方法(三种)
    虚函数实现
    链表删除结点
    TCP的状态转移
  • 原文地址:https://www.cnblogs.com/yy95/p/5784211.html
Copyright © 2011-2022 走看看