`
liu78778
  • 浏览: 16291 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

来贴存根: 理解Ext.extend函数 3.1

阅读更多
今天群里有人闻起来, 找了半天, 特地将以前稿子存根



首先感谢LZ的分析, 站在LZ的基础上, 我自己也分析了一遍, 希望大家能更明白.
extend : function(){
	// inline overrides, 临时函数用于覆盖属性到this上.
	var io = function(o){
		for(var m in o){
			this[m] = o[m];
		}
	};
	var oc = Object.prototype.constructor; //保留Object的构造器的引用.

	//上面的部分为Ext.extend函数的私有变量区, 使用闭包.
	//下面的部分是Ext.extend调用者实际调用的函数.
	return function(sb, sp, overrides){
		/**
		 * 在这个if语句中完成了对Ext.extend方法的重载. Ext.extend有两种调用方式.
		 * 1. var Subclass = function(){...};
		 *    Ext.extend(Subclass, Superclass, {...});
		 * 2. var Subclass = Ext.extend(Superclass, {...});
		 * 
		 * 方式1和方式2的不同在于, 参数顺序的错位. 其中子类的引用在方式2中没有, 导致原本在2,3位置的父类
		 * 和属性集变成了1,2位.
		 * 为了屏蔽两种调用方式的差异, if(Ext.isObject(sp)) 用来判断2号参数的类型, 如果不是"Object"
		 * 类型就是第一种调用方式, 否则就是第二种调用方式.
		 * 当知晓是第二种调用方式之后, 需要修正参数的位置, 于是出现了一下两个语句:
		 * overrides = sp; //修正3号参数(原2号)
		 * sp = sb; //修正2号参数(原1号)
		 * 那么空出来的1号参数怎么办呢? sb对应第一种调用方式应该是子类引用. 
		 * 而第二种的子类引用正是Ext.extend返回的.
		 * 所以这里就给了一个默认的构造函数给子类.(这也是1,2两种方式的不同: 是否自定义构造函数.)
		 * 默认的构造函数的内容就是在子类对象的作用域内调用父类的构造函数, 即获取父类的非原型属性(当然
		 * 这个获取的过程是new子类对象时产生的, 而现在只是产生了这个能够调用父类函数的引用作为子类
		 * 的构造函数).
		 * 自此, 两种方式的重载完成修正, 下面可以正常的按照3个参数(即第一种方式)建立继承关系.
		 */
		if(Ext.isObject(sp)){
			overrides = sp;
			sp = sb;
			sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
		}
		
		/**
		 * 上面说到了子类的构造方法能够获取父类的非原型属性, 那么最关键的父类原型的内容就在下面.
		 * 值得注意的是: 要准确的区分静态属性(方法)与实例属性(方法).
		 * 静态属性(方法)指的是类(构造器)的直接属性(方法), 这里就是sb.[...]. 这种方式书写, 不会作为
		 * 对象的属性(方法), 只能通过类的引用(类名)来访问.
		 * 实例属性(方法)指的是类(构造器)原型对象的属性(方法), 这里就是sbp.[...]. 这种方式的
		 * 属性(方法)才会被对象(实例)所拥有.
		 * 同样, 构造器函数内部定义的, 附加到this之上的属性也是实例属性(方法).
		 */
		//这里建立一个空函数F是去除父类的非原型属性, 防止多拷贝一次非原型属性, 影响性能.
		var F = function(){}, 
			sbp,	//子类原型的引用. subclass-prototype 的缩写.
			spp = sp.prototype;	//父类原型的引用. superclass-prototype 的缩写

		F.prototype = spp;
		//获取在父类原型基础上产生的对象作为子类原型, 这里建立了原型继承关系.
		sbp = sb.prototype = new F(); 
		sbp.constructor=sb; //修正子类的构造函数指向子类(原本指向F, 因为是new F()出来的原型.
		sb.superclass=spp; //设置子类引用父类原型对象, 静态属性.
		if(spp.constructor == oc){ //这里修正了下父类的构造函数, 若为Object就扭转到自身.
			spp.constructor=sp;
		}
		//子类的override静态方法, o为属性集, 用于覆盖原本的子类原型的属性.
		sb.override = function(o){ 
			Ext.override(sb, o);
		};
		//子类的实例方法, 可以获取到父类原型的引用.
		sbp.superclass = sbp.supr = (function(){	
			return spp;
		});
		//子类的实例方法, 覆盖对象的属性. 实际上此方法依赖js的动态语言特性实现.
		sbp.override = io; 
		//最后, 将继承时需要的属性(方法)覆盖到子类的原型, 即增加/修改了子类的实例属性(方法).
		Ext.override(sb, overrides); 
		sb.extend = function(o){return Ext.extend(sb, o);};
		return sb;
	};
}(),

分享到:
评论

相关推荐

    discord.py存根:discord.py存根

    不和谐存根 该软件包包含类型存根,以为discord.py提供更精确的静态类型和类型推断。 安装 pip install discord.py-stubs 注意:由于discord.py使用名称空间包作为其扩展名, mypy必须将mypy配置为使用带有--...

    sharedpreferences-stub:存根 android.content.SharedPreferences

    这个库的存在是为了恢复SharedPreferences的存根版本。 请原谅我。GitHub 托管的 Maven 存储库命令mvn deploy将构建的 jars 上传到github.com/mozilla-services/android-sync的mvn-repo分支。 您需要拥有对该 git ...

    带存根介绍信格式.pdf

    带存根介绍信格式.pdf

    小学生借读证明存根excel模版下载.xlsx

    小学生借读证明存根excel模版下载.xlsx

    CyUSB.dll文件调用接口函数说明

    CyAPI.lib是一个库文件,它包含了CyUSB.dll中所有函数的存根(stub)代码,供编译器在链接阶段使用。当开发者编写代码时,使用到CyUSB.dll提供的API函数,编译器实际上链接的是CyAPI.lib文件,而运行时通过该库找到...

    web-stub:存根 node.js 网络项目

    这不仅提高了开发效率,还使得项目更容易理解和维护,对于新手和经验丰富的开发者来说都是一个极好的起点。 此外,Node.js社区拥有丰富的模块和库,例如Express.js是一个常用的Web应用框架,它简化了路由、中间件和...

    stubulika:又一个存根服务器......

    受 stub.by 的启发,这是一个存根应用程序,用于根据不同的请求提供预制响应,并公开一个 REST API,用于管理创建存根请求/响应。 用 spring boot / java 8 & react 编写,这是一个同构 webapp 的例子,它在没有 ...

    gsoap源代码 带实例带教程带使用说明

    4) soapStub.h // soap的存根文件,定义了我们编写的头文件里对应的远程调用模型 5) add.nsmap //XML服务命名空间 6)服务器端要载入的文件有:soapServer.cpp,soapC.cpp,stdsoap2.cpp; 要包含的文件有:gservice...

    sinon-chai:使用Sinon.JS模拟框架的断言扩展Chai

    Sinon-Chai提供了一组自定义断言,以便通过断言库使用间谍,存根和框架。 通过Sinon.JS的所有强大工具,您可以获得Chai的所有好处。 而不是使用Sinon.JS的断言: sinon . assert . calledWith ( mySpy , "foo" ) ;...

    机场英语对话PPT教案.pptx

    这篇文档是关于机场英语对话的教学材料,主要涵盖了与机场相关的基本词汇、短语以及重要的语法点。以下是相关知识点的详细说明: ...这份教学材料对于英语学习者,尤其是准备出国旅行或工作的人来说非常有价值。

    特定:使用clojure.spec生成模拟和其他测试双打

    测试双打包括模拟函数、代理对象(proxies)和存根(stubs),它们在测试中代替实际的函数或对象,返回预设的结果或记录调用情况。在Clojure中,虽然`clojure.spec`本身并不直接提供模拟和存根功能,但可以结合其他...

    altspacevr-project-threejs-shaders:使用Three.js框架创建着色器的项目存根

    使用此项目存根可使用three.js框架实现着色器项目。 是一个WebGL库,可以快速上手并且功能强大。 该项目的第一部分是在此框架中实现基本的phong着色器。 该项目的第二部分是实现至少一个您选择的有趣的自定义着色...

    Golang存根主服务器keyshop.zip

    keyshop 是一个小的,用于提供测试 E2E 扩展的 Golang 存根(stub)主服务器。 标签:keyshop

    东北财经大学20春《信息系统分析与设计》单元作业三(参考答案).docx

    - **描述内容**:图形模型有助于理解那些很难用语言来描述的复杂关系。 - 正确答案是B,正确。 ### 23. 结构化设计的原则 - **描述内容**:结构化设计的两个基本原则是程序模块应该设计成耦合松散和高度内聚。 - ...

    基于BP神经网络税收模型的经济分析_沈存根[借鉴].pdf

    在税收预测模型的建立过程中,作者沈存根采用的是一种三层的BP神经网络模型,具体包括输入层、一个隐含层和输出层。输入层包含8项经济指标,分别是第一产业增加值、第二产业增加值、第三产业增加值、固定资产投资...

    7digital-api-stubber:使用Node.js API客户端进行集成测试中的7digital API的流利助手

    一个帮助程序包,它将一个API存根作为一个子进程启动,并允许您在集成测试中流畅地配置存根的行为。 您可以通过以下方式对响应进行存根: respondsWithFile(filePath)将使用提供的文件路径的内容进行响应 ...

    golang写的grpc实例demo

    6. **客户端调用**:客户端可以使用生成的客户端存根来调用服务。以下是一个简单的示例: ```go conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure()) if err != nil { log.Fatalf("did not connect...

    pygenstub:从Python源文件中的文档字符串生成存根文件的实用程序-python source file

    如果函数的文档字符串包含sig字段,则该字段的值将用于通过以相同顺序将类型与参数匹配来生成存根。 例如,对于下面给出的功能: def foo ( a , b ): """Do foo. :sig: (int, str) -> None """ pygenstub将...

    webmock.cr:模拟HTTP

    webmock.cr 在用于存根HTTP::Client请求的库。 ...仅基于uri和默认响应的存根请求 WebMock .stub( :any , " www.example.com " ) response = HTTP :: Client .get( " http://www.example.com " )

Global site tag (gtag.js) - Google Analytics