文档章节

javascript的瑞士军刀: ns.js

lnwazg
 lnwazg
发布于 2016/05/20 17:01
字数 2662
阅读 66
收藏 0

目前这套工具包已经稳定运行于生产环境半年,日均10W PV。

基于这套js,哪怕你是个菜鸟也可以很轻松愉快地加入到JS前端开发的世界啦!

废话不多说,上代码:

/**
 * @author  LiNan  
 * @company kidswant Co. Ltd.
 * @email   lnwazg@126.com
 * @version 2016-4-13 
 * @remark  需要依赖JQuery库
 * 我的JS命名空间的解释:
 * 简称	 	释义
 * NS		namespace的缩写,表示通用的命名空间。这里面放置的全部是工具类。当你不确定你的工具类方法应该放在什么地方的时候,你就可以将其放在这里。
 * 			其中,NS里面放置的是基础性的通用方法,便于在任何的业务代码中方便地调用。
 * 			而NS.webExt里面放置的是Web领域方向专用方法。其相比通用方法,更加领域化。
 * 			NS和NS.webExt之间的关系,好比JAVA SE与JAVA EE之间的关系。前者是基础,是基石,是赖以生存的根基。后者是前者的有力补充、重要扩充,是资料片。
 * 			好的设计模式,必然是经久不衰的!在实践的过程中,不断地提炼出结构化、模块化、可复用的、通用性强的代码,形成自己的个性代码库,从长远来看,都是超值的。
 * 
 * PB		pubSub,发布订阅设计模式的一个实现。利用此种模式,可以方便的为指定的对象绑定事件、触发事件。
 * 			
 */
