常用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 >抽签</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 })