直接看代码吧:

        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()源码分析的更多相关文章

  1. Java 序列化和反序列化(三)Serializable 源码分析 - 2

    目录 Java 序列化和反序列化(三)Serializable 源码分析 - 2 1. ObjectStreamField 1.1 数据结构 1.2 构造函数 2. ObjectStreamClass ...

  2. Vert.x系列(三)--ClusteredEventBus源码分析

    前言:因为ClusteredEventBus涉及集群,有必产生网络问题,从而引入了NetServer.ServerID等涉及网络,端口的类.在之前的EventBusImpl中, 使用的数据结构是以ad ...

  3. 一个普通的 Zepto 源码分析(三) - event 模块

    一个普通的 Zepto 源码分析(三) - event 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块, ...

  4. ABP源码分析三:ABP Module

    Abp是一种基于模块化设计的思想构建的.开发人员可以将自定义的功能以模块(module)的形式集成到ABP中.具体的功能都可以设计成一个单独的Module.Abp底层框架提供便捷的方法集成每个Modu ...

  5. 一个普通的 Zepto 源码分析(二) - ajax 模块

    一个普通的 Zepto 源码分析(二) - ajax 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块,以 ...

  6. 一个普通的 Zepto 源码分析(一) - ie 与 form 模块

    一个普通的 Zepto 源码分析(一) - ie 与 form 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核 ...

  7. 【JUC】JDK1.8源码分析之ReentrantLock(三)

    一.前言 在分析了AbstractQueuedSynchronier源码后,接着分析ReentrantLock源码,其实在AbstractQueuedSynchronizer的分析中,已经提到过Ree ...

  8. 【JUC】JDK1.8源码分析之ArrayBlockingQueue(三)

    一.前言 在完成Map下的并发集合后,现在来分析ArrayBlockingQueue,ArrayBlockingQueue可以用作一个阻塞型队列,支持多任务并发操作,有了之前看源码的积累,再看Arra ...

  9. 【JUC】JDK1.8源码分析之AbstractQueuedSynchronizer(二)

    一.前言 在锁框架中,AbstractQueuedSynchronizer抽象类可以毫不夸张的说,占据着核心地位,它提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.所以很有必 ...

随机推荐

  1. gulp入门演练

    一直想学习下gulp看了蛮多资料,然后总是感觉是是而非,突然开窍了,把自己学会的过程给大家分享下,入门超级简单的 gulp安装 安装gulp 如果参数-g 表示全局安装 $ npm install g ...

  2. java的4种代码块

    一.普通代码块 直接在一个方法中出现的{}就称为普通代码块,例子程序如下: public class CodeDemo01{ public static void main(String[] args ...

  3. git clone --early EOF

    出现这个问题可能需要重新检查以下方面: 1. Android studio Git 的安装地址:  ..../Git/cmd/git.exe 记得在环境变量 --Path 中进行配置: ,..../G ...

  4. linux哲学思想

    linux哲学思想 1.一切皆为文件 linux将所有的对象几乎都抽象为文件,无论是硬件设备.还是通讯接口都当做文件处理,这样可以设计统一的访问控制操作(read();write();delete() ...

  5. IIS 常见问题集记录

    win7 iis7.5 详细错误信息模块 IIS Web Core 通知 BeginRequest 处理程序 尚未确定 错误代码 0x80070021 配置错误 不能在此路径中使用此配置节.如果在父级 ...

  6. Java中用ClassLoader载入各种资源(类、文件、web资源)的方法

    lassLoader主要对类的请求提供服务,当JVM需要某类时,它根据名称向ClassLoader要求这个类,然后由ClassLoader返回这个类的class对象. ClassLoader负责载入系 ...

  7. PLL输出怎么不能配置成我想要的时钟

    如下图,我的clk_out7想配置成160M,十几输出变为了150M

  8. ios基础篇(三十)—— AFNetworking的使用

    一.AFNetworking的创建 1.新建工程,命名为AFNDemo 2.导入AFNetworking.h AFNetworking文件下载:https://github.com/AFNetwork ...

  9. git pull 和本地文件冲突问题解决

    具体方法如下 git pull origin 分支 //出现错误 git stash  缓存起来 git pull origin 分支 git stash pop //还原 git stash cle ...

  10. Java自由块(静态和非静态)(转载)

    java中的自由块分为两种: 静态块和非静态块 静态块: public class Test { 2 static int x = 10; 3 //静态块:静态块的执行时机是在class文件装载的时候 ...