//这里是我的专属命名空间
var NS = {
	browser:{
		versions : function() {
			var u = navigator.userAgent, app = navigator.appVersion;
			return { // 移动终端浏览器版本信息
				iOS : !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), 		// ios终端
				android : u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, 	// android终端或uc浏览器
				iPhone : u.indexOf('iPhone') > -1, 			// 是否为iPhone或者QQHD浏览器
				iPad : u.indexOf('iPad') > -1				// 是否iPad
			};
		}()},
	/**
	 * 写cookies
	 * name键
	 * value值
	 */	
	setCookie:function(name,value,expireDays){
		var Days = 36000;//(默认为永远不过期)写入之后有效期设置为100年,也就是相当于永不过期
		if(expireDays){
			//假如传了过期时间这个参数
			Days = expireDays;
		}
		var exp = new Date();    
		exp.setTime(exp.getTime() + Days*24*60*60*1000);
		document.cookie=(name + "="+ escape(value) + ";expires=" + exp.toGMTString()+";path=/" +(NS.cookieDomain? (";domain="+ NS.cookieDomain):"")); //设置cookie的键值对信息以及过期信息 (指定path真的很重要!) 
	},
	//写cookie。该cookie的生命周期为:session
	setCookieInSession:function(name,value){
		var isIE=!-[1,];//判断是否是ie核心浏览器  
		if(isIE){  
			document.cookie = (name + "="+ escape(value) + ";expires=At the end of the Session;path=/" +(NS.cookieDomain? (";domain="+ NS.cookieDomain):""));//设置cookie的键值对信息以及过期信息 (指定path真的很重要!) 
		}else{
			document.cookie = (name + "="+ escape(value) + ";expires=Session;path=/" +(NS.cookieDomain? (";domain="+ NS.cookieDomain):""));//设置cookie的键值对信息以及过期信息 (指定path真的很重要!) 
		}
	},
	//读取cookies
	getCookie:function(name){   
		var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");   
		if(arr=document.cookie.match(reg)){
			return unescape(arr[2]);
		}else{
			return null;   
		}
	},
	//删除cookies   
	delCookie:function(name){   
		var exp = new Date();   
		exp.setTime(exp.getTime() - 1);//将过期时间设置为上一毫秒   
		var cval=this.getCookie(name);   
		if(cval!=null){
			document.cookie= (name + "="+cval+";expires="+exp.toGMTString()+";path=/"+(NS.cookieDomain? (";domain="+ NS.cookieDomain):""));//若能取到这个cookie的键值对,那么就将其设置为过期    (指定path真的很重要!) 
		}
	},
	//删除cookies,未指定域名的
	delCookieWithoutDomain:function(name){
		var exp = new Date();   
		exp.setTime(exp.getTime() - 1);//将过期时间设置为上一毫秒   
		var cval=this.getCookie(name);   
		if(cval!=null){
			document.cookie= (name + "="+cval+";expires="+exp.toGMTString()+";path=/");//若能取到这个cookie的键值对,那么就将其设置为过期    (指定path真的很重要!) 
		}
	},
	//判断某个字符串是否为空
	isNull:function(obj){
		if(!obj || obj.length ==0){
			return true;
		}
		return false;
	},
	//判断是否为空
	isEmpty:function(obj){
		return this.isNull(obj);
	},
	/**
	 * 是否不为空
	 */
	isNotEmpty:function(obj){
		return !this.isNull(obj);
	},
	//某个数组中是否包含某个元素
	contains:function(element,array){
		if(this.indexOf(element,array)!=-1){
			return true;
		}
		return false;
	},
	//返回某个元素在数组中的位置
	indexOf:$.inArray,
	/**
	 * 删除数组中某个索引的数据
	 * @param idx
	 * @param array
	 * @returns
	 */
	removeIdx:function(idx, array){
		if(isNaN(idx)||idx>array.length){
			return false;
		}
		for(var i=0,n=0; i<array.length; i++){
			if(array[i]!=array[idx]){
				array[n++]=array[i];
			}
		}
		array.length-=1;//如果数组已经没元素了,再删除就会报错!
		return array;
	},	
	/**
	 * 判断某个字符串是不是以某个字符串开头
	 * 为何要写这个方法?因为令人无语的微信浏览器竟然不支持该方法啊!!!
	 * @param original  原有的字符串
	 * @param str    待搜索的字符串
	 * @returns {Boolean}
	 */
	startsWith:function(original,str){  
        if(str==null||str==""||original.length==0||str.length>original.length){
        	return false;  
        }  
		if(original.substr(0,str.length)==str){
			return true;  
		}else{
			return false;  
		}  
		return true;  
      },
      /**
       * 判断某个字符串是不是以某个字符串结尾
       * @param original
       * @param str
       * @returns {Boolean}
       */
	endWith:function(original,str){  
		if(str==null||str==""||original.length==0||str.length>original.length){
			return false;  
		}  
		if(original.substring(original.length-str.length)==str){
			return true;  
		}else{
			return false;  
		}  
		return true;  
	  },        
	//返回短名称
	shortName:function(str, maxLength){
		if(str && str.length>0){
			var len = str.length;
			if(len<=maxLength){
				return str;
			}else{
				return (str.substr(0,maxLength)+"...");
			}
		}else{
			return "";
		}
	},
	//检查是否是数字
	checkNumber:function(value){
		var reg = /^[1-9]\d*$/;
		if("0" == value || reg.test(value)){
			return true;
		}else{
			return false;
		}
	},
	//将指定map的指定的key初始化成空array
	initMapArray:function(){
		var len = arguments.length;//可变参数的方法
		if(len==0 || len ==1){
			return;
		}
		var map = arguments[0];
		for(var i=1;i<arguments.length;i++){
			var paramName = arguments[i];
			map[paramName]=[];
		}
	},
	//匿名
	anoym:function(name){
		if(!name || name.length ==0){
			return "***";
		}
		var length = name.length;
		if(length == 1){
			return (name +"***");
		}else{
			return (name[0]+"***"+name[name.length-1]); 
		}
	},
	/**
	 * 动态加载脚本
	 * 不推荐使用,因为这样加载的脚本会到最后才执行。如果该脚本被其他脚本依赖,则不推荐这样的方式
	 * @param script
	 */
    loadScript:function(url) {
        var content = '<script type="text/javascript" src="' + url + '"></script>';
        document.writeln(content);
    },
    /**
     * 动态加载样式
     * @param url
     */
    loadCss:function(url) {
        var content = '<link rel="stylesheet" type="text/css" href="'+url+'"/>';
        document.writeln(content);
    },
	//转换为用于显示用的字符串(去除undefined等等不合理的显示)
	toStr:function(obj){
		if(this.isNull(obj)){
			return "";
		}
		return obj;
	},
    //兼容方式获取滚动条距离顶部的距离
    getScrollTop:function(){
    	var scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
		return scrollTop;
    },
    //兼容方式设置滚动条距离顶部的距离
    setScrollTop:function(scroll_top) {
    	document.documentElement.scrollTop = scroll_top;
    	window.pageYOffset = scroll_top;
    	document.body.scrollTop = scroll_top;
    },
    /**
     * 获取两个日期的天数差(起始时间-结束时间) 
     */
    getDateDiffDays:function(startDate,endDate){  
        var startTime = new Date(Date.parse(startDate.replace(/-/g,"/"))).getTime();//得到毫秒数     
        var endTime = new Date(Date.parse(endDate.replace(/-/g,"/"))).getTime();     
        var dates = Math.abs((startTime - endTime))/(1000*60*60*24);//取绝对值     
        return dates;    
    },
	//防重复提交的事件注册表
	//用于检测某个事件是否已经在队列里先行一步了
	_timerReg:{},
	/**
	 * 防止快速点击所导致的重复提交
	 * @param id 标记,用于区分是否是同一种业务场景
	 * @param fn 回调函数
	 * @param wait 等待的毫秒数
	 * @returns
	 */
	preventDuplicateSubmission:function(id, fn, wait){
		if(!wait){
			wait=300;//默认延迟时间是300毫秒
		}
		if (NS._timerReg[id]) {
			console.log("检测到重复点击...");
	        window.clearTimeout(NS._timerReg[id]);
	        delete NS._timerReg[id];
	    }
	    return NS._timerReg[id] = window.setTimeout(function() {
	        fn();
	        delete NS._timerReg[id];
	    }, wait);
	},
	/**
	 * 将对象保存到localStorage
	 * @param key
	 * @param obj
	 */
	saveLocalStorageObj:function(key,obj){
		if(localStorage){
			localStorage[key] = JSON.stringify(obj);
		}
	},
	/**
	 * 从localStorage读取出对象
	 * @param key
	 */
	readLocalStorageObj:function(key){
		if(localStorage && localStorage[key]){
			if(NS.isNotEmpty(localStorage[key])){
				return JSON.parse(localStorage[key]);
			}
		}
		return null;
	},
	/**
	 * 指定的Url中,如果不存在某个参数,则添加该参数
	 */
	appendUrlParamIfNotExist:function(url,name,value){
		if(!this.urlHasParam(url,name)){
			//没有参数,则加上参数。有参数,则什么都不做
			url = this.urlAppendParam(url,name,value);
		}
		return url;
	},
	/**
	 * 给指定的url增加参数
	 * @param url
	 * @param name
	 * @param value
	 */
	urlAppendParam:function(url,name,value){
		url+=((url.indexOf("?")==-1?"?":"&")+name+"="+value);
		return url;
	},
	//某个url中,是否含有某个参数
	urlHasParam:function(url,name){
		var paramArray = this.getUrlParamArray(url);
		if(this.contains(name,paramArray)){
			return true;
		}else{
			return false;
		}
	},
	/**
	 * 获取指定URL的参数的数组
	 * 只要是在这个URL中出现过的参数,都可以算在里面
	 * @param url
	 * @returns {Object}
	 */
	getUrlParamArray:function(url) {
	   var retArray =[];
	   if (url.indexOf("?") != -1) {
	      var str = url.substr(url.indexOf("?")+1);
	      strs = str.split("&");
	      for(var i = 0; i < strs.length; i ++) {
//	         theRequest[strs[i].split("=")[0]]=(strs[i].split("=")[1]);
				retArray.push(strs[i].split("=")[0]);
	      }
	   }
	   return retArray;
	},
	/**
	 * 替换所有字符
	 * @param str 
	 * @param reallyDo 想要替换的
	 * @param replaceWith 替换成的
	 * @param ignoreCase 是否忽略大小写
	 * @returns
	 */
	replaceAll:function(str, reallyDo, replaceWith, ignoreCase) {  
	    if (!RegExp.prototype.isPrototypeOf(reallyDo)) {  
	        return str.replace(new RegExp(reallyDo, (ignoreCase ? "gi": "g")), replaceWith);  
	    } else {  
	        return str.replace(reallyDo, replaceWith);  
	    }  
	}
};

