google closure继承模块三:goog.base()源码分析
直接看代码吧:
base: function (me, opt_methodName, var_args) {
var caller = arguments.callee.caller;
if (caller.superClass_) {
// Copying using loop to avoid deop due to passing arguments object to
// function. This is faster in many JS engines as of late 2014.
var ctorArgs = new Array(arguments.length - 1);
for (var i = 1; i < arguments.length; i++) {
ctorArgs[i - 1] = arguments[i];
}
// This is a constructor. Call the superclass constructor.
return caller.superClass_.constructor.apply(me, ctorArgs);
}
// Copying using loop to avoid deop due to passing arguments object to
// function. This is faster in many JS engines as of late 2014.
var args = new Array(arguments.length - 2);
for (var i = 2; i < arguments.length; i++) {
args[i - 2] = arguments[i];
}
var foundCaller = false;
for (var ctor = me.constructor;
ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {
if (ctor.prototype[opt_methodName] === caller) {
foundCaller = true;
} else if (foundCaller) {
return ctor.prototype[opt_methodName].apply(me, args);
}
}
// If we did not find the caller in the prototype chain, then one of two
// things happened:
// 1) The caller is an instance method.
// 2) This method was not called by the right caller.
if (me[opt_methodName] === caller) {
return me.constructor.prototype[opt_methodName].apply(me, args);
} else {
console.log(
'goog.base called from a method of one name ' +
'to a method of a different name');
}
}
goog.base的代码其实并不复杂,
var caller = arguments.callee.caller;
caller是执行goog.base()这个方法的函数名称。通过判断函数是否有superClass_的属性,来区分是否此函数是子构造函数。
(superClass_这个属性就是之前goog.inherit()埋下的伏笔,不仅可以通过这个属性访问父构的原型对象,还可以判断执行goog.base()的函数是否为构造函数)
如果是自构造函数,就把当前子构造函数的this对象和agruments传递给父构造函数,调用父构造函数。通过在自构造函数中调用goog.base(this);
即可以让通过子构造函数创建出来的对象,拥有父构造函数创建出来的一些属性。
这就是为什么之前通过那个只有一个name属性显示“周杰伦”的构造函数A创建出来的新对象,拥有构造函数B,和C创建的一些属性。
(这里需要注意,在调用构造函数必须先用goog.inherit(childCtor,parentCtor)建立起继承关系。)
如果不是子构造函数的话,那么就是另一种可能性就是自构造函数原型对象中的方法。
var args = new Array(arguments.length - 2);
for (var i = 2; i < arguments.length; i++) {
args[i - 2] = arguments[i];
}
这时候goog.base()的前两个参数一个为作用域对象,一个则是方法名称,剩下的则为传入方法的参数,args即为提取出需要传入方法的参数,
目的是调用继承的父构造函数的原型对象的方法,第二个参数即为调用的方法名称,这个方法名称一般设为调用
goog.base()的子原型对象方法的名称(方法继承)。
for (var ctor = me.constructor;
ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {
if (ctor.prototype[opt_methodName] === caller) {
foundCaller = true;
} else if (foundCaller) {
return ctor.prototype[opt_methodName].apply(me, args);
}
}
这一段稍微有点绕,但是目的明确,看起来就不是那么晦涩了,首先ctor为原型对象constructor指向的子构造函数,
if (ctor.prototype[opt_methodName] === caller) {
foundCaller = true;
}
这段代码是为了检查子构原型对象的方法和调用继承的父构圆形对象的方法是否同名。然后通过
ctor = ctor.superClass_ && ctor.superClass_.constructor
通过superClass_属性,找到父构造函数的原型对象,然后constructor指向的当然是父构造函数,都是存在的。所以
return ctor.prototype[opt_methodName].apply(me, args);
即调用父构造函数原型对象的同名方法。(此时的ctor为子构造函数superClass_指向的父构造函数)
google closure继承模块三:goog.base()源码分析的更多相关文章
- Java 序列化和反序列化(三)Serializable 源码分析 - 2
目录 Java 序列化和反序列化(三)Serializable 源码分析 - 2 1. ObjectStreamField 1.1 数据结构 1.2 构造函数 2. ObjectStreamClass ...
- Vert.x系列(三)--ClusteredEventBus源码分析
前言:因为ClusteredEventBus涉及集群,有必产生网络问题,从而引入了NetServer.ServerID等涉及网络,端口的类.在之前的EventBusImpl中, 使用的数据结构是以ad ...
- 一个普通的 Zepto 源码分析(三) - event 模块
一个普通的 Zepto 源码分析(三) - event 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块, ...
- ABP源码分析三:ABP Module
Abp是一种基于模块化设计的思想构建的.开发人员可以将自定义的功能以模块(module)的形式集成到ABP中.具体的功能都可以设计成一个单独的Module.Abp底层框架提供便捷的方法集成每个Modu ...
- 一个普通的 Zepto 源码分析(二) - ajax 模块
一个普通的 Zepto 源码分析(二) - ajax 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块,以 ...
- 一个普通的 Zepto 源码分析(一) - ie 与 form 模块
一个普通的 Zepto 源码分析(一) - ie 与 form 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核 ...
- 【JUC】JDK1.8源码分析之ReentrantLock(三)
一.前言 在分析了AbstractQueuedSynchronier源码后,接着分析ReentrantLock源码,其实在AbstractQueuedSynchronizer的分析中,已经提到过Ree ...
- 【JUC】JDK1.8源码分析之ArrayBlockingQueue(三)
一.前言 在完成Map下的并发集合后,现在来分析ArrayBlockingQueue,ArrayBlockingQueue可以用作一个阻塞型队列,支持多任务并发操作,有了之前看源码的积累,再看Arra ...
- 【JUC】JDK1.8源码分析之AbstractQueuedSynchronizer(二)
一.前言 在锁框架中,AbstractQueuedSynchronizer抽象类可以毫不夸张的说,占据着核心地位,它提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.所以很有必 ...
随机推荐
- Android中文TTS
如今在Android中开发中文语音播报有各式各样的云服务.SDK.API等云云,但是大部分服务是需要联网支持来进行语音合成的,在中文语音合成方面,科大讯飞无疑是佼佼者,而且它也提供了离线语音合成包(需 ...
- 使用VC++ ATL实现iStylePDF的COM插件
本文介绍了一种使用VC++ ATL(Active Template Library),利用ISPExtensibility接口,为 iStylePDF 加入功能简单的COM插件(addin),加入工具 ...
- 理解RESTful
REST全称为Representational State Transfer,可以翻译为“表现状态转换”,是由是Roy Thomas Fielding在他2000年的博士论文中提出的,目的是为了得到一 ...
- JAVA 1.7 流程控制语句 续
1. Java中的循环控制语句一共有3种,分别是while,do… while以及for循环.2. while循环,形式为:while(布尔表达式){//待执行的代码}3. do…while循环,新式 ...
- NTFS系统的ADS交换数据流
VC++ 基于NTFS的数据流创建与检测 What are Alternate Streams?(交换数据流) NTFS alternate streams , 或者叫streams,或者叫ADS(w ...
- 正则表达式抓取文件内容中的http链接地址
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; ...
- chrome 跨域设置
右击chrome快捷方式,在启动指令后面添加--disable-web-security,然后保存.如下: "C:\Program Files (x86)\Google\Chrome\App ...
- 改造laravel的登录流程,仅使用一个token登录laravel
背景:最近使用lavavel来改造目前的系统,但是之前的老系统还不能立马下线,这时就出现了双系统共存的状态,需要解决的一个问题就是一次登录2个系统. 第一步 修改中间件App\Http\Middlew ...
- MySQL update时使用联表,聚合
原文地址 http://stackoverflow.com/questions/3022405/mysql-update-query-with-left-join-and-group-by UPDAT ...
- 记一次使用jQuery清空元素
缘由: 数据量比较大,分页显示,页码是自己写的,动态创建页码,创建元素时会绑定元素的click事件,每次显示五个页码(1,2,3,4,5),点击2—4不换,点5,页码变成3,4,5,6,7. 遇到的问 ...