在本章中,我们将分析John Resig关于JavaScript继承的一个实现 - Simple JavaScript Inheritance。
John Resig作为jQuery的创始人而声名在外。是《Pro JavaScript Techniques》的作者,而且Resig将会在今年秋天推出一本书《JavaScript Secrets》,非常期待。
调用方式
调用方式非常优雅:
注意:代码中的Class、extend、_super都是自定义的对象,我们会在后面的代码分析中详解。
var Person = Class.extend({ // init是构造函数 init: function(name) { this.name = name; }, getName: function() { return this.name; } }); // Employee类从Person类继承 var Employee = Person.extend({ // init是构造函数 init: function(name, employeeID) { // 在构造函数中调用父类的构造函数 this._super(name); this.employeeID = employeeID; }, getEmployeeID: function() { return this.employeeID; }, getName: function() { // 调用父类的方法 return "Employee name: " + this._super(); } }); var zhang = new Employee("ZhangSan", "1234"); console.log(zhang.getName()); // "Employee name: ZhangSan"
说实话,对于完成本系列文章的目标-继承-而言,真找不到什么缺点。方法一如jQuery一样简洁明了。
代码分析
为了一个漂亮的调用方式,内部实现的确复杂了很多,不过这些也是值得的 - 一个人的思考带给了无数程序员快乐的微笑 - 嘿嘿,有点肉麻。
不过其中的一段代码的确迷惑我一段时间:
fnTest = /xyz/.test(function(){xyz;}) "htmlcode">// 自执行的匿名函数创建一个上下文,避免引入全局变量 (function() { // initializing变量用来标示当前是否处于类的创建阶段, // - 在类的创建阶段是不能调用原型方法init的 // - 我们曾在本系列的第三篇文章中详细阐述了这个问题 // fnTest是一个正则表达式,可能的取值为(/\b_super\b/ 或 /.*/) // - 对 /xyz/.test(function() { xyz; }) 的测试是为了检测浏览器是否支持test参数为函数的情况 // - 不过我对IE7.0,Chrome2.0,FF3.5进行了测试,此测试都返回true。 // - 所以我想这样对fnTest赋值大部分情况下也是对的:fnTest = /\b_super\b/; var initializing = false, fnTest = /xyz/.test(function() { xyz; }) "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) "htmlcode">(function() { var initializing = false, fnTest = /xyz/.test(function() { xyz; }) "function" && typeof _super[name] === "function" && fnTest.test(prop[name])) { prototype[name] = fn(name, prop[name]); } else { prototype[name] = prop[name]; } } function Class() { if (!initializing && this.init) { this.init.apply(this, arguments); } } Class.prototype = prototype; Class.constructor = Class; Class.extend = arguments.callee; return Class; }; })();写到这里,大家是否觉得Resig的实现和我们在第三章一步一步实现的jClass很类似。 其实在写这一系列的文章之前,我已经对prototype、mootools、extjs、 jQuery-Simple-Inheritance、Crockford-Classical-Inheritance这些实现有一定的了解,并且大部分都在实际项目中使用过。 在第三章中实现jClass也参考了Resig的实现,在此向Resig表示感谢。
下来我们就把jClass改造成和这里的Class具有相同的行为。我们的实现
将我们在第三章实现的jClass改造成目前John Resig所写的形式相当简单,只需要修改其中的两三行就行了:(function() { // 当前是否处于创建类的阶段 var initializing = false; jClass = function() { }; jClass.extend = function(prop) { // 如果调用当前函数的对象(这里是函数)不是Class,则是父类 var baseClass = null; if (this !== jClass) { baseClass = this; } // 本次调用所创建的类(构造函数) function F() { // 如果当前处于实例化类的阶段,则调用init原型函数 if (!initializing) { // 如果父类存在,则实例对象的baseprototype指向父类的原型 // 这就提供了在实例对象中调用父类方法的途径 if (baseClass) { this._superprototype = baseClass.prototype; } this.init.apply(this, arguments); } } // 如果此类需要从其它类扩展 if (baseClass) { initializing = true; F.prototype = new baseClass(); F.prototype.constructor = F; initializing = false; } // 新创建的类自动附加extend函数 F.extend = arguments.callee; // 覆盖父类的同名函数 for (var name in prop) { if (prop.hasOwnProperty(name)) { // 如果此类继承自父类baseClass并且父类原型中存在同名函数name if (baseClass && typeof (prop[name]) === "function" && typeof (F.prototype[name]) === "function" && /\b_super\b/.test(prop[name])) { // 重定义函数name - // 首先在函数上下文设置this._super指向父类原型中的同名函数 // 然后调用函数prop[name],返回函数结果 // 注意:这里的自执行函数创建了一个上下文,这个上下文返回另一个函数, // 此函数中可以应用此上下文中的变量,这就是闭包(Closure)。 // 这是JavaScript框架开发中常用的技巧。 F.prototype[name] = (function(name, fn) { return function() { this._super = baseClass.prototype[name]; return fn.apply(this, arguments); }; })(name, prop[name]); } else { F.prototype[name] = prop[name]; } } } return F; }; })(); // 经过改造的jClass var Person = jClass.extend({ init: function(name) { this.name = name; }, getName: function(prefix) { return prefix + this.name; } }); var Employee = Person.extend({ init: function(name, employeeID) { // 调用父类的方法 this._super(name); this.employeeID = employeeID; }, getEmployeeIDName: function() { // 注意:我们还可以通过这种方式调用父类中的其他函数 var name = this._superprototype.getName.call(this, "Employee name: "); return name + ", Employee ID: " + this.employeeID; }, getName: function() { // 调用父类的方法 return this._super("Employee name: "); } }); var zhang = new Employee("ZhangSan", "1234"); console.log(zhang.getName()); // "Employee name: ZhangSan" console.log(zhang.getEmployeeIDName()); // "Employee name: ZhangSan, Employee ID: 1234"这篇文章就接受到这了,下面还有一个系列的文章,大家都可以看下
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]