/**
 * @author LiNan 2016-4-13
 * 发布、订阅模式的工厂类<br>
 * 如果想用,请实例化,例如:var pubSub = new NS.PubSub();
 */
NS.PubSub = function(){
	//是否开启日志
	this.debugMode=true;
	/**
	 * 事件处理器列表
	 * 结构如下:
	 * 	click:[functionA, functionB, functionC, ...]
	 *  blur:[functionD, functionE, functionF, ...]
	 *  ...
	 */
	this.handlers={};
	/**
	 * 为某种事件名成绑定(追加)一个新的事件监听器<br>
	 * 例如,PubSub.on("click",function(){ doSth...})
	 */
	this.bind=this.on=function(eventType, handler) {
		if (!(eventType in this.handlers)) {
			// 若还从未绑定过此种事件类型,例如click事件
			this.handlers[eventType] = [];// 为该种类的事件类型初始化一个空的处理器数组
		}
		// 此时,this.handlers[eventType]可能是一个空数组,也可能是一个已经有了若干个处理器的数组了!
		this.handlers[eventType].push(handler);
		if (this.debugMode) {
			console.log("成功绑定" + eventType + "事件!");
		}
		// 返回this,便于后续的继续的链式调用
		return this;
	};
	/**
	 * 移除事件处理器
	 */
	this.clear = this.off = function(eventType, handler) {
		if(eventType){
			//对指定的事件类型进行移除
			if (handler) {
				// 如果传参了,那么只移除指定的handler
				this.handlers[eventType].pop(handler);
				if (this.debugMode) {
					console.log("成功解除指定参数类型的" + eventType + "事件!");
				}
			} else {
				// 移除所有的handler
				this.handlers[eventType] = [];
				if (this.debugMode) {
					console.log("成功解除所有的" + eventType + "事件!");
				}
			}
		}else{
			//移除所有的事件类型
			for(var et in this.handlers){
				 if (typeof(et)=="function"){
					 //是一个function,不可以删除 
				 }else if(typeof(et) =="string"){
					 //可以删除
					 delete this.handlers[et];
				 }
			}
		}
		return this;
	};
	/**
	 * 打印所有的事件列表
	 */
	this.show=this.view=function(eventType) {
		if(eventType){
			if(this.handlers[eventType]){
				console.log("当前绑定" + eventType + "类型的事件回调函数列表为:\n"+ this.handlers[eventType]);
			}
		}else{
			for(var p in this.handlers){
				 if (typeof(p)=="string"){
					 console.log("当前绑定" + p + "类型的事件回调函数列表为:\n"+ this.handlers[p]);
				 }
			}
		}
		return this;
	};
	/**
	 * 手工触发某个事件<br>
	 * 例如:PubSub.emit("click","param1","param2");<br>
	 * 那么,就会将PubSub对象上面绑定的所有的click事件函数依次触发(调用)一遍
	 */
	this.fire = this.trigger = this.emit=function(eventType) {
		// 从第一个参数往后截取所有的后续参数的数组,例如,此例中,就是["param1","param2"]
		var handlerArgs = Array.prototype.slice.call(arguments, 1);
		if(this.handlers[eventType] && this.handlers[eventType].length>0){
			for (var i = 0; i < this.handlers[eventType].length; i++) {
				// this.handlers[eventType][i]就是那个绑定的函数,调用该函数,并传入参数,即可
				this.handlers[eventType][i].apply(this, handlerArgs);
			}
		}else{
			if (this.debugMode) {
				console.log("未绑定任何 【"+ eventType+"】 事件!忽略调用!");
			}
		}
		// 返回this,便于后续的继续的链式调用
		return this;
	}
};

//一个开箱即用的发布订阅模式的实例,你可以立刻使用它!
var PB = new NS.PubSub();

 

想要上手使用很容易:

判断一个变量是否为空                                NS.isEmpty(param)

获取cookie名称为uid的值                            NS.getCookie("uid")

读取LocalStorage对象                                NS.readLocalStorageObj("aaa")

判断数组中是否含有某个元素                     NS.contains('a',['a','b'])

...

 

想要基于ns.js做扩展也很容易:

NS.webExt={
    showTip:window.showTip
}

//将新增的方法全部扩展至主方法中
$.extend(NS, NS.webExt);

这样,扩展的方法也可以直接通过 NS.showTip() 进行调用啦!

是不是很方便呀!

© 著作权归作者所有

lnwazg

lnwazg

粉丝 19
博文 8
码字总数 13103
作品 4
南京
程序员
私信 提问
加载中

评论(1)

西米小娅
西米小娅
52
Firebug 1.5.4 发布,网页开发者调试利器

Firebug是Firefox下的一款开发类插件,现属于Firefox的 五星级强力推荐插件之一。它集HTML查看和编辑、Javascript控制台、网络状况监视器于一体,是开发JavaScript、CSS、HTML和 Ajax的得力助...

红薯
2010/05/07
592
1
FireBug的网友评论

