前期准备
解决这个问题是通过匿名函数,然后在匿名函数内创建对象,将window
作为参数传入匿名函数,并将此对象赋值与window
1 2 3 4 5 6 7 8 9 10
| (function (global) { if (!global) { console.error("当前环境不是浏览器环境!"); return false; } var mytool = new Object(); global.mytool = mytool; })(window);
|
此时在全局作用域中便存在了一个对象mytool
。
选择器
实现一个选择器,用于替代getElementById
、getElementsByClassName
、getElementsByTagName
三种获取方式。
实现方式,将需要搜索的标签名(id,class,tagname)传入方法参数,通过内部处理返回一个数组。
- 对于
id
选择器或class
选择器来说,传入形参为#id
或.class
。那么只需要去匹配第一个字符即可。 - 如果不匹配以上两种情况,那么可以视为
TagName
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| mytool.getElement = function (selector) { if (selector !== "" && selector !== undefined && selector !== null) { var firstSelector = selector.slice(0, 1); var lastSelector = selector.slice(1); var result, arr = []; if (firstSelector === "#") { result = document.getElementById(lastSelector); } else if (firstSelector === ".") { result = document.getElementsByClassName(lastSelector); } else { result = document.getElementsByTagName(selector); } if (result.length) { for (var i = 0; i < result.length; i++) { arr.push(result[i]); } } else { arr.push(result); } return arr; } };
|
选择器的改造
定义开放给全局作用域的变量,其具有两重身份
实现一个类数组对象只需要将某个构造函数的原型指向一个数组即可。例如:
1 2 3 4 5 6 7 8 9 10 11
| function createObject() { this.name = "李雷"; this.sayMe = function () {}; }
createObject.prototype = new Array();
var newObj = new createObject();
newObj.push("xxx"); console.log(newObj);
|
在函数内部创建核心对象,操作在核心对象上,最后返回这个对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| var _mytool = function (selector) { var _tool = new createMyTool();
if (selector !== "" && selector !== undefined && selector !== null) { var firstSelector = selector.slice(0, 1); var result; if (firstSelector === "#") { result = document.getElementById(selector.slice(1)); } else if (firstSelector === ".") { result = document.getElementsByClassName(selector.slice(1)); } else { result = document.getElementsByTagName(selector); }
if (result.length) { for (var i = 0; i < result.length; i++) { _tool.push(result[i]); } } else { _tool.push(result); } } return _tool; };
|
NOTE
在函数内部定义局部变量、内部函数或对象时, 命名格式经常使用"_"作为前缀
目的主要为了与真正在全局作用域中定义变量、对象或函数进行区分
在实际开发, 经常会使用一个符号替代对象名. 比如后面要学习的jQuery库, 使用"$"替代对象
选择器的再次改造
首先是需要判断当前的运行环境
改造的思路为,判断当前环境是否存在document
,如果存在则为浏览器环境,如果不存在为其他环境。当浏览器环境时,去运行一个回调函数。
1 2 3 4 5 6 7 8
| (function (global, factory) { if (global.document) { factory(global); } else { } })(window !== undefined ? window : this, function (window) {})
|
于是匿名函数的结构就变成了如上结构。
传入的windows
形参是为了增加功能时直接使用的全局对象。
开放给全局的对象
回调函数需要明确的是:还是需要返回一个类数组对象,并且需要开放给全局一个对象来使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| (function (global, factory) { if (global.document) { factory(global); } else { } })(window !== undefined ? window : this, function (window) { MyTool.init = function () {}; MyTool.init.prototype = new Array(); window.MyTool = window.$ = MyTool; })
|
定义MyTool基本模型
1 2 3 4 5 6 7 8 9 10
| var MyTool = function (selector) { var _mytool = new MyTool.init(); if (selector === undefined || selector === null || selector === "") { return _mytool; } return _mytool; };
|
完成选择器的功能
字符串可以使用索引值的方式去取到第一个字符,因此可以替换掉slice
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| var MyTool = function (selector) { var _mytool = new MyTool.init(); if (selector === undefined || selector === null || selector === "") { return _mytool; } else if (selector[0] === "#") { result = _document.getElementById(selector.slice(1)); } else if (selector[0] === ".") { result = _document.getElementsByClassName(selector.slice(1)); } else { result = _document.getElementsByTagName(selector); }
if (result.length) { for (var i = 0; i < result.length; i++) { _mytool.push(result[i]); } } else { _mytool.push(result); } return _mytool; };
|
扩展创建标签的功能
扩展标签所需要判断的是开头为<
,并且最后一个字符为>
,且长度大于等于3。那么即可视为创建标签元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| else if ( selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3 ) {
var firstRightArrowIndex = selector.indexOf(">"); var startTag = selector.slice(0, firstRightArrowIndex + 1); var firstSpaceIndex = startTag.indexOf(" "); var tagName, textValue;
if (firstSpaceIndex !== -1) { tagName = selector.slice(1, firstSpaceIndex); } else { tagName = selector.slice(1, firstRightArrowIndex); } var newElement = _document.createElement(tagName);
if (selector.match(/[<]/g).length === 2) { var lastLeftArrowIndex = selector.lastIndexOf("<"); textValue = selector.slice( firstRightArrowIndex + 1, lastLeftArrowIndex );
newElement.textContext = textValue; }
if (firstSpaceIndex !== -1) { var attrArr = startTag.slice(0, firstRightArrowIndex).split(" "); for (var i = 1; i < attrArr.length; i++) { var attrText = attrArr[i]; var attrName = attrText.split("=")[0]; var attrValue = attrText.split("=")[1]; attrValue = attrValue.slice(1, attrValue.length - 1);
newElement.setAttribute(attrName, attrValue); } }
result = newElement; }
|
开发历程及代码
时间 | 开发内容 |
---|
2020-06-07 | 选择器的再次改造、扩展创建标签的功能 |
2020-06-06 | 选择器的改造 |
2020-06-03 | 前期准备、选择器 |
代码仓库:mytools
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| (function (global, factory) {
if (global.document) { factory(global); } else { }
})(window !== undefined ? window : this, function (window) { var _document = window.document; var MyTool = function (selector) { var _mytool = new MyTool.init(), result; if (selector === undefined || selector === null || selector === "") { return _mytool; } else if ( selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3 ) {
var firstRightArrowIndex = selector.indexOf(">"); var startTag = selector.slice(0, firstRightArrowIndex + 1); var firstSpaceIndex = startTag.indexOf(" "); var tagName, textValue;
if (firstSpaceIndex !== -1) { tagName = selector.slice(1, firstSpaceIndex); } else { tagName = selector.slice(1, firstRightArrowIndex); } var newElement = _document.createElement(tagName);
if (selector.match(/[<]/g).length === 2) { var lastLeftArrowIndex = selector.lastIndexOf("<"); textValue = selector.slice( firstRightArrowIndex + 1, lastLeftArrowIndex );
newElement.textContext = textValue; }
if (firstSpaceIndex !== -1) { var attrArr = startTag.slice(0, firstRightArrowIndex).split(" "); for (var i = 1; i < attrArr.length; i++) { var attrText = attrArr[i]; var attrName = attrText.split("=")[0]; var attrValue = attrText.split("=")[1]; attrValue = attrValue.slice(1, attrValue.length - 1);
newElement.setAttribute(attrName, attrValue); } }
result = newElement; } else if (selector[0] === "#") { result = _document.getElementById(selector.slice(1)); } else if (selector[0] === ".") { result = _document.getElementsByClassName(selector.slice(1)); } else { result = _document.getElementsByTagName(selector); }
if (result.length) { for (var i = 0; i < result.length; i++) { _mytool.push(result[i]); } } else { _mytool.push(result); }
return _mytool; }; MyTool.init = function () {}; MyTool.init.prototype = new Array(); window.MyTool = window.$ = MyTool; });
|