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队列,可以用于构建锁或者其他相关同步装置的基础框架.所以很有必 ...
随机推荐
- Ubuntu 和 Redhat / Fedora 服务管理命令对比表(附Fedora16新的服务管理工具systemctl )
以 apache/httpd 服务作为例子 任务 Red Hat / Fedora Ubuntu Ubuntu (with sysv-rc-conf or sysvconfig) 立即启动/停止某服务 ...
- Javascript 数组常用操作方法
一.数组 Array 1.创建数组 /* 构造函数 */ var arr1 = new Array(); //创建一个空数组 var arr1 = new Array(5); //创建指定长度数组(数 ...
- Error:No suitable device found: no device found for connection "System eth0"
环境描述: Vmware 故障说明: 在克隆几台虚拟机,发现启动后不能配置IP地址等信息,使用linux命令: “ifup eth0”也不能激活网卡, 而在使用"service networ ...
- ajax post 请求415\ 400 错误
今天用ajax 向后台发送 post请求时,出现了两个问题: 1, 发送请求后,控制台 返回 Unsupported media type-415(不支持的媒体类型),这时突然想起来,post 请求 ...
- HAOI2012音量调节
Description 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都要改变一次音量.在演出开始之前,他已经做好了一个列表,里面写着在每首歌开始之前他想要改 ...
- viewPager + fragment
有两种实现方式,一种是 fragmentActivity + FragmentPagerAdapter (Fragment,FragmentManager需要导包:android.support.v4 ...
- CSS3的基础用法
CSS3的现状:1.浏览器支持程度差,需要添加私有前缀 2.移动端支持优于PC端 3.不断改进中 4.应用相对广泛 在CSS3中增加新增了许多灵活查找元素的方法,极大的提高了查找元素的效率和精准度.C ...
- flume原理及代码实现
转载标明出处:http://www.cnblogs.com/adealjason/p/6240122.html 最近想玩一下流计算,先看了flume的实现原理及源码 源码可以去apache 官网下载 ...
- node.js基础 1之 HTTP事件回调进阶(HTTP模块)
HTTP概念进阶 1. 什么是回调? 回调是异步编程时的基础,将后续逻辑封装成起始函数的参数,逐层嵌套 2. 什么是同步/异步? 同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯 ...
- Java_I/O输入输出_实现读取文件时出现一个表示读取进度的进度条。可以使用java.swing包提供的输入流类ProgressMonitorInputStream
import java.io.*; import javax.swing.*; public class Student { public static void main(String[] temp ...