安装地址:https://addons.mozilla.org/firefox/addon/1843 Firebug是Firefox下的一款开发类插件,现属于Firefox的 五星级强力推荐插件之一。它集HTML查看和编辑、Javascript控制台、网络状况...

红薯
2009/12/11
152
1
Firebug 1.4.1 发布

Firebug是Firefox下的一款开发类插件,现属于Firefox的 五星级强力推荐插件之一。它集HTML查看和编辑、Javascript控制台、网络状况监视器于一体,是开发JavaScript、CSS、HTML和 Ajax的得力助...

红薯
2009/07/28
283
0
FireFox五星级插件 -- Firebug 1.4.0b1 发布

Firebug是Firefox下的一款开发类插件,现属于Firefox的 五星级强力推荐插件之一。它集HTML查看和编辑、Javascript控制台、网络状况监视器于一体,是开发JavaScript、CSS、HTML和 Ajax的得力助...

红薯
2009/06/04
585
0
Firebug 1.11.4 发布

Firebug 1.11.4 发布了,修复了 4 issues,兼容 Firefox 17-22 Firebug是Firefox下的一款开发类插件,现属于Firefox的 五星级强力推荐插件之一。它集HTML查看和编辑、Javascript控制台、网络...

oschina
2013/05/26
1K
6

没有更多内容

加载失败,请刷新页面

加载更多

正则表达式匹配

请实现一个函数用来匹配包括 '.' 和 '*' 的正则表达式。模式中的字符 '.' 表示任意一个字符,而 '*' 表示它前面的字符可以出现任意次(包含 0 次)。 在本题中,匹配是指字符串的所有字符匹配...

Garphy
45分钟前
5
0
Laravel 5.1的多路由文件的配置

默认的路由配置文件只有一个, \app\Http\routes.php。 在同一个文件中写路由容易起冲突,文件会越来越大,就需要定义多个路由文件。 找到加载\app\Http\routes.php的文件, 打开\app\Provid...

mdoo
今天
5
0
Hibernate 5 开始使用指南前言

同时在面向对象软件和关系型数据库进行工作,可能会非常复杂和费时。数据在对象和数据库之间可能会不一致,然后导致开发成本会非常高。 Hibernate 是一个针对 Java 环境的对象关系映射(Obj...

honeymoose
今天
5
0
聊聊nacos ServiceManager的UpdatedServiceProcessor

序 本文主要研究一下nacos ServiceManager的UpdatedServiceProcessor ServiceManager.init nacos-1.1.3/naming/src/main/java/com/alibaba/nacos/naming/core/ServiceManager.java @Compone......

go4it
今天
7
0
正则表达式的使用(QQ格式的判断与空格的切割)

//正则表达式的使用 public static void main(String[] args) throws IOException, ClassNotFoundException { //test1("123456"); test2("-1 99 kk"); } /** * ......

zhengzhixiang
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部