1. 写一个构造函数G,调用G 时,返回G上的fn 对象的init() 的实例
2.设置G.fn 的指向,使用G.fn 与G.prototype指向同一个对象
2.1 重写G.prototype 对象,修复constructor 的指向为G,确认调用init()时的要处理的内容:主要是获取元素,init()中有两个参数,分别是选择器selector 和 选择范围context,根据这两个参数查找到需要选择的元素
2.2 通过init 设置实例上属性的值
2.4 返回 这个实例
3.重写G.fn.init.prototype ,把这个原型对象指向G.fn ,即G.fn.init.prototype = G.fn ,这样G.fn.init() 的实例就可以调用G.fn 上的属性和方法了
4.在G上扩展函数extend,同时在G.fn上也扩展extend,把这两个扩展指向同一个函数,即G.extend = G.fn.extend = function(){}, 这样,调用了扩展函数也可以同时调用G 的原型对象上的属性和方法了;
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>Document</title> 8 <script> 9 // 创建一个构造函数,函数有两个参数,分别为选择器selector 和 选择范围, 10 // 当调用G函数时,返回G的fn对象上的init()的实例 11 var G = function(selector, context) { 12 return new G.fn.init(selector, context); 13 }; 14 // G的fn指向与G.prototype都指向一个匿名对象{} 15 16 G.fn = G.prototype = { 17 // 设置匿名对象的constructor的属性,使这个属性指向构造函数,修复原型对象的指向 18 constructor: G, 19 // 对象上有一个初始化函数,有两个参数selector,和context,分别代表选择器和选择范围; 20 // this 指向prototype,操作init(),设置proto上的属性, 21 init: function(selector, context) { 22 this.length = 0; // 设置this.length 属性为0 23 var context = context || document; // 当有范围时,选择范围,没有范围时,context就直接赋值为context 24 if (selector.indexOf("#") == 0) { // 当选择器中有#号时,说明是Id选择器, 25 this[0] = document.getElementById(selector.substring(1)); // 直接设置this[0] 为选中的Id元素 26 this.length = 1; // 同时设置this.length 属性为1,因为只有一个元素 27 } else { 28 var aNode = context.getElementsByTagName(selector); // 当选择器为元素选择器时,获取所有的元素 29 for (var i = 0, len = aNode.length; i < len; i++) { // 对所有的元素进行遍历 30 this[i] = aNode[i]; // 对应的元素赋值给this中对象的下标属性 31 }; 32 this.length = len; // 设置this.length 的属性为元素的个数 33 }; 34 this.selector = selector; //把元素的选择器也放到this的属性里 35 this.context = context; //把元素的范围也放到this的属性里 36 return this; // 返回this对象 37 }, 38 length: 0, // 原型对象上的属性,初始为0 39 size: function() { // 原型对象上的size() 函数 40 return this.length; 41 } 42 } 43 // 重写G.fn.init的原型对象,即G.fn.init.prototype 44 G.fn.init.prototype = G.fn; // 这里是为了确保 init()的实例可以调用G.prototype 原型对象上的属性和方法 45 // 把扩展的函数extend 挂载在G 上,同时也挂载在G.prototype上,这两个挂载指向同一个函数 ,这个函数返回dst; 46 // 当G的实例调用这个扩展函数时,就直接调用这个匿名函数了 47 G.extend = G.fn.extend = function() { 48 var i = 1, 49 len = arguments.length, 50 dst = arguments[0], 51 j; 52 if (i == len) { 53 dst = this; 54 i--; 55 }; 56 for (; i < len; i++) { 57 for (j in arguments[i]) { 58 dst[j] = arguments[i][j]; 59 } 60 } 61 return dst; 62 }; 63 window.onload = function() { 64 console.log(G("#box")); 65 G("#box")[0].style.background = "#789"; 66 G("ul")[1].style.color = 'red'; 67 console.log(G("ul")); 68 console.log(G("#box").extend({ 69 'name': 'huanying2015' 70 }, { 71 'sex': 'man' 72 }, { 73 'age': 25 74 }, { 75 'show': function() { 76 console.log("huanying2015"); 77 } 78 })); 79 } 80 </script> 81 </head> 82 <body> 83 <div class="box" id="box">huanying2015,这是一个测试</div> 84 <ul id="box2">huanying2015,这是另外一个测试</ul> 85 <ul id="box3">huanying2015,这是再一个测试</ul> 86 </body> 87 </html>
运行结果: