老生常谈的问题,大部分人也不一定可以系统的理解。Javascript语言对继承实现的并不好,需要工程师自己去实现一套完整的继承机制。下面我们由浅入深的系统掌握使用javascript继承的技巧。
1. 直接使用原型链
这是最简粗暴的一种方式,基本没法用于具体的项目中。一个简单的demo如下:
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; } function SubType(){ this.subproperty = false; } //继承 SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function(){ return this.subproperty; } var instance = new SubType();
这种方式的问题是原型中的属性会被所用实例共享,通过一个实例改变一个继承过来的属性时,会影响到其他实例。,这显然不是一种常规意义上的继承。
2.使用构造函数
构造函数本质上也只是一个函数而已,可以在任何作用域中调用,在子构造函数中调用父构造函数,就可以实现简单的继承。
function SuperType(){ this.colors = {"red","blue","green"} } function SubType(){ SuperType.call(this); } var instance = new SubType();
这种实现避免了多个实例共享属性的问题,但是又出现了新的问题,比如没法共享函数,而且 instance instanceof SuperType 为false。
3. 组合使用原型和构造函数
function SuperType(name){ this.name = name; this.colors = {"red","blue","green"} } SuperType.prototype.sayName = function(){ //code } function SubType(name,age){ SuperType.call(this,name); this.age = age; } SubType.prototype = new SuperType(); var instance = new SubType();
组合使用原型和构造函数是javascript中最常用的继承模式。使用这种方式,每个实例都有自己的属性,同时可以共享原型中的方法。但是这种方式的缺点是:无论什么情况,都会调用两次超类构造函数。一次是在创建子类原型时,另一次是在子类构造函数内部。这种问题该怎么解决呢?
4. 寄生组合式继承
SubType的原型并不一定非要是SuperType的实例,只需是一个构造函数的原型是SuperType的原型的普通对象就可以了。Douglas Crockford的方法如下:
function obejct(o){ function F(){}; F.prototype = o; return new F(); }
其实这也就是ES5中Object.create的实现。那么我们可以修改本文中的第3种方案:
function inheritPrototype(subType,superType){ var prototype = object(superType.prototype); prototype.constructor = subType; subType.prototype = prototype; } function SuperType(name){ this.name = name; this.colors = {"red","blue","green"} } SuperType.prototype.sayName = function(){ //code } function SubType(name,age){ SuperType.call(this,name); this.age = age; } inheritPrototype(SubType,SuperType); var instance = new SubTYpe();
其实寄生组合式继承已经是一种非常好的继承实现机制了,足以应付日常使用。如果我们提出更高的要求:比如如何在子类中调用父类的方法呢?
5.simple-inheritance库的实现
看这么难懂的代码,起初我是拒绝的,但是深入之后才发现大牛就是大牛,精妙思想无处不在。我对每一行代码都有详细的注释。如果你想了解细节,请务必详细研究,读懂每一行。我觉得这个实现最精妙的地方就是按需重写父类方法,在实例对象中可以通过_super调用父类的同名方法,类似于java的实现。
(function(){ //initializing用于控制类的初始化,非常巧妙,请留意下文中使用技巧 //fnTest返回一个正则比表达式,用于检测函数中是否含有_super,这样就可以按需重写,提高效率。当然浏览器如果不支持的话就返回一个通用正则表达式 var initializing = false,fnTest = /xyz/.test(function(){xyz;}) "function" && typeof _super[name] == "function" && fnTest.test(prop[name])"htmlcode">var Human = Class.extend({ init: function(age,name){ this.age = age; this.name = name; }, say: function(){ console.log("I am a human"); } }); var Man = Human.extend({ init: function(age,name,height){ this._super(age,name); this.height = height; }, say: function(){ this._super(); console.log("I am a man"); } }); var man = new Man(21,'bob','191'); man.say();由浅入深讲解Javascript继承机制与simple-inheritance源码分析,希望本文分享能够帮助到大家。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。