jQuery分离构造器
http://www.imooc.com/code/3401
通过new操作符构建一个对象,一般经过四步:
A.创建一个新对象
B.将构造函数的作用域赋给新对象(所以this就指向了这个新对象)
C.执行构造函数中的代码
D.返回这个新对象
最后一点就说明了,我们只要返回一个新对象即可。其实new操作符主要是把原型链跟实例的this关联起来,这才是最关键的一点,所以我们如果需要原型链就必须要new操作符来进行处理。否则this则变成window对象了。
下面这个例子,console结果一样。因为都用了new 。如果不用new就不一样了。
var $$ = ajQuery = function(selector) {
this.selector = selector;//this是aJquery {}name: "sss"__proto__: Object
return this
}
var ins = new $$("111");
console.log(ins);//
var $$2 = ajQuery2 = function(selector) {
this.selector = selector;
}
var ins2 = new $$2("2222");
console.log(ins2);//
去掉new 后。ajQuery里的return this就起了作用。
var $$ = ajQuery = function(selector) {
this.selector = selector;
return this
}
var ins = $$("111");
console.log(ins);//window
var $$2 = ajQuery2 = function(selector) {
this.selector = selector;
}
var ins2 = $$2("2222");
console.log(ins2);//undefined
我们常见的类式写法:
var $$ = ajQuery = function(selector) {
console.log(this instanceof ajQuery);//true ajQuery被new形式调用时,this就是ajQuery的实例
this.selector = selector;
return this
}
ajQuery.fn = ajQuery.prototype = {
selectorName:function(){
return this.selector;
},
constructor: ajQuery
}
var ins = new $$("111");
console.log(ins.selectorName());
首先改造jQuery无new的格式,我们可以通过instanceof判断this是否为当前实例
var $$ = ajQuery = function(selector) {
console.log(this);//先是window,再是ajQuery的实例
if(!(this instanceof ajQuery)){
return new ajQuery(selector);
}
this.selector = selector;
return this
}
ajQuery.fn = ajQuery.prototype = {
selectorName:function(){
return this.selector;
},
constructor: ajQuery
}
var ins = $$("111");
console.log(ins.selectorName());
注意千万不要像下面这样写:
var $$ = ajQuery = function(selector) {
this.selector = selector;
return new ajQuery(selector);
}
Uncaught RangeError: Maximum call stack size exceeded
这样会无限递归自己,从而造成死循环并且溢出。
jQuery为了避免出现这种死循环的问题,采取的手段是把原型上的一个init方法作为构造器。
function aJquery(selector){
return new aJquery.fn.init(selector);
}
aJquery.fn = aJquery.prototype = {
showName:function(){
console.log(this.name)
},
init: function(){
console.log(this);
}
}
var a = aJquery("sss");
a.showName();//报错
这样确实解决了循环递归的问题,但是又问题来了,init是ajQuery原型上作为构造器的一个方法,那么其this就不是ajQuery了,所以this就完全引用不到ajQuery的原型了(showName报错),所以这里通过new把init方法与ajQuery给分离成2个独立的构造器。
静态与实例方法共享设计
jQuery遍历方法:
$(".aaron").each() //作为实例方法存在
$.each() //作为静态方法存在
这是最常见的遍历方法,第一条语句是给有指定的上下文调用的,就是(".aaron")获取的DOM合集,第二条语句$.each()函数可用于迭代任何集合,无论是“名/值”对象(JavaScript对象)或数组。在迭代数组的情况下,回调函数每次都会传递一个数组索引和相应的数组值作为参数。本质上来说2个都是遍历,那么我们是不是要写2个方法呢?
我们来看看jQuery的源码:
jQuery.prototype = {
each: function( callback, args ) {
return jQuery.each( this, callback, args );
}
}
var Newobj = function(name){
this.name = name;
}
Newobj.showName = function(args){//静态方法:不能被实例对象调用
console.log(args);
}
Newobj.prototype = {
showName: function(args){//实例方法
return Newobj.showName(this.name + args );
}
}
var s = new Newobj("sss");
s.showName("bbb");//sssbbb
实例方法取于静态方法,换句话来说这是静态与实例方法共享设计,静态方法挂在jQuery构造器上,原型方法挂在哪里呢?
我们上节不是讲了内部会划分一个新的构造器init吗?jQuery通过new原型prototype上的init方法当作构造器,那么init的原型链方法就是实例的方法了,所以jQuery通过2个构造器划分2种不同的调用方式一种是静态,一种是原型。
方法是共享的,并且实例方法取于静态方法,2个构造器是完全隔离的 ,这个要如何处理?
看看jQuery给的方案:
画龙点睛的一处init.prototype = jQuery.fn
,把jQuery.prototype原型的引用赋给jQuery.fn.init.prototype的原型,这样就把2个构造器的原型给关联起来了。
ajQuery.fn = ajQuery.prototype = {
name: 'aaron',
init: function(selector) {
this.selector = selector;
return this;
},
constructor: ajQuery
}
ajQuery.fn.init.prototype = ajQuery.fn
这段代码就是整个结构设计的最核心的东西了,有这样的一个处理,整个结构就活了!不得不佩服作者的设计思路,别具匠心。
看看init的的构造图:
(单击图片查看大图)
通过原型传递解决问题,把jQuery的原型传递给jQuery.prototype.init.prototype。换句话说jQuery的原型对象覆盖了init构造器的原型对象,因为是引用传递所以不需要担心这个循环引用的性能问题。
var $$ = ajQuery = function(selector) {
//把原型上的init作为构造器
return new ajQuery.fn.init( selector );
}
ajQuery.fn = ajQuery.prototype = {
name: 'aaron',
init: function(selector) {
this.selector = selector;
return this;
},
constructor: ajQuery
}
ajQuery.fn.init.prototype = ajQuery.fn;
ajQuery.fn.foo = function () { alert("foo!"); };
ajQuery(".some-selector").foo();
//挂在ajQuery.fn上的实例方法变成了ajQuery(ajQuery.fn.init)上的原型方法
现在的ajQuery(".some-selector")
原型中有foo有init。 http://stackoverflow.com/questions/1755080/why-jquery-do-this-jquery-fn-init-prototype-jquery-fn
jQuery分离构造器的更多相关文章
- jQuery 源码分析 8: 回头看jQuery的构造器(jQuery.fn,jQury.prototype,jQuery.fn.init.prototype的分析)
在第一篇jQuery源码分析中,简单分析了jQuery对象的构造过程,里面提到了jQuery.fn.jQuery.prototype.jQuery.fn.init.prototype的关系. 从代码中 ...
- 【深入浅出jQuery】源码浅析2--奇技淫巧
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- 解密jQuery事件核心 - 委托设计(二)
第一篇 http://www.cnblogs.com/aaronjs/p/3444874.html 从上章就能得出几个信息: 事件信息都存储在数据缓存中 对于没有特殊事件特有监听方法和普通事件都用ad ...
- JQuery源码分析(五)
分离构造器 通过new 操作符构建一个对象,一般经过四部: A.创建一个新对象 B.将构造函数的作用域赋给新对象(所以this就指向了这个新对象) C.执行构造函数中的代码 D.返回这 ...
- 【深入浅出jQuery】源码浅析2--使用技巧
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- jquery 使用整理机制
短路表达式 与 多重短路表达式 短路表达式这个应该人所皆知了.在 jQuery 中,大量的使用了短路表达式与多重短路表达式. 短路表达式:作为"&&"和" ...
- jQuery源码浅析2–奇技淫巧
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- jQuery中对象的构建
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- jQuery源码解读----part 2
分离构造器 通过new操作符构建一个对象,一般经过四步: A.创建一个新对象 B.将构造函数的作用域赋给新对象(所以this就指向了这个新对象) C.执行构造函数中的代码 D.返回这个新对象 最后一点 ...
随机推荐
- ImageView的圆角半径
// 设置imageview的圆角半径 UIImageView *imageView = (UIImageView *)[cell viewWithTag:tag]; imageView.layer. ...
- 14、USB摄像头(V4L2接口)的图片采集
参考网站http://www.cnblogs.com/surpassal/archive/2012/12/19/zed_webcam_lab1.html 一.一些知识 1.V4L和V4L2. V4L是 ...
- HDoj-1163- Digital Roots
Problem Description The digital root of a positive integer is found by summing the digits of the int ...
- android 应用内部获取本应用或者相应包名的应用的SHA1签名的办法
我这个人比較懒.每次做的都是心血来潮,所以打算改掉这个坏毛病.昨晚非常晚才睡,躺在床上一直在回忆.这两年来,我以前的目标是什么,我放弃了什么,我完毕了什么. 结果目标非常多,也放弃了一些. 完毕的差点 ...
- 是男人就下100层【第四层】——Crazy贪吃蛇(3)
上一篇<是男人就下100层[第四层]--Crazy贪吃蛇(2)>实现了贪吃蛇绕着屏幕四周移动,这一篇我们来完成贪吃蛇的所有功能. 一.随机产生苹果 private void addAppl ...
- 我的嵌入式Qt开发第一课——基于BBB和hmc5843三轴电子罗盘
几次想照着课本系统地学习Qt,但我发现还是有详细问题驱动时学习比較快. 于是我给自己设定了这个任务: 读取HMC5843的三轴磁场强度值,计算出角度,并把角度用直观形式显示在图形界面上. 这里面涉及到 ...
- C# 使用 RabbitMQ
1. RabbitMQ MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接 ...
- 【t010】最近距离
Time Limit: 1 second Memory Limit: 32 MB [问题描述] 聚类方法要求将空间中的点集,按照一点的方式进行归类,要求每一类中的点集相互之间的距离足够的"近 ...
- 程序猿的还有一出路:大数据project师
非常多年前我非常郁闷地写了一篇博客<程序猿的出路在哪里?>,之所以郁闷.我记得是看了中国男足的比赛,不由自主对照自已苦逼的程序猿生涯,以前对中国软件的感情有如对中国男足,绝望到没有不论什么 ...
- 为什么 qt 成为 c++ 界面编程的第一选择?
为什么qt成为c++界面编程的第一选择 一.前言 为什么现在QT越来越成为界面编程的第一选择,笔者从事qt界面编程已经有接近8年,在这之前我做C++界面都是基于MFC,也做过5年左右.当时为什么会从M ...