在网上下了一个类似于jQuery的小框架,分析源码,看看怎么写框架。

选择器Select

  1. //用沙箱闭包其整个代码,只有itcast和I暴漏在全局作用域
  2. (function( window , undefined){
  3. //Itcast函数,参数:selector。返回值一个Itcast对象,功能:new Itcast。prototype。init()
  4. function Itcast(selector){
  5. return new Itcast.prototype.init();
  6. }
  7. // Itcast的原型属性用替换重新定义
  8. Itcast.prototype = {
  9. constructor: Itcast,
  10. type: "Itcast",
  11. length: 0,
  12. //constructor指向构造函数Itcast,type记录对象类型“Itcast”,length:变成伪数组
  13. // init函数 功能:Itcast对象的真正的构造函数,根据参数类型,进行不同的处理: 参数:selector。
  14. // 返回值:只要在适当的位置返回即可,构造函数不需要返回值,但是为了提醒这里是为了创建对象,所以写成return this
  15. //因为init是构造函数,this就是指创建出来的这个对象,现在要把获取到的dom对象全部追加到this中来,再通过Itcast返回
  16. // 。因为Itcast和init是用的同一个原型,所以认为此处创建出来的就是Itcast对象
  17. init:function(selector){
  18. var push = [].push;
  19. if( typeof selector == "string"){
  20. // 如果selector是html字符串,用parseHtml将其转成DOM伪数组,再转成this(Itcast伪数组)
  21. if( selector.charAt(0) == "<"){
  22. push.apply(this , parseHTML(selector));
  23. }else{
  24. // 如果selector是选择器。用Select函数,
  25. push.apply(this , Select(selector));
  26. }
  27.  
  28. }
  29. // 如果是function ,近似于onload
  30. if( typeof selector == "function"){
  31.  
  32. }
  33. // 如果是dom,追加到this(Itcast伪数组)中
  34. if( selector.nodeType ){
  35.  
  36. }
  37. // 如果是Itcast对象,追加到新的Itcast对象中返回
  38. if( selector.type = "Itcast" ){
  39.  
  40. }
  41. }
  42. }
  43.  
  44. //让init的原型属性指向Itcast。prototype。即有init创建出来的对象也就是Itcast对象了
  45. Itcast.prototype.init.prototype = Itcast.fn = Itcast.prototype;
  46. //设定Itcast的扩展方式,Itcast。extend(静态成员扩展) 。 Itcast.prototype.extend(动态成员扩展)
  47. // .函数参数: 对象option。 返回值: 无, 功能:将option中的属性或方法依次添加给Itcast或Itcast.fn
  48. Itcast.fn.extend = Itcast.extend = function(option){
  49. for( var k in option){
  50. this[ k ] = option[ k ];
  51. }
  52. }
  53. //模块化,功能化。(构造函数的补充)
  54. //扩充静态成员
  55. //选择器Select(闭包,仅将Select暴漏在外面)参数:无,返回值Select函数。
  56. // 功能:再沙箱中将Select函数定义好,
  57. var Select = (function(){
  58. //数据初始化:
  59. //将某些浏览器是否支持a方法用对象support储存起来以免每一次动用函数的时候都要进行查找
  60. // 是否提供可以看函数体是否包含 [native code]即可;,正则表达式的变量以r开头
  61. var rnative = /\[native code\]/,
  62. push = [].push ,
  63. i,
  64. div = document.createElement("div");
  65. var support = {
  66. qsa: rnative.test(document.querySelectorAll),
  67. getByClass : rnative.test( document.getElementsByClassName),
  68. getByClass2: rnative.test(div.getElementsByClassName),
  69. trim: rnative.test(String.prototype.trim),
  70. indexOf: rnative.test(Array.prototype.indexOf),
  71. }
  72. // 要用的函数提前准备好
  73. // push,push没有兼容性问题但是push.apply再IE低版本,不能展开伪数组,会报错
  74. // ,因此用try{}catch的方法兼容
  75. try{
  76. push.apply([],document.getElementsByTagName("*"));
  77. }catch(e){
  78. //z自定义push.apply的函数,参数数组a,伪数组b, 返回值 数组a,
  79. // 功能:将b中的内容添加到 a当中;
  80. var push = {
  81. apply : function( a , b){
  82. for( var i =0 ; i< b.length ; i++ ){
  83. a[ a.length++ ] = b[ i ];
  84. }
  85. return a;
  86. }
  87. }
  88. }
  89. //trim 参数:字符串 ,返回值:首位去除空白的I字符串。功能:将字符串的两端的空白去出,并返回
  90. function trim( str ){
  91. if( support.trim ){
  92. return str.trim();
  93. }else{
  94. var rtrim = /^\s+|\s+$/;
  95. return str.replace( rtrim , "");
  96. }
  97. }
  98. // indexOf,参数数组arr,a要查找项,返回值:a的索引值,如果没有返回-1
  99. //indexOf 还需要一个参数, 就是 查找的开始位置
  100. function indexOf( arr , a,startIndex){
  101. startIndex = startIndex || 0;
  102. if(support.indexOf){
  103. return arr.indexOf(a , startIndex);
  104. }
  105. for(var i = startIndex; i< arr.length ;i++){
  106. if( arr[ i ] === a){
  107. return i;
  108. }
  109. }
  110. return -1;
  111. }
  112. //unique函数,参数:数组 ,返回值:去重之后的数组,功能: 将穿进来的数组中的重复项去除
  113. function unique( arr ){
  114. var array = [];
  115. for( var i=0 ; i< arr.length ;i++){
  116. if(indexOf( array ,arr[ i ]) == -1){
  117. array.push( arr[i]);
  118. }
  119. }
  120. return array;
  121. }
  122. //核心函数Select:参数:selector选择器, 要被添加元素的数组或伪数组results, 返回值results
  123. //功能: 将selector对应的DOM对象,追加到results中输出
  124. function Select(selector ,results){
  125. results = results || [];
  126. if( typeof selector !== "string"){
  127. return ;
  128. }
  129. //如果浏览器支持querySelectorAll就用,如果不支持,就自己定义一个select2
  130. if( support.qsa ){
  131. return document.querySelectorAll( selector );
  132. }else {
  133. return select2( selector);
  134. }
  135. }
  136. // select2,参数:selector选择器,返回值dom对象,
  137. function select2( selector ,results){
  138. // 功能:看选择器是不是并集选择器,将selector用trim函数去掉首尾的空白()
  139. results = results || [];
  140. // ,再用split函数切割成数组,
  141. var arr = selector.split(",");
  142. for( i = 0 ; i < arr.length ; i++){
  143. // 再用select3函数进行处理,将切割好的字符串用trim方法取出前后空白
  144. select3( trim(arr[ i ]) , results);
  145. }
  146. return unique(results);
  147. }
  148. function select3 ( selector , results){
  149. results = results || [];
  150. //select3函数:参数select ,返回值dom对象。功能:判断选择器是“*”还是id,还是类,还是标签
  151. var first = selector.charAt(0);
  152. //注意如果是类选择器,document.getElementsByClassName有浏览器兼容性问题。
  153. //区分好后,调用相应的函数进行处理
  154. //此处屏蔽掉后代选择器的影响,此时如果selector经过了首尾去空格后还有空格,说明是后代选择器
  155. if( selector.slice(" ").length == 1){
  156. if(selector == "*"){
  157. /*
  158. results = document.getElementsByTagName("*");
  159. return results;
  160. ,如果results原来就有内容,此处把results中的内容全部覆盖了所以不行,
  161. 要将选择器对应的dom元素挨个追加到results中
  162. */
  163. }else if( first == "#"){
  164. return id(selector.slice(1) , results);
  165. }else if( first == "."){
  166. //类
  167. return c(selector.slice(1),results);
  168. }else {
  169. //标签
  170. return t(selector , results)
  171. }
  172. }else{
  173. //如果是后代选择器,此处咱不处理,抛出一个bug,提示升级浏览器
  174. throw new Error("您的浏览器版本过低,请升级浏览器")
  175. }
  176. }
  177.  
  178. //参数:选择器selector 被追加元素的数组。 返回值: results
  179. //功能: 将selector对应的元素挨个追加到results中并输出,
  180. function id( selector ,results ){
  181. results = results || [];
  182. push.apply(results , document.getElementById(selector));
  183. return results;
  184. }
  185. // 标签
  186. function t( selector , results){
  187. results = results || [];
  188. push.apply( results , document.getElementsByTagName( selector));
  189. return results;
  190. }
  191. //类,getElementsByClassName有浏览器兼容行问题,
  192. function c( selector , results ){
  193. results = results || [];
  194. push.apply( results , getByClass( selector , document));
  195. return results;
  196. }
  197.  
  198. //兼容类选择器,参数:类名className ,查找返回node,返回值:返回查找到的dom元素数组
  199. //功能: 用className属性查找node中的符合条件的dom对象,并返回对象数组
  200. function getByClass(className , node){
  201. node = node || document;
  202. //如果浏览器支持
  203. if( node == document && support.getByClass || node.nodeType && support.getByClass2){
  204. return node.getElementsByClassName(className);
  205. }else{
  206. //如果浏览器不支持
  207. //获取所有的标签,遍历
  208. var list = node.getElementsByTagName("*"),
  209. arr = [],
  210. tempClassName;
  211. for( var i = 0 ; i< list.length ;i++){
  212. tempClassName = list[ i ];
  213. if( !tempClassName ){
  214. continue;
  215. } //再class属性存在的情况下
  216. //用slice(“ ”)分割
  217. //判断是否与className相同
  218. //如果相同追加到results中
  219. if(indexOf(tempClassName.slice(" "),className) !== -1){
  220. arr.push(tempClassName);
  221. }
  222. }
  223. return arr;
  224.  
  225. }
  226.  
  227. }
  228.  
  229. return Select;
  230. })();
  231.  
  232. // 解析html字符串parseHTML
  233. //在解析过程中,需要在内存中创建一个node,为了不暴漏在外面使用沙箱(自调自用的函数,返回该数组)
  234. //参数:selector,(html字符串),返回值存储dom的数组,功能: 将html字符串转化成dom对象储存在数组中
  235. Itcast.parseHTML =(function (){
  236. var node = document.createElement("div");
  237. var arr = [];
  238. function parseHTML(selector){
  239. node.innerHTML = selector;
  240. arr.push.apply(arr , node.childNodes);
  241. return arr;
  242. }
  243. return parseHTML;
  244. })();
  245.  
  246. //扩充实例成员
  247. Itcast.fn.extend({
  248. appendTo: function ( parent , child ){
  249. parent.appendChild( child );
  250. }
  251. })
  252.  
  253. //将Itcast挂在window上
  254. window.Itcast = window.I = Itcast;
  255. })(window);

  

