js框架开发之旅--对父类的访问
2013-10-15 11:41
239 查看
上一章我们讨论了基于原型的继承和基于类的继承。这一章我们继续介绍如何实现面向对象的js,我们要阐述turing.oo的原理,并且尝试去实现super方法。
apply看上去很神奇,但是有些人不太喜欢他,因为它使用复杂不利于封装。上面的例子,我们在类的构造函数中调用初始化方法,并使用this和arguments作为参数。this表示将方法绑定到新创建的实例上执行,arguments代表你给构造函数传递的所有参数。
根据上面的代码,所有的创建的类都应该有一个默认的初始化方法。如果你不需要在初始化的时候做什么,你可以定义一个简单的空方法:
引入对象应该遵守一定的规则,以便让代码有一个统一的规范。
方法必须从指定的类里继承
initialize方法不能被覆盖
可以继承多个对象
如果你使用turing.oo.create创建了类,你的类里继承了引入的方法。为了保持代码的可读性,我们没有在create里进行属性继承,我们使用了一个新的方法mixin。我们尝试写一下符合上面规则的伪代码:
下面的例子,我们创建了User类,并且通过继承User类创建了SuperUser:
我们测试上面的代码:
我们还没有实现super,执行结果如下:
上面的代码说明新的初始化方法覆盖了父类的方法。现在我们想要调用父类的初始化方法,这里再次使用了apply。
代码看上去还不太完美,许多语言的super的实现都比较简单,让用户通过apply来实现super的调用确实不太友好。最好的办法就是在父类的原型中实现super方法,把上面的代码封装起来。
这样的代码看上去简单多了并且便于理解。
牧客网--让自由职业成为一个靠谱的工作
更深层次的类的创建
Turing的方法Class.create方法创建一个类,使用new创建的过程中会调用初始化方法。方法非常简单:create: function() { var methods = null, parent = undefined, klass = function() { this.initialize.apply(this, arguments); };
apply看上去很神奇,但是有些人不太喜欢他,因为它使用复杂不利于封装。上面的例子,我们在类的构造函数中调用初始化方法,并使用this和arguments作为参数。this表示将方法绑定到新创建的实例上执行,arguments代表你给构造函数传递的所有参数。
根据上面的代码,所有的创建的类都应该有一个默认的初始化方法。如果你不需要在初始化的时候做什么,你可以定义一个简单的空方法:
if (!klass.prototype.initialize) klass.prototype.initialize = function(){};
语法技巧
在我们的类里继承其他对象是一个非常有用的技巧。语法如下:var MixinUser = turing.Class({ include: User, initialize: function(log) { this.log = log; } });
引入对象应该遵守一定的规则,以便让代码有一个统一的规范。
方法必须从指定的类里继承
initialize方法不能被覆盖
可以继承多个对象
如果你使用turing.oo.create创建了类,你的类里继承了引入的方法。为了保持代码的可读性,我们没有在create里进行属性继承,我们使用了一个新的方法mixin。我们尝试写一下符合上面规则的伪代码:
mixin: function(klass, things) { if "there are some valid things" { if "the things are a class" { "use turing.oo.extend to copy the methods over" } else if "the things are an array" { for "each class in the array" { "use turing.oo.extend to copy the methods over" } } } },
父类
之前我们提到了Prototype的super功能。Prototype允许类通过addMethods扩展方法,相同名称的方法会被覆盖,但是我们仍然可以通过$super来方法父类的方法。下面的例子,我们创建了User类,并且通过继承User类创建了SuperUser:
var User = turing.Class({ initialize: function(name, age) { this.name = name; this.age = age; }, login: function() { return true; }, toString: function() { return "name: " + this.name + ", age: " + this.age; } }); var SuperUser = turing.Class(User, { initialize: function() { // Somehow call the parent's initialize } });
我们测试上面的代码:
given('an inherited class that uses super', function() { var superUser = new SuperUser('alex', 104); should('have run super()', superUser.age).equals(104); });
我们还没有实现super,执行结果如下:
Given an inherited class that uses super - should have run super(): 104 does not equal: undefined
上面的代码说明新的初始化方法覆盖了父类的方法。现在我们想要调用父类的初始化方法,这里再次使用了apply。
var SuperUser = turing.Class(User, { initialize: function() { User.prototype.initialize.apply(this, arguments); } });
代码看上去还不太完美,许多语言的super的实现都比较简单,让用户通过apply来实现super的调用确实不太友好。最好的办法就是在父类的原型中实现super方法,把上面的代码封装起来。
var SuperUser = turing.Class(User, { initialize: function() { this.$super('initialize', arguments); }, toString: function() { return "SuperUser: " + this.$super('toString'); } });
这样的代码看上去简单多了并且便于理解。
结论
我们现在已经实现了一个简单,可读的面向对象的类。我们以后的架构都是基于这个类实现的。我希望通过最近的两篇文章,能让你感受到js的简单和灵活。牧客网--让自由职业成为一个靠谱的工作
相关文章推荐
- Node.js开发手册(四)-Redis数据库访问
- 十个拥有丰富UI组件的JS开发框架
- 当今最流行的Node.js应用开发框架简介
- Node.js开发之访问Redis数据库教程
- Node.js开发之访问Redis数据库教程
- 我的基于asp.net mvc5 +mysql+dapper+easyui 的Web开发框架(1)数据库访问(0)
- [js高手之路]从零开始打造一个javascript开源框架gdom与插件开发免费视频教程连载中
- ajax的js开发的目录规范 (目录框架下载)
- WebApp开发框架Ionic+AngularJS+Cordova
- [IOS_HTML5]各种JS框架介绍--用HTML5/CSS3/JS开发Android/IOS应用
- 【JavaScript】前端开发框架三剑客—AngularJS VS. Backone.js VS.Ember.js
- Node.js开发框架Express4.x
- 移动架构32_自定义网络访问框架开发
- 当今最流行的Node.js应用开发框架简介
- js各框架中的互相访问
- Ajax 开发框架property 1.5 js
- Node.js的原型继承函数util.inherits + 开发框架Express4.x
- 基于 Node.js 平台,快速、开放、极简的 web 开发框架。
- QuickCSharp框架开发(16)------基于角色的访问控制(验证思路回顾)
- 我的第一个python web开发框架(7)——本地部署前端访问服务器