常用javascript代码片段集锦
常用方法的封装
根据类名获取DOM元素
1 var $$ = function (className, element) { 2 if (document.getElementsByClassName) { 3 return (element || document).getElementsByClassName(className); 4 } 5 var nodes = (element || document).getElementsByTagName('*'), 6 elements = [], 7 len = nodes.length, 8 i, 9 j, 10 currentNode, 11 classNames, 12 classLength; 13 for (i = 0; i < len; i++) { 14 currentNode = nodes[i]; 15 classNames = currentNode.className.split(' '); 16 classLength = classNames.length; 17 for (j = 0 ; j < classLength; j++) { 18 if (classNames[j] === className) { 19 elements.push(currentNode); 20 break; 21 } 22 } 23 } 24 return elements; 25 }
判断是否是数字
1 function isNum (numStr) { 2 3 // 方法一:正则 4 // return /^\d+$/g.test(numStr); 5 6 // 方法二:使用isNaN函数,可能存在潜在问题 7 return !isNaN(numStr); 8 }
从数组中删除指定下标的元素
声明一个临时数组,遍历原数组并判断是否等于给出的索引,如果相等则跳过本次循环;否则将其压入临时数组。
/**
* 从数组中删除指定下标的元素(返回的是新的数组并不影响原来的数组)
*/
1 function deleteElement (index,arr) { 2 3 var content = []; 4 for (var i = 0; i < arr.length; i++) { 5 if(index == i){ 6 continue; 7 } 8 content.push(arr[i]); 9 } 10 return content; 11 }
常用效果案例
标题栏跑马灯
1 // 标题栏实现跑马灯效果(可指定方向left,right) 2 var marqueeTitle = function(dir){ 3 4 var title = document.title; 5 6 var firstCh,leftChs,lastCh; // 第一个字符,剩下的字符和最后一个字符 7 8 if(dir == 'left'){ 9 firstCh = title.charAt(0); 10 leftChs = title.substring(1,title.length); 11 document.title = leftChs + firstCh; 12 } else if(dir == 'right'){ 13 lastCh = title.charAt(title.length - 1); 14 leftChs = title.substring(0,title.length - 1); 15 document.title = lastCh + leftChs; 16 } else { 17 console.error('跑马灯的方向只能是left和right'); 18 return; 19 } 20 // console.log('当前文字的移动方向' + dir + ',' + document.title); 21 } 22 23 window.onload = function(){ 24 // 标题栏跑马灯(注意带参的函数应该使用引号) 25 setInterval('marqueeTitle("right")',500); 26 }
走动的页面时钟
1 /** 2 * 当时钟数字不足2位数时补0 3 */ 4 function checkTime(i) { 5 return i < 10 ? '0' + i : i; 6 } 7 8 /** 9 * 走动的页面时钟 10 */ 11 function timeDate(){ 12 13 var now = new Date(), 14 15 year = now.getFullYear(), 16 month = now.getMonth() + 1, 17 day = now.getDate(), 18 h = checkTime(now.getHours()), 19 m = checkTime(now.getMinutes()), 20 s = checkTime(now.getSeconds()), 21 weekday = '星期' + '日一二三四五六'.charAt(now.getDay()); 22 23 getDOMById('time').innerHTML = year + "年" + month + "月" + day + "日 " + weekday + h + ":" + m + ":" + s; 24 25 setTimeout(timeDate,1000); 26 } 27 28 window.onload = function(){ 29 timeDate(); 30 }
抽签程序
1 <button id="select">抽签</button> 2 <script> 3 /** 4 * 从数组中删除指定下标的元素(返回的是新的数组并不影响原来的数组) 5 */ 6 function deleteElement (index,arr) { 7 8 var content = []; 9 for (var i = 0; i < arr.length; i++) { 10 if(index == i){ 11 continue; 12 } 13 content.push(arr[i]); 14 } 15 return content; 16 } 17 18 var data = [ 19 {"no":1,"name":'张三'}, 20 {"no":2,"name":'李四'}, 21 {"no":3,"name":'王五'}, 22 {"no":4,"name":'赵六'}, 23 {"no":5,"name":'孙七'} 24 ]; 25 26 console.info(data); 27 var tmp = data; 28 document.getElementById('select').onclick = function (){ 29 content = deleteElement(Math.floor(Math.random() * tmp.length),tmp); 30 tmp = content; 31 console.log(content); 32 33 }; 34 </script>
跳出$.each()
遍历使用return false
1 $.each(arr, function(index, val) { 2 console.log(index + '-->' + val); 3 if (index == 2) { 4 return false; // 只能是return false 5 }; 6 });
Excel列编号转化为数字
1 /** 2 * 将excel列转化为数字:A-->1,B-->2,AA-->27 3 */ 4 function convertColNumToInt(sHex) { 5 6 const START = 'A'.charCodeAt(0) - 1; 7 const RADIX = 26; 8 var ret = 0; 9 for(let i = 0;i < sHex.length;i++){ 10 ret *= RADIX; 11 ret += sHex.charCodeAt(i) - START; 12 } 13 return ret; 14 } 15 16 // 法2 17 /** 18 * 将excel列转化为数字:A-->1,B-->2,AA-->27 19 * 20 * hash表存放 21 * A => 1,B => 2,...Z => 26 22 */ 23 function convertColNumToInt(sHex) { 24 25 const RADIX = 26; 26 let m = new Map(); 27 for(let i = 1;i <= 26;i++){ 28 m.set(String.fromCodePoint(64+i),i); 29 } 30 31 let ret = 0; 32 for(let i = 0;i < sHex.length;i++){ 33 ret *= RADIX; 34 ret += m.get(sHex.charAt(i)); 35 } 36 return ret; 37 }
判断2个数组是否相似
具体需求如下:
-
数组中的成员类型相同,顺序可以不同。例如[1, true] 与 [false, 2]是相似的。
-
数组的长度一致。
-
类型的判断范围,需要区分:String, Boolean, Number, undefined, null, 函数,日期, window.
1 function arraysSimilar(arr1, arr2) { 2 3 if (!Array.isArray(arr1) || !Array.isArray(arr2) || arr1.length !== arr2.length) { 4 return false; 5 } 6 var t1 = [], 7 t2 = []; 8 // 依次取得2个数组中的元素类型并放入新的数组 9 for (var i = 0; i < arr1.length; i++) { 10 t1.push(typeOf(arr1[i])); 11 t2.push(typeOf(arr2[i])); 12 } 13 // 排序 14 t1.sort(); 15 t2.sort(); 16 // 比较排序后序列化的字符串 17 return t1.join() === t2.join(); 18 } 19 20 /** 21 * 得到元素的类型 22 * 23 * 单独判断null主要是兼容低版本IE 24 */ 25 function typeOf(element) { 26 return null === element ? "[object Null]" : Object.prototype.toString.call(element); 27 }
对象克隆
基本思路是逐个枚举属性,如果属性是对象,则进行递归处理。
1 Object.prototype.clone = function() { 2 var newObj = {}; 3 for(var i in this){ 4 if(typeof(this[i]) == 'object' || typeof(this[i] == 'function')){ 5 newObj[i] = this[i].clone(); 6 } else { 7 newObj[i] = this[i]; 8 } 9 } 10 return newObj; 11 } 12 13 Array.prototype.clone = function() { 14 var newArr = []; 15 if(typeof(this[i]) == 'object' || typeof(this[i]) == 'function'){ 16 newArr[i] = this[i].clone(); 17 } else { 18 newArr[i] = this[i]; 19 } 20 return newArr; 21 } 22 23 Function.prototype.clone = function() { 24 var _this = this; 25 var newFunc = function () { 26 return _this.apply(this, arguments); 27 }; 28 for(var i in this){ 29 newFunc[i] = this[i]; 30 } 31 return newFunc; 32 }
上面的代码在绝大多数情况下有效,但是当2个对象互相引用的时候就显得无力,会陷入死循环。必须使用图论算法建立拓扑关系,依次复制每个节点并重建依赖关系!
递归删除目录及文件
1 // rmdir -r 2 var rmdir = function(dir) { 3 var list = fs.readdirSync(dir); 4 for (var i = 0; i < list.length; i++) { 5 var filename = path.join(dir, list[i]); 6 var stat = fs.statSync(filename); 7 if (filename === "." || filename === "..") {} else if (stat.isDirectory()) { 8 rmdir(filename); 9 } else { 10 fs.unlinkSync(filename); 11 } 12 } 13 fs.rmdirSync(dir); 14 };
复制项目模板文件到指定目录
1 function copy(origin, target) { 2 if(!fs.existsSync(origin)) { 3 abort(origin + 'does not exist.'); 4 } 5 if(!fs.existsSync(target)) { 6 mkdir(target); 7 console.log(' create : '.green + target); 8 } 9 fs.readdir(origin, function(err, datalist) { 10 if(err) { 11 abort(FILEREAD_ERROR); 12 } 13 for(var i = 0; i < datalist.length; i++) { 14 var oCurrent = path.resolve(origin, datalist[i]); 15 var tCurrent = path.resolve(target, datalist[i]); 16 if(fs.statSync(oCurrent).isFile()) { 17 fs.writeFileSync(tCurrent, fs.readFileSync(oCurrent, ''), ''); 18 console.log(' create : '.green + tCurrent); 19 } else if(fs.statSync(oCurrent).isDirectory()) { 20 copy(oCurrent, tCurrent); 21 } 22 } 23 }); 24 }
以上的程序常用于项目的初始化,例如express init
默认生成了初始文件和项目。
判断节点是否包含另一个节点
1 function contains(refNode, otherNode){ 2 if (typeof refNode.contains == "function" && (!client.engine.webkit || client.engine.webkit >= 522)){ 3 return refNode.contains(otherNode); 4 } else if (typeof refNode.compareDocumentPosition == "function"){ 5 return !!(refNode.compareDocumentPosition(otherNode) & 16); 6 } else { 7 var node = otherNode.parentNode; 8 do { 9 if (node === refNode){ 10 return true; 11 } else { 12 node = node.parentNode; 13 } 14 } while (node !== null); 15 return false; 16 } 17 }
页面失去焦点触发标题栏切换
1 'use strict' 2 3 let originTitile = document.title 4 let timer; 5 document.addEventListener('visibilitychange', function () { 6 if (document.hidden) { 7 document.title = "(つェ⊂)赶快回来玩游戏啦" 8 clearTimeout(timer); 9 } else { 10 document.title = '(*´∇`*) 欢迎回来继续游戏 ' + originTitile 11 timer = setTimeout(function () { 12 document.title = OriginTitile 13 }, 3000) 14 } 15 })