javascript常用方法和技巧
浏览器变编辑器
data:text/html, <style type="text/css">#e{position:absolute;top:0;right:0;bottom:0;left:0;}</style><div id="e"></div><script src="http://d1n0x3qji82z53.cloudfront.net/src-min-noconflict/ace.js" type="text/javascript" charset="utf-8"></script><script>var e=ace.edit("e");e.setTheme("ace/theme/monokai");e.getSession().setMode("ace/mode/javascript");</script>
深度拷贝
function deepCopy(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === 'object') { c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c[i]); } else { c[i] = p[i]; } } return c; }
生成随机字符串
// 生成随机字符串 var strRandom = "qwertyuioplkjhgfdsazxcvbnm0123456789"; function getRamdomStr(){ var str = "", len = strRandom.length, index = Math.floor(len*Math.random()); str = strRandom.substring(index-1,index); return str; } function generateClassName(){ var arr = []; for(var i = 0; i< 12; i++){ arr.push(getRamdomStr()); } return arr.join(""); }
curry化函数
// 【通用curry化函数】 function curry(fn) { var slice = Array.prototype.slice, stored_args = slice.call(arguments, 1); return function () { var new_args = slice.call(arguments), args = stored_args.concat(new_args); return fn.apply(null, args); } } // 测试 function add(x, y) { return x + y; } // 将一个函数curry化获得一个新的函数 var newadd = curry(add, 5); console.log(newadd(4)); // 另一种选择--直接调用新函数 console.log(curry(add, 6)(7));
计数器
var setup = function () { var count = 0; return function () { return (count += 1); }; }; // 用法 var next = setup(); next();
获取地址参数
var getValueParam = function(key){ var url = window.location.href, para = url.split('?')[1], arrparam = [], val = undefined; if(para.length){ arrparam = para.split('&'); for( var i = 0; i<arrparam.length; i++ ){ if(arrparam[i].split("=")[0] == key){ val = arrparam[i].split("=")[1]; break; } } } return val; };
php数组赋值js变量
var data = <?php echo json_encode($data) ?>
弹出居中
function getValue ($target){ var h = $(document).scrollTop()+($(window).height()-$target.height())/2; var w = ($(window).width()-$target.width())/2 return { t : h, l : w } }
form表单Ajax提交
$('form').submit(function(e){ e.preventDefault(); var postData = $(this).serializeArray(); var formURL = $(this).attr("action"); $.ajax({ url : formURL, type: "POST", data : postData, dataType : "json", success:function(data, textStatus, jqXHR) { if(textStatus == 'success'){ console.log(data, textStatus, jqXHR); } //data: return data from server }, error: function(jqXHR, textStatus, errorThrown) { //if fails } }); });
腾讯视频嵌入代码
<iframe class="video_iframe" style=" z-index:1; " src="http://v.qq.com/iframe/player.html?vid=m0144ws2h0q&width=300&height=200&auto=0" allowfullscreen="" frameborder="0" height="200" width="300"></iframe>
网页代码编辑器
data:text/html, <style type="text/css">.e{position:absolute;top:0;right:0;bottom:0;left:0;}</style><div class="e" id="editor"></div><script src="http://d1n0x3qji82z53.cloudfront.net/src-min-noconflict/ace.js" type="text/javascript" charset="utf-8"></script><script>var e=ace.edit("editor");e.setTheme("ace/theme/monokai");e.getSession().setMode("ace/mode/javascript");</script>
【scp】 上端口大写P 为参数,2222 表示更改SSH端口后的端口,如果没有更改SSH端口可以不用添加该参数 获取文件: scp -P 2222 root@www.legcloud.com:/root/test.tar.gz /home/test.tar.gz 上传目录: scp -P 2222 -r /home/dirname/ root@www.legcloud.com:/root/dirname/
判断是否为数组的函数: isArray()
// 支付宝同学在用的
if (value instanceof Array ||
(!(value instanceof Object) &&
(Object.prototype.toString.call((value)) == '[object Array]') ||
typeof value.length == 'number' &&
typeof value.splice != 'undefined' &&
typeof value.propertyIsEnumerable != 'undefined' &&
!value.propertyIsEnumerable('splice'))) {
return 'array';
}
// 最直接的、简单的方式(在不同 iframe 中创建的 Array 并不共享 prototype)
var arr = [];
arr instanceof Array; // true
arr.constructor == Array; //true
// 基于iframe的情况 使用 Douglas Crockford 的方法是可以解决这个问题(《JavaScript 语言精粹》P61)
var is_array = function(value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
// 更简单的方法,也是jQuery 正在使用的。淘宝的 kissy 也是使用这种方式
var isArray = function(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
// 大而全而cool 判断类型
var is = function (obj,type) {
return (type === "Null" && obj === null) ||
(type === "Undefined" && obj === void 0 ) ||
(type === "Number" && isFinite(obj)) ||
Object.prototype.toString.call(obj).slice(8,-1) === type;
}
1、&&和if
// &&和 var a = 1; a == 1 && ( b = 0,console.log(b)) ; // 0 // 上面代码等同于 var a = 1; if( a == 1 ){ b = 0,console.log(b); } a == 1 && ( b = 0,console.log(b)) // 0 // 以下还会返回值 var a = 1; a != 1 && ( b = 0,console.log(b)) ; // false
2、判断IE
常规的判断已经阻挡不了NB的IE了,没有msie。。用它:
// IE11 !!navigator.userAgent.match(/Trident\/7\./) // 或者 Object.hasOwnProperty.call(window, "ActiveXObject") && !window.ActiveXObject
// IE6
var ie6 = !-[1,]&&!window.XMLHttpRequest;
// IE7
var ie7 = (navigator.appName == "Microsoft Internet Explorer" && navigator.appVersion.match(/7./i)=="7.")
3、移动端常用
// 移动端判断屏幕高度 document.documentElement.clientHeight // browser info and capability var _ua = window.navigator.userAgent; // isRetina window.devicePixelRatio && window.devicePixelRatio > 1 // isIDevice (/iphone|ipod|ipad/i).test(_ua) // isMobileChrome _ua.indexOf('Android') > -1 && (/Chrome\/[.0-9]*/).test(_ua) // isMobileIE _ua.indexOf('Windows Phone') > -1 // isMobileSafari isIDevice && _ua.indexOf('Safari') > -1 && _ua.indexOf('CriOS') < 0; // isTablet (isMobileSafari && _ua.indexOf('iPad') > -1) || (isMobileChrome && _ua.indexOf('Mobile') < 0);
Platform = {
list :[{"name":"iOS",
"value" : 1
},{"name":"Android",
"value" :2
},{"name":"weixin",
"value" :3
}],
getName : function(){
var name = this.getInfo().name;
return name;
},
getValue : function(){
var val = this.getInfo().value;
return val;
},
getInfo : function(){
var list = this.list,
regObj = this.judgeReg,
obj = {"name":"weixin","value":2};
for(var i=0;i<list.length; i++){
if(regObj[list[i]['name']]){
obj = list[i];
break;
}
}
return obj;
},
judgeReg : {
"iOS" : !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),
"Android" : navigator.userAgent.indexOf('Android') > -1 || navigator.userAgent.indexOf('Linux') > -1,
"weixin" : /MicroMessenger/.test(navigator.userAgent)
}
};
横竖屏函数判断 function orientationChange() { switch (window.orientation) { case 0: // Portrait case 180: // Upside-down Portrait // Javascript to setup Portrait view alert('Portrait'); break; case -90: // Landscape: turned 90 degrees counter-clockwise case 90: // Landscape: turned 90 degrees clockwise // Javascript to steup Landscape view alert('Landscape'); break; } } window.addEventListener(("onorientationchange" in window || "orientation" in window) ? "orientationchange" : "resize", orientationChange, false);
4、deffer
var Promise = function () { this.thens = []; }; Promise.prototype = { resolve: function () { var t = this.thens.shift(), n; t && (n = t.apply(null, arguments), n instanceof Promise && (n.thens = this.thens)); }, then: function (n) { return this.thens.push(n), this; } } function f1() { var promise = new Promise(); setTimeout(function () { alert(1); promise.resolve(); }, 5500) return promise; } function f2() { var promise = new Promise(); setTimeout(function () { alert(2); promise.resolve(); }, 1500) return promise; } function f3() { var promise = new Promise(); setTimeout(function () { alert(3); promise.resolve(); }, 1500) return promise; } function f4() { alert(4); } f1().then(f2).then(f3).then(f4);
5、更多常用方法
String.prototype.isMobile = function(){ var pattern = /^0{0,1}(13[0-9]|14[6|7]|15[0-3]|15[5-9]|18[0-9]|17[0-9])[0-9]{8}$/; return pattern.test( this ); } String.prototype.isEmail = function(){ var pattern = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/; return pattern.test( this ); } String.prototype.isUrl = function(){ var pattern = /([\w-]+\.)+[\w-]+.([^a-z])(\[\w-\.\?%&=]*)?|[a-zA-Z0-9\-\.][\w-]+.([^a-z])(\[\w-\.\?%&=]*)?/; return pattern.test( this ); } String.prototype.isChinese = function(){ var pattern = /^[\u4e00-\u9fa5]+$/; return pattern.test( this ); } String.prototype.isEnglish = function(){ var pattern = /^[a-zA-Z]+$/; return pattern.test( this ); } var BASE = { // html模板替换,用于html和数据相分离 // 模板中的变量用‘{}’包起来,‘{}’内的字符作为变量替换掉需要的内容 // 模板写法: var dom = '<li class="item {selected}" val="{value}">{text}</li>' // 【方法调用】:BASE.regReplace(dom,{selected:1,value:2,text:3}); // 输出结果:"<li class="item 1" val="2">3</li>" regReplace : function(str,data,reg){ if (!reg){ reg = /\{\w*\}/g; } return str.replace(reg,function(match,pos){ var s = ''; var command = match.substring(1,match.length-1); if (data[command]){ s = data[command]; } return s; }); }, // 在数组中查找元素,如果存在,返回所在下标,如果不存在,则返回-1 // 【方法调用】:BASE.isInArr(1,[2,3,1]); isInArr : function(item, arr){ if( arr.length > 0 ){ for( var i = 0; i < arr.length; i++ ){ if( arr[i] == item ){ return i; break; } } return -1; }else{ return -1; } }, // 在数组中删除指定元素,如果存在,返回删除后的数组,如果不存在,返回undefined // 【方法调用】:BASE.removeInArr(1,[2,3,1]); removeInArr : function(item, arr){ var index = this.isInArr(item, arr); if (index > -1) { arr.splice(index, 1); return arr; }else{ return undefined; } }, // 得到最大天数 getMaxDays : function(year, month){ var dt = new Date(year, month - 1, '01'); dt.setDate(1); dt.setMonth(dt.getMonth() + 1); cdt = new Date(dt.getTime()-1000*60*60*24); return cdt.getDate(); }, getCookie : function (a) { var b; b = a + "="; offset = document.cookie.indexOf(b); if (offset != -1) { offset += b.length; end = document.cookie.indexOf(";", offset); if (end == -1) { end = document.cookie.length; } return document.cookie.substring(offset, end); } else { return ""; } } };
6、图片尺寸
// 传统做法 var imgLoad = function (url, callback) { var img = new Image(); img.src = url; if (img.complete) { callback(img.width, img.height); } else { img.onload = function () { callback(img.width, img.height); img.onload = null; }; }; }; // 1、保证回调执行顺序:error > ready > load;2、回调函数this指向img本身 // 2、增加图片完全加载后的回调、提高性能 /** * 图片头数据加载就绪事件 - 更快获取图片尺寸 * @param {String} 图片路径 * @param {Function} 尺寸就绪 * @param {Function} 加载完毕 (可选) * @param {Function} 加载错误 (可选) * @example imgReady('http://x.autoimg.cn/www/common/images/logo.png', function () { alert('size ready: width=' + this.width + '; height=' + this.height); }); */ var imgReady = (function () { var list = [], intervalId = null, // 用来执行队列 tick = function () { var i = 0; for (; i < list.length; i++) { list[i].end ? list.splice(i--, 1) : list[i](); }; !list.length && stop(); }, // 停止所有定时器队列 stop = function () { clearInterval(intervalId); intervalId = null; }; return function (url, ready, load, error) { var onready, width, height, newWidth, newHeight, img = new Image(); img.src = url; // 如果图片被缓存,则直接返回缓存数据 if (img.complete) { ready.call(img); load && load.call(img); return; }; width = img.width; height = img.height; // 加载错误后的事件 img.onerror = function () { error && error.call(img); onready.end = true; img = img.onload = img.onerror = null; }; // 图片尺寸就绪 onready = function () { newWidth = img.width; newHeight = img.height; if (newWidth !== width || newHeight !== height || // 如果图片已经在其他地方加载可使用面积检测 newWidth * newHeight > 1024 ) { ready.call(img); onready.end = true; }; }; onready(); // 完全加载完毕的事件 img.onload = function () { // onload在定时器时间差范围内可能比onready快 // 这里进行检查并保证onready优先执行 !onready.end && onready(); load && load.call(img); // IE gif动画会循环执行onload,置空onload即可 img = img.onload = img.onerror = null; }; // 加入队列中定期执行 if (!onready.end) { list.push(onready); // 无论何时只允许出现一个定时器,减少浏览器性能损耗 if (intervalId === null) intervalId = setInterval(tick, 40); }; }; })(); 调用例子: imgReady('http://www.google.com.hk/intl/zh-CN/images/logo_cn.png', function () { alert('size ready: width=' + this.width + '; height=' + this.height); });
7、iframe跨域
function Messenger(win) { // save the pointer to the window which is interacting with this.win = win; this.init(); } // postMessage API is supported Messenger.prototype.init = function () { var self = this; var receiver = function (event) { // Some IE-component browsers fails if you compare // window objects with '===' or '!=='. if (event.source != self.win) return; (self.onmessage || function () {}).call(self, event.data); }; if (window.addEventListener) window.addEventListener('message', receiver, false); else if (window.attachEvent) window.attachEvent('onmessage', receiver); }; Messenger.prototype.send = function (data) { this.win.postMessage(data, '*'); }; Messenger.initInParent = function (frame) { return new this(frame.contentWindow); }; Messenger.initInIframe = function () { return new this(window.parent); }; // in IE, postMessage API is not supported if (!window.postMessage && window.attachEvent) { // redefine the init method Messenger.prototype.init = function () { var isSameOrigin = false; // test if the two document is same origin try { isSameOrigin = !!this.win.location.href; } catch (ex) {} if (isSameOrigin) { this.send = this.sendForSameOrigin; this.initForSameOrigin(); return; } // different origin case // init the message queue, which can guarantee the messages won't be lost this.queue = []; if (window.parent == this.win) { this.initForParent(); } else { this.initForFrame(); } }; Messenger.prototype.initForSameOrigin = function () { var self = this; document.attachEvent('ondataavailable', function (event) { if (!event.eventType || event.eventType !== 'message' || event.eventSource != self.win) return; (self.onmessage || function () {}).call(self, event.eventData); }); }; Messenger.prototype.sendForSameOrigin = function (data) { var self = this; setTimeout(function () { var event = self.win.document.createEventObject(); event.eventType = 'message'; event.eventSource = window; event.eventData = data; self.win.document.fireEvent('ondataavailable', event); }); }; // create two iframe in iframe page Messenger.prototype.initForParent = function () { var fragment = document.createDocumentFragment(); var style = 'width: 1px; height: 1px; position: absolute; left: -999px; top: -999px;'; var senderFrame = document.createElement('iframe'); senderFrame.style.cssText = style; fragment.appendChild(senderFrame); var receiverFrame = document.createElement('iframe'); receiverFrame.style.cssText = style; fragment.appendChild(receiverFrame); document.body.insertBefore(fragment, document.body.firstChild); this.senderWin = senderFrame.contentWindow; this.receiverWin = receiverFrame.contentWindow; this.startReceive(); }; // parent page wait the messenger iframe is ready Messenger.prototype.initForFrame = function () { this.senderWin = null; this.receiverWin = null; var self = this; this.timerId = setInterval(function () { self.waitForFrame(); }, 50); }; // parent page polling the messenger iframe // when all is ready, start trying to receive message Messenger.prototype.waitForFrame = function () { var senderWin; var receiverWin; try { senderWin = this.win[1]; receiverWin = this.win[0]; } catch (ex) {} if (!senderWin || !receiverWin) return; clearInterval(this.timerId); this.senderWin = senderWin; this.receiverWin = receiverWin; if (this.queue.length) this.flush(); this.startReceive(); }; // polling the messenger iframe's window.name Messenger.prototype.startReceive = function () { var self = this; this.timerId = setInterval(function () { self.tryReceive(); }, 50); }; Messenger.prototype.tryReceive = function () { try { // If we can access name, we have already got the data. this.receiverWin.name; return; } catch (ex) {} // if the name property can not be accessed, try to change the messenger iframe's location to 'about blank' this.receiverWin.location.replace('about:blank'); // We have to delay receiving to avoid access-denied error. var self = this; setTimeout(function () { self.receive(); }, 0); }; // recieve and parse the data, call the listener function Messenger.prototype.receive = function () { var rawData = null; try { rawData = this.receiverWin.name; } catch (ex) {} if (!rawData) return; this.receiverWin.name = ''; var self = this; var dataList = rawData.substring(1).split('|'); for (var i = 0; i < dataList.length; i++) (function () { var data = decodeURIComponent(dataList[i]); setTimeout(function () { (self.onmessage || function () {}).call(self, data); }, 0); })(); }; // send data via push the data into the message queue Messenger.prototype.send = function (data) { this.queue.push(data); if (!this.senderWin) return; this.flush(); }; Messenger.prototype.flush = function () { var dataList = []; for (var i = 0; i < this.queue.length; i++) dataList[i] = encodeURIComponent(this.queue[i]); var encodedData = '|' + dataList.join('|'); try { this.senderWin.name += encodedData; this.queue.length = 0; } catch (ex) { this.senderWin.location.replace('about:blank'); var self = this; setTimeout(function () { self.flush(); }, 0); } }; } // 父页面 var messenger = Messenger.initInParent(document.getElementById('iframe')); messenger.onmessage = function (data) { var newline = '\n'; var text = document.createTextNode(data + newline); document.getElementById('output').appendChild(text); }; function sendMessage() { var message = document.getElementById('message'); messenger.send(message.value); message.value = ''; } // 子页面 var messenger = Messenger.initInIframe(); messenger.onmessage = function (data) { var newline = '\n'; var text = document.createTextNode(data + newline); document.getElementById('output').appendChild(text); }; function sendMessage() { var message = document.getElementById('message'); messenger.send(message.value); message.value = ''; }
8、发布订阅模型
var PubSub = {handlers: {}} PubSub.on = function(eventType, handler) { if (!(eventType in this.handlers)) { this.handlers[eventType] = []; } this.handlers[eventType].push(handler); return this; } PubSub.emit = function(eventType) { var handlerArgs = Array.prototype.slice.call(arguments, 1); for (var i = 0; i < this.handlers[eventType].length; i++) { this.handlers[eventType][i].apply(this, handlerArgs); } return this; }
9、关于this作用域
// 兼容性更好的 bind if (!Function.prototype.bind) { Function.prototype.bind = function() { var __method = this; var args = Array.prototype.slice.call(arguments); var object = args.shift(); return function() { return __method.apply(object, args.concat(Array.prototype.slice.call(arguments))); } } }
// 最简单的 bind (ie9以上,不可取) Function.prototype.bind = function (scope) { var fn = this; return function () { return fn.apply(scope); }; } // 例子 var foo = { x: 3 } var bar = function(){ console.log(this.x); } bar(); // undefined var boundFunc = bar.bind(foo); boundFunc(); // 3 // 适用场景:事件绑定回调和setTimeout回调 // 1 事件绑定 var logger = { x: 0, updateCount: function(){ this.x++; console.log(this.x); } }
// 原始函数 document.querySelector('button').addEventListener('click', function(){ logger.updateCount(); }); // 改造后 document.querySelector('button').addEventListener('click', logger.updateCount.bind(logger)); // 2 setTimeout // 原始函数 render: function () { this.$el.html(this.template()); setTimeout(this.afterRender, 0); } // 改造后 render: function () { this.$el.html(this.template()); setTimeout(this.afterRender.bind(this), 0); }
// Tidier Event Binding With querySelectorAll Array.prototype.forEach.call(document.querySelectorAll('.klasses'), function(el){ el.addEventListener('click', someFunction); }); // 改造后 var unboundForEach = Array.prototype.forEach, forEach = Function.prototype.call.bind(unboundForEach); forEach(document.querySelectorAll('.klasses'), function (el) { el.addEventListener('click', someFunction); });
10、jquery多版本
<script type="text/javascript" src="/jquery.1.7.js"></script> var jQuery_1_7 = jQuery.noConflict(true); jQuery_1_7('.class').on(callback);
11、常用正则
匹配 UTF-8 中文:^[\x{4e00}-\x{9fa5}]+$ 匹配包含全角字符的 UTF-8 中文:^[\x{4e00}-\x{9fa5}A-Za-z0-9_]+$ 匹配 GB2312/GBK 中文:^[".chr(0xa1)."-".chr(0xff)."]+$ 匹配包含全角字符的 GB2312/GBK 中文:^[".chr(0xa1)."-".chr(0xff)."A-Za-z0-9_]+$ 匹配 HTML 标记:< (\S*?)[^>]*>.*?|< .*? /> 匹配邮件地址:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* 匹配网址 URL:[a-zA-z]+://[^\s]* 匹配加区号的国内电话号码:\d{3}-\d{8}|\d{4}-\d{7} 匹配 QQ 号:[1-9][0-9]{4,} 匹配邮政编码:[1-9]\d{5}(?!\d) 匹配身份证号码:\d{15}|\d{18} 匹配 ip 地址:\d+\.\d+\.\d+\.\d+
12、地址转义
var encodeRFC5987ValueChars = function (str) { return encodeURIComponent(str). // Note that although RFC3986 reserves "!", RFC5987 does not, // so we do not need to escape it replace(/['()]/g, escape). // i.e., %27 %28 %29 replace(/\*/g, '%2A'). // The following are not required for percent-encoding per RFC5987, // so we can allow for a little better readability over the wire: |`^ replace(/%(?:7C|60|5E)/g, unescape); };
//添加反斜杠
function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
}
13 安装压缩
npm install uglify-js -g