分析一个类似于jquery的小框架的更多相关文章

  1. 分析一个类似于jquery的小框架 (2)

    核心构造函数 (function ( window, undefined ) { // 定义Itcast构造函数 function Itcast ( selector ) { return new I ...

  2. 【JavaScript框架封装】实现一个类似于JQuery的基础框架、事件框架、CSS框架、属性框架、内容框架、动画框架整体架构的搭建

    /* * @Author: 我爱科技论坛 * @Time: 20180715 * @Desc: 实现一个类似于JQuery功能的框架 * V 1.0: 实现了基础框架.事件框架.CSS框架.属性框架. ...

  3. 【JavaScript框架封装】实现一个类似于JQuery的DOM框架的封装

    // DOM框架(选择器框架) (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({ /** * 向现 ...

  4. 【JavaScript框架封装】实现一个类似于JQuery的缓存框架的封装

    // 缓存框架 (function (xframe) { /** * 实现了缓存框架的临时存储功能(内存存储) * @type {{data: Array, get: (function(*): *) ...

  5. 【JavaScript框架封装】实现一个类似于JQuery的动画框架的封装

    // 动画框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({}); // 不需要参与链式访问的 ...

  6. 【JavaScript框架封装】实现一个类似于JQuery的属性框架的封装

    // 属性框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({ /** * 获取/设置某一个元素 ...

  7. 【JavaScript框架封装】实现一个类似于JQuery的选择框架的封装

    // 选择框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({}); // 不需要参与链式访问的 ...

  8. 【JavaScript框架封装】实现一个类似于JQuery的事件框架的封装

    // 事件框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({ /** * 实现一个浏览器的基本 ...

  9. 【JavaScript框架封装】实现一个类似于JQuery的内容框架的封装

    // 内容框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({ /** * .html()用为读 ...

随机推荐

  1. symfony2取得web目录绝对路径、相对路径、网址的函数是什么

    对于你的需求,Symfony2通过DIC提供了kernel服务,以及request(请求)的封装. 在controller里(在其他地方你可以自行注入kernel,这个服务是HttpKernel库里的 ...

  2. putty远程连接ubuntu

      步骤一.在ubuntu系统中安装ssh,可使用如下的命令进行安装: sudo apt-get install openssh-server步骤二.为了保险起见,安装完成后重启一下ssh服务,命令如 ...

  3. oracle中的日期:周月季年,首天未天。

    SQL> SQL 前一小时数 FROM dual; 现在时间 当前小时数 前一小时数 ------------------- ---------- ---------- :: SQL> S ...

  4. Windows 查看端口占用和关闭进程

    支持原创地址 :http://www.cnblogs.com/moodlxs/p/4145384.html 开始--运行--cmd 进入命令提示符 输入netstat -ano 即可看到所有连接的PI ...

  5. 将yyyyMMdd,dd/MM/yyyy 类型字符串转换为datetime 类型 yyyy-MM-dd C#

    DateTime ConvertDate = DateTime.ParseExact(", "yyyyMMdd", null, System.Globalization. ...

  6. 无索引状态下比较DataTable的几种过滤方法效率

    先构造一个DataTable: public DataTable GetDataTable() { DataTable dtTmp = new DataTable(); dtTmp.Columns.A ...

  7. ios启动载入启动图片

    版本判断: 1.首先你要知道这个键值对的key:id key =   (id)kCFBundleVersionKey; 2.同过本地的NSBundle取得当前的版本号. 3.在沙盒中取得对应的版本号. ...

  8. 重构MVC多条件+分页解决方案

    为支持MVC的验证,无刷新查询,EF,以及让代码可读性更强一点,所以就重构了下原来的解决方案. 这里就简单讲下使用方法吧: Model: 继承PagerBase: 1 public class Sea ...

  9. MyEclipse中代码格式化后自动换行

    MyEclipse的默认设置里面各种坑人,怎么不方便怎么设置,用户体验差到极点.今天又遇到个问题,按下Ctrl + Shift + F 后,自动格式化后的代码原来只有一行,结果变成了3行,看着都想吐. ...

  10. selenium 关于富文本的处理

    http://www.cnblogs.com/xiaobaichuangtianxia/p/5889999.html