Join Resig's “Simple JavaScript Inheritance ”
Original Script - John Resig Simple JavaScript Inheritance
(function(){
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
this.Class = function(){};
Class.extend = function(prop) {
var _super = this.prototype;
initializing = true;
var prototype = new this();
initializing = false;
for (var name in prop) {
prototype[name] = typeof prop[name] == "function" &&
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
(function(name, fn){
return function() {
var tmp = this._super;
this._super = _super[name];
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, prop[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;
};
})();
Breakdown of the Simple Inheritance script
下面我们来分析一下, 它是如何实现和有哪些技术被使用.
- (function(){ // ... })(); /*创建一个自执行匿名函数, 使这段代码被载入时候自动执行。为代码创建一个作用域,避免污染全局*/
- 作用:可以用它创建命名空间,只要把自己所有的代码都写在这个特殊的函数包装内,那么外部就不能访问,除非你允许(变量前加上window,这样该函数或变量就成为全局)。各JavaScript库的代码也基本是这种组织形式。
- var initializing = false
这 initializing 变量意思很直接, 它是boolean来检查Class Function(稍后介绍)什么时候被调用. 在创建实例时设置 initializing 为true/false 或者只是返回一个对象指向当前的原型链上来达到"继承"的目的.
如果我们创建一个实例(initializing == false), 正好Class有一个init方法, 这样 init 会自动执行。 再或者, 如果我们仅仅将它分配给原型上(initializing == true), 将不会发生什么, init 方法不会被执行。这样做是为了避免 每次调用构造方法都要执行 init 方法. (var prototype = new this());.
- fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
这个fnTest的目的就是为了验证 class method 中是否使用了 "_super()" 调用. 这种技术叫做 " function decompilation(函数反编译)" 也叫做 "function serialisation(函数序列化)", Function serialisation 是在一个函数被转换成字符串时发生的. 现在很多浏览器都支持 toString 方法。
测试 Function serialisation, fnTest 使用一个匿名函数 funciton(){xyz;} 设置内容为 "xyz", 在转变成字符串后使用正则对 "xyz" 进行查找. 它将返回true (如果浏览器支持 function serialisation) 因为 函数将转变成字符串所以 "xyz" 也民属于字符串的一部分. 在这个例子中 fnTest 将返回 "/\b_super\b/", 另一种则返回 "/.*/" 如果浏览器不支持 function serialisation 则始终返回 true。(这个指的是原始代码中的fnTest.test)使用 fnTest 正则, 和 函数序列化技术, 我们能很容易方法中是否使用了 "_super" 如果它们使用, 则执行一些特殊方法. 反之正常. 这个特殊方法是为了避免在 父类与子类中同时出现同一个方法. 父类将会被覆盖.
- this.Class = function(){};
- Class.extend = function(prop) {
- // ...
- }
加入 extends 方法和一个简单的 prop(一个对象) 参数. 它将返回 新构造方法的原型 + 父对象的原型;
- var _super = this.prototype;
将当前对象的原型对象存储在 _super中. this.prototype是被扩展对象的原型, 它可以访问父级方法在你需要的地方, 这个变量叫什么 _super , 是因为 super 是保留字. 尽管现在还没有应用起来.
- initializing = true;
- var prototype = new this();
- initializing = false;
- for (var name in prop) {
- // ...
- }
- prototype[name] = typeof prop[name] == "function" &&
- typeof _super[name] == "function" && fnTest.test(prop[name]) ?
- (function(name, fn){
- return function() {
- // special handling for _super
- };
- })(name, prop[name]) :
- prop[name];
typeof prop[name] == "function") (typeof _super[name] == "function") (fnTest.test(prop[name]) == true)- if (typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])) {
- prototype[name] = (function(name, fn){
- return function() {
- // special handling for _super
- };
- })(name, prop[name]);
- } else {
- // just copy the property
- prototype[name] = prop[name];
- }
- // special handling for super
- var tmp = this._super;
- this._super = _super[name];
- var ret = fn.apply(this, arguments);
- this._super = tmp;
- return ret;
- var Foo = Class.extend({
- qux: function() {
- return "Foo.qux";
- }
- });
- var Bar = Foo.extend({
- qux: function() {
- return "Bar.qux, " + this._super();
- }
- });
- Bar.prototype.qux = function () {
- var tmp = this._super;
- this._super = Foo.prototype.qux;
- var ret = (function() {
- return "Bar.qux, " + this._super();
- }).apply(this, arguments);
- this._super = tmp;
- return ret;
- }
- function Class() {
- if ( !initializing && this.init )
- this.init.apply(this, arguments);
- }
- Class.prototype = prototype;
- Class.constructor = Class;
- Class.extend = arguments.callee;
- Class.extend = extend;.
- return Class;
Join Resig's “Simple JavaScript Inheritance ”的更多相关文章
- Simple JavaScript Inheritance(John Resig)
I’ve been doing a lot of work, lately, with JavaScript inheritance – namely for my work-in-progress ...
- Simple JavaScript Inheritance
1. [代码]Simple JavaScript Inheritance (function(){ var initializing = false, fnTest = /xyz/.test ...
- Simple JavaScript Inheritance--一个极简JS面向对象-类库
面向对象 面向对象思想的几个重要特征(针对类的要求): 抽象-封装.信息隐藏(将内部实现的方法和数据隐藏, 定义开放的接口) 继承-子类可以使用父类的资源,并可以定制自己的资源, 资源包括方法和数据 ...
- JavaScript Inheritance All in One
JavaScript Inheritance All in One constructor inheritance prototype chain inheritance "use stri ...
- 44 答疑(三)--join的写法/Simple nested loop join的性能问题/Distinct和group by的性能/备库自增主键问题
44 答疑(三) Join的写法 35节介绍了join执行顺序,加了straight_join,两个问题: --1 如果用left join,左边的表一定是驱动表吗 --2 如果两个表的join包含多 ...
- 再读<<基于MVC的JavaScript Web 富应用开发>>
工作的时候粗读过这本书的几章内容,真真是囫囵吞枣~~目前手边就剩这一本,重新读才觉得先前是没看明白啊!这个作者博闻强识,对这些插件.库了解的非常多.记录下,查的资料 订阅/发布 jQuery Tiny ...
- 大型应用的javascript架构
来源:http://blog.leezhong.com/tech/2010/11/29/javascript-arch.html 目前很多网站基本没有明确的前端架构,大多是服务端渲染视图页,输出到浏览 ...
- 【Cocos2d-Js基础教学(2)类的使用和面向对象】
类的使用和面向对象 大家都知道在cocos2d-x 底层是C++编写的,那么就有类的概念和继承机制. 但是在JS中,是没有类这个概念的,没有提供类,没有C++的类继承机制. 那么JS是通过什么方式实现 ...
- 从cocos2d-html5中提取出来的,用做前端开发的框架——cc.js
从cocos2d-html5中提取出来的,用做前端开发的框架——cc.js /************************************************************* ...
随机推荐
- 资料汇总--Web前端
01.前端技能汇总 02.gitHub优秀前端资料分享 03.大前端 HTML Doctype作用?严格模式与混杂模式如何区分?它们有何意义? 1. <!DOCTYPE> 声明位于文档中的 ...
- java 并发(五)---AbstractQueuedSynchronizer(3)
文章代码分析和部分图片来自参考文章 问题 : CountDownLatch 和 CyclicBarrier 的区别 认识 CountDownLatch 分析这个类,首先了解一下它所可以 ...
- [android] 安卓自定义样式和主题
简单练习自定义样式和主题,样式是加在View上,主题是加在Application或者Activity上 styles.xml <?xml version="1.0" enco ...
- URL 编码 之 我见
URL编码 编辑 url编码是一种浏览器用来打包表单输入的格式.浏览器从表单中获取所有的name和其中的值 ,将它们以name/value参数编码(移去那些不能传送的字符,将数据排行等等)作为URL的 ...
- Java Object类的toString()方法
Java只要定义一个类,那么它都在继承,没有说明它在继承哪个类的时候,则默认继承java.lang.Object类,也就是说Object类是所有类的父类.看下面一段代码. public class O ...
- HDU 1561 The more, The Better 经典树形DP
The more, The Better Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- POJ 2955 Brackets 区间DP 最大括号匹配
http://blog.csdn.net/libin56842/article/details/9673239 http://www.cnblogs.com/ACMan/archive/2012/08 ...
- Linux 安装 EPEL YUM源
原文:https://blog.csdn.net/harbor1981/article/details/51135623 我们用yum安装软件时,经常发现我们的yum源里面没有该软件,需要自己去wge ...
- JDK自带工具keytool生成ssl证书 和 HTTPS双向认证
创建证书(第一步) keytool -genkey -alias "baidu" -keypass "123456" -keystore "D:/ba ...
- org.apache.ibatis.binding.BindingException
1.异常提示: org.apache.ibatis.binding.BindingException: Mapper method 'com.artup.dao.WorksDao.selectWork ...