zoukankan      html  css  js  c++  java
  • js类式继承模式学习心得

    最近在学习《JavaScript模式》,感觉里面的5种继承模式写的很好,值得和大家分享。

    类式继承模式#1——原型继承

    方法

    让子函数的原型来继承父函数实例出来的对象

    	<script type="text/javascript">
    		function SuperType(name) {
    			this.name = name || "john";
    		}
    
    		SuperType.prototype.sayName = function() {
    			console.log(this.name);
    		};
    
    		function SubType(name,age) {
    		}
    
    		// 继承方法
    		function inherit(C,P) {
    			C.prototype = new P();
    		}
    
    		inherit(SubType,SuperType);
    
    		var instance1 = new SubType("mo");
    		console.log(instance1.sayName()); // john
    	</script>
    

    以上代码中通过关键字new操作符,操作子函数SubType创建一个新实例。以这种调用构造函数会经过四个步骤:

    • 创建新对象
    • 将构造函数的作用域赋给新对象(构造函数的this指针指向了这个新对象)
    • 执行构造函数中的代码,创建的属性与方法赋值给这个新对象
    • 返回新对象

    缺点

    • 继承了两个对象的属性,即添加到this的属性及原型中的属性
    • 另外一个问题是不能将子函数的参数传递给父函数

    类式继承模式#2——借用构造函数

    方法

    在子函数中访问父函数的作用域

    <script type="text/javascript">
    	function SuperType(name) {
    		this.name = name || "mo";
    		}
    	}
    	SuperType.prototype.getName = function () {
    		return this.name;
    	}
    	function SubType() {
    		SuperType.call(this,"mo"); // 通过使用call方法,改变子构造函数的作用域的指向,此时this指向父函数的作用域。
    	}
    
    	var ins1 = new SubType();
    	console.log(ins1.getName());
    </script>
    

    此方法的问题:子类不能访问父类原型中的属性与方法
    因为子函数是通过call方法访问父函数的作用域,而不是访问父函数原型中的作用域。父函数与父函数原型是通过_proto_对象链接的。

    类式继承模式#3——借用和设置原型

    方法

    先借用构造函数,然后设置子函数的原型使其指向父函数创建的实例

    <script type="text/javascript">
    	function SuperType(name) {
    		this.name = name || "mo";
    		}
    	}
    	SuperType.prototype.getName = function () {
    		return this.name;
    	}
    	function SubType() {
    		SuperType.call(this,"mo");
    	}
           
            SubType.prototype = new SuperType();
            // 此时SubType.prototype的constructor以改变,并且指向了SuperType
    
    	var ins1 = new SubType();
    	console.log(ins1.getName()); // mo
    </script>
    

    注意:new SuperType()是创建了一个新对象出来,所以要赋值给SubType的原型prototype,不能赋给函数。利用子类的原型来实现继承。

    这种模式的缺点

    • 父函数被调用了两次,因此导致了其效率十分低下的问题。
    • 自身的属性(name)也会被继承两次

    类式继承模式#4——共享原型

    方法

    把可复用的成员转移到原型中而不是放在this对象中,即让子对象的原型等于父对象的原型

    	<script type="text/javascript">
    		function Parent(name) {
    			this.name = name||"mo"; 
    		}
    		Parent.prototype.sayName = function() {
    			return this.name;
    		}
    
    		function Child(name) {
    			Parent.call(this,name);
    		}
    
    		function inherit (C,P) {
    			C.prototype = P.prototype;
    		}
    		inherit(Child,Parent);
    		var ins = new Child();
    		console.log(ins.name);
    	</script>
    

    缺点

    • 如果继承下方的某处存在一个子对象或者孙对象修改了原型,它将会影响所用的父对象和祖先对象

    类式继承模式#5——临时构造函数

    方法

    通过断开父对象与子对象原型之间的直接链接关系,从而解决共享同一个原型的问题,即构造一个新的空的构造函数做代理

    	<script type="text/javascript">
    		function Parent(name) {
    			this.name = name||"mo"; 
    		}
    		Parent.prototype.sayName = function() {
    			return this.name;
    		}
    
    		function Child(name) {
    			Parent.call(this,name);
    		}
    
    		function inherit (C,P) {
    			var F = function() {};
    			F.prototype = P.prototype;
    			C.prototype = new F();
    			// 重置构造函数的指针
    			C.prototype.constructor = C;
    			// uber用来储存超类,uber可以指向原始父对象的引用。
    			C.uber = P.prototype;
    		}
    		inherit(Child,Parent);
    		var ins = new Child();
    		console.log(ins.name);
    	</script>
    

    该模式也有一个缺点:

    • 每次继承时都会创建一个新的构造函数F()

    改善临时构造函数模式

    方法:使用即时函数,并且在闭包中储存代理函数

    		var inherit = (function () {
    			var F = function() {};
    			return function (C,P) {
    				F.prototype = P.prototype;
    				C.prototype = new F();
    				// 重置构造函数的指针
    				C.prototype.constructor = C;
    				// uber用来储存超类,uber可以指向原始父对象的引用。
    				C.uber = P.prototype;	
    			}
    		})();
    

    总结:
    这种方式相对来说是比较好的,可以不继承父函数中的成员,也不会多次调用父函数,自身的属性也不会被继承多次。但是如果需要继承父函数中的成员的时候则这种模式不可取,还是的使用组合继承(也称伪经典继承)。所以没有在用的时候要看哪种继承模式是最适合自己的。
    以上有哪里写的不对的,或者表述不清除的地方,欢迎来指正。

  • 相关阅读:
    数学形态学——腐蚀、膨胀、开、闭、细化
    VS2010中 报错:error C2146、error C4430 原因一:缺少CvvImage类
    帧同步和状态同步
    HTML5触摸事件演化tap事件
    screenX clientX pageX的区别
    phaser的小游戏的onInputDown问题
    phaser入手
    pixi.js 微信小游戏 入手
    正则表达式
    剖析Vue原理&实现双向绑定MVVM-2
  • 原文地址:https://www.cnblogs.com/Mrdouhua/p/5960242.html
Copyright © 2011-2022 走看看