实用的Javascript代码锦集
实用的Javascript代码锦集
Date.parse("2016-04-4")
Date.parse
safari 不能使用单位数字的月份和日期,否则解析为NaN
火狐较低版本(火狐43)也是如此
+new Date('2017-06-08 21:00:00');
在IE11
上得出NaN Safari10
上也得出NaN Chrome 和 Firfox下OK
原因在于 IE 和 Safari 都不识别以-
分割的日期 需要写成 +new Date('2017/06/08 21:00:00');
, 这样才能在所有浏览器兼容.
IE10 has not anchorNode focusNode 属性, 取得选中的文字需要读取 text 属性, IE11 一切正常 , 取得选中文字可以直接 toString
IE10,IE11 不支持 html5 的 download 属性, 无法点击下载自定义名称的html和图片等文件. 可以使用 下载的 downloadFile,利用ajax下载,顺便说 ajax 下载也不能使用fetch IE系统统不支持fetch,到EDGE14才支持fetch, https://github.com/github/fetch 可支持IE10+
火狐不支持和chrome的scrollTop
表现也不相同
// 兼容处理 chrome 和 firefox
let scrollTop=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop;
if(scrollTop<20){
this.headerShowStatus=true;
}else if(scrollTop>170){
this.headerShowStatus=false;
}
if(document.documentElement.scrollHeight-scrollTop- document.documentElement.clientHeight< 400 ){
this.loadMore();
}
火狐不支持 e.srcElement
需要使用 e.target
代替
IE10,IE11, 不支持location.origin
var origin = location.origin?location.origin:location.protocol+"//"+location.host;
firefox 浏览器下载接受的后端header 不支持单引号
旧版firefox 不支持insertAdjacentElement
,直到火狐48才支持
https://gist.github.com/kafene/8e56adaf3c1ca4188938
if ("undefined" === typeof (Element.prototype.insertAdjacentElement)) {
Object.defineProperty(Element.prototype, "insertAdjacentElement", {
enumerable: false,
writable: true,
configurable: true,
value: function (position, elem) {
switch (position.toString().toUpperCase()) {
case "BEFOREBEGIN":
return this.parentNode.insertBefore(elem, this);
case "AFTERBEGIN":
return this.insertBefore(elem, this.firstChild);
case "BEFOREEND":
return this.appendChild(elem);
case "AFTEREND":
return this.parentNode.insertBefore(elem, this.nextSibling);
default:
throw new Error("Invalid element position `" + position + "`");
}
}
});
}
safari8 safari10 对于父元素是border-radius,overflow:hidden;
子元素可以被父元素相切,只显示父元素相切后的内容, 但是子元素如果使用了keyframe帧动画,则出现bug,相切的并不是border-radius后的结果.
IE
word-wrap: break-word;
文字换行, Chrome,Safari,Firefox 无论中英文,还是超长英文单词,都能够自动换行不溢出.
但是IE10,IE11对于超长单词仍然溢出,需要添加word-break: break-all;
chrome 31 or 搜狗5.0.9 (2014年)
chrome 31 内核 bug , supports 函数不能赋值给其他变量执行
var support = (window.CSS && window.CSS.supports) || window.supportsCSS || false;
if(support){
return support('-webkit-text-decoration-style','wavy')||support('text-decoration-style','wavy');
}
return false;
如上,会报TypeError:Illegal invocation
可修改为如下
if(window.CSS&&window.CSS.supports){
return window.CSS.supports('-webkit-text-decoration-style','wavy')||window.CSS.supports('text-decoration-style','wavy');
}else if(window.supportsCSS){
return window.supportsCSS('-webkit-text-decoration-style','wavy')||window.supportsCSS('text-decoration-style','wavy');
}else{
return false;
}
IE ajax get 缓存
IE 发送 GET 请求的缓存策略比较激进
当服务端没有设定相关缓存策略时,IE是默认缓存GET请求的。下次同地址的GET请求将会直接 200 from cache
在使用 axios 发送请求时,我们需要申明禁用缓存,表明请求该地址不使用本地缓存。
IE11 禁用ajx get 缓存
const headers = {
'X-Requested-With': 'XMLHttpRequest',
'Pragma': 'no-cache',
'Expires': 0
};
export const httpSys = axios.create({
baseURL:baseURLSys,
timeout: 60000,
withCredentials: true,
headers,
});
polyfill service
为兼容IE9,IE10,IE11等等众多浏览器,
我们需要在自己的代码工程里引入非常多的 polyfill,
但大部分 polyfill 对于新版的Chrome,Firefox 都是不必要的,但是也被打包到bundle里,造成bundle包很大
使用 polyfill service 我们可以免除对于polyfill的考虑,并且每个浏览器各自下载的内容不同,不需要的不会被下载。
并且基于CDN和缓存,各浏览器基本只需要下载一次。
并且会自动解决各种polyfill依赖问题,例如 https://cdn.polyfill.io/v2/polyfill.js?features=Element.prototype.closest|always
实测 EDGE16
不支持 Promise.prototype.finally
https://hospodarets.com/promise.prototype.finally#support
node >= 8.1.4 <10.0.0 可以通过 node -harmony-promise-finally
开启 Promise.prototype.finally
node >=10.0.0 默认支持 Promise.prototype.finally
https://cdn.polyfill.io/v2/polyfill.min.js?features=default,Promise.prototype.finally
https://babeljs.io/docs/usage/polyfill/
babel-polyfill
包含的core-js
也是一种方式
异步之中的下载文件
在异步中使用window.open是无法生效的
发现异次元的下载链接
使用 form.submit 向后端提交下载地址 (不要使用target _blank) ,后端302即可实现异步调用文件下载
还可以使用定时器设定打开任务,然后ajax回调后设定变量
window.opener
window.open
打开同源网站,目标站点可访问 window.opener, 且可操作其opener各种属性和方法
对应打开的非同源网站, 目标站点不能读取 opener的信息,如 location.href. 出现跨域问题,但是可以调用 window.opener.location.replace/assign 等 , 让原网站跳转指定url.
判断是否在某个div内
在jQuery中,我们可以直接使用closest
从此元素向上查找父元素,判断包含关系,
在原生JS中可以使用如下代码
function isParent(node, parent) {
while (node) {
if (node === parent) {
return true;
}
node = node.parentNode;
}
return false;
}
下面一个函数更加灵活,使用自定义函数判断是否查找到。
var closest = function(el, fn) {
return el && (fn(el) ? el : closest(el.parentNode, fn));
}
参考: http://clubmate.fi/jquerys-closest-function-and-pure-javascript-alternatives/
document.querySelector("#outer-3”).closest("#outer-1”)
if (window.Element && !Element.prototype.closest) {
Element.prototype.closest =
function(s) {
var matches = (this.document || this.ownerDocument).querySelectorAll(s),
i,
el = this;
do {
i = matches.length;
while (--i >= 0 && matches.item(i) !== el) {};
} while ((i < 0) && (el = el.parentElement));
return el;
};
}
参考: http://usefulangle.com/post/44/jquery-closest-function-in-pure-vanilla-javascript
MDN上也有Polyfill
https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
query builder
function buildQuery(params){
var esc = encodeURIComponent;
return Object.keys(params).map(k => esc(k) + '=' + esc(params[k])).join('&');
}
function buildQuery(params){
var esc = encodeURIComponent;
return Object.keys(params).map(function(k) {return esc(k) + '=' + esc(params[k]);}).join('&');
}
function query(o){
return Object.entries(o).reduce((arr, [k, v]) => arr.concat(encodeURIComponent(k) + '=' + encodeURIComponent(v)), []).join('&')
}
获取查询查询字符串get参数值
function getParam()
{
var data = decodeURIComponent(location.href).split("?")[1].split("&");
var param = {};
for(var i = 0; i<data .length; i++)
{
param[data [i].split("=")[0]] = data [i].split("=")[1];
}
return param;
}
类似于PHP中的$_GET
var $_GET = (function()
{
var url = decodeURIComponent(location.href);
var u = url.split( "?" );
if ( typeof (u[1]) == "string" )
{
u = u[1].split( "&" );
var get = {};
for ( var i in u)
{
var j = u[i].split( "=" );
get[j[0]] = j[1];
}
return get;
}
else
{
return {};
}
})();
给出要获取的参数,每次都会解析一遍
function getPar(par)
{
//获取当前URL
var local_url = decodeURIComponent(location.href);
//获取要取得的get参数位置
var get = local_url.indexOf(par + "=" );
if (get == -1)
{
return false ;
}
//截取字符串
var get_par = local_url.slice(par.length + get + 1);
//判断截取后的字符串是否还有其他get参数
var nextPar = get_par.indexOf( "&" );
if (nextPar != -1)
{
get_par = get_par.slice(0, nextPar);
}
return get_par;
}
QueryString
function QueryString(item)
{
var value = location.search.match(new RegExp('[\?\&]' + item + '=([^\&]*)(\&?)','i'));
return value ? value[1] : value;
}
Cookie操作
function setCookie(cookiename, cookievalue, hours)
{
var date = new Date();
date.setTime(date.getTime() + Number(hours) * 3600 * 1000);
document.cookie = cookiename + "=" + cookievalue + "; path=/;expires = " + date.toGMTString();
}
取得Cookie中某个键的值
$.getCookie = function(name)
{
if(document.cookie.indexOf(name)!=-1) return document.cookie.split(name+'=')[1].split(';')[0]
}
另一个
function getcookie(cookieid)
{
//获取cookie字符串
var strCookie=document.cookie;
//将多cookie切割为多个名/值对
var arrCookie=strCookie.split("; ");
var cookieval;
//遍历cookie数组,处理每个cookie对
for(var i=0;i<arrCookie.length;i++)
{
var arr=arrCookie[i].split("=");
//找到名称为userId的cookie,并返回它的值
if(cookieid==arr[0])
{
cookieval=arr[1];
break;
}
}
return(cookieval);
}
类似于 php 中 http_build_query
jQuery 中的 $.param
var params = {
parameter1: 'value_1',
parameter2: 'value 2',
parameter3: 'value&3'
};
var esc = encodeURIComponent;
var query = Object.keys(params).map(k => esc(k) + '=' + esc(params[k])).join('&');
进入全屏
function gofull()
{
var el=document.documentElement;
el.webkitRequestFullScreen&&el.webkitRequestFullScreen();
el.mozRequestFullScreen&&el.mozRequestFullScreen();
el.requestFullscreen&&el.requestFullscreen();
}
字符串去空格
String.prototype.trim=function() {return this.replace(/(^\s*)|(\s*$)/g,""); }
String.prototype.ltrim=function(){return this.replace(/(^\s*)/g,""); }
String.prototype.rtrim=function(){return this.replace(/(\s*$)/g,""); }
字节格式化
function size(size)
{
var name=['B','KB','MB','GB','TB','PB'];
var pos=0;
while(size>=1204)
{
size/=1024;
pos++;
}
return size.toFixed(2)+" "+name[pos];
}
判断页面滚动到底部和顶部
$(document).scroll(function()
{
if ($(document).scrollTop()<=0)
{
console.log("滚动条已经到达顶部为0");
}
if ($(document).scrollTop() >= $(document).height() - $(window).height())
{
console.log("滚动条已经到达底部为" + $(document).scrollTop());
}
});
滚动到顶部
$('html,body').animate({
scrollTop: '0px'
}, 800);
纯js滚动到顶部
window.scrollTo(0, 0);
或者
document.body.scrollTop = 0
document.documentElement.scrollTop = 0
平滑滚动
chrome 原生支持
window.scroll({top: 0, left: 0, behavior: 'smooth' });
用JS实现
linear
function scrollToTop(scrollDuration) {
var scrollStep = -window.scrollY / (scrollDuration / 15),
scrollInterval = setInterval(function(){
if ( window.scrollY != 0 ) {
window.scrollBy( 0, scrollStep );
}
else clearInterval(scrollInterval);
},15);
}
ease in and out
function scrollToTop(scrollDuration) {
const scrollHeight = window.scrollY,
scrollStep = Math.PI / ( scrollDuration / 15 ),
cosParameter = scrollHeight / 2;
var scrollCount = 0,
scrollMargin,
scrollInterval = setInterval( function() {
if ( window.scrollY != 0 ) {
scrollCount = scrollCount + 1;
scrollMargin = cosParameter - cosParameter * Math.cos( scrollCount * scrollStep );
window.scrollTo( 0, ( scrollHeight - scrollMargin ) );
}
else clearInterval(scrollInterval);
}, 15 );
}
https://stackoverflow.com/questions/21474678/scrolltop-animation-without-jquery
scroll-behavior: smooth;
也支持锚点跳转
https://stackoverflow.com/questions/17631417/css-pure-css-scroll-animation
运行JS代码
// execute code in the content page scope
var injectScript = function(source) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.textContent = ';(' + source.toString() + ')()';
document.body.appendChild(script);
document.body.removeChild(script)
}
添加CSS代码
// insert css
function injectStyle(css) {
var script = document.createElement('style')
script.setAttribute('type', 'text/css')
script.textContent = css
document.head.appendChild(script)
}
利用注释,可也生成html,css,js 等代码
如
(function(){/* body{background:#f00} */}).toString().slice(15,-4)
当然利用es6的字符串模板更加方便,http://babeljs.io/repl/ 在线转换为es5代码
一些正则验证
验证邮箱
function is_mail(str)
{
return(new RegExp(/^[0-9a-zA-Z]+@(([0-9a-zA-Z]+)[.])+[a-z]{2,4}$/i).test(str));
}
验证手机号
function is_tel(str)
{
return(new RegExp(/^1[34578][0-9]{9}$/).test(str));
}
Base64的1x1像素间隔gif
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
哪个个深拷贝最快
Object.assign
并不是深拷贝
一个range函数
function range(start, count)
{
return Array.apply(0, Array(count)).map(function (element, index)
{
return index + start;
});
}
简化console.log
var log = console.log.bind(console);
简化querySelector
srcQuery=srcQ.querySelector.bind(srcQ);
生成较短的唯一ID
一定年限内单线程非连续调用唯一
function shortId()
{
var time=Date.now()+'';
time=parseInt(time.substr(1));
return time.toString(36);
}
生成随机短ID,仅具备较低的不重复性
var t=Math.floor((1+Math.random())*0x1000000000).toString(16);
生成指定长度随机字符串
PHP代码
function code($nc, $a='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
{
$l=strlen($a)-1; $r='';
while($nc-->0) $r.=$a{mt_rand(0,$l)};
return $r;
}
给jQuery的form添加serializeObject
jQuery.prototype.serializeObject=function()
{
var a,o,h,i,e;
a=this.serializeArray();
o={};
h=o.hasOwnProperty;
for(i=0;i<a.length;i++)
{
e=a[i];
if(!h.call(o,e.name))
{
o[e.name]=e.value;
}
}
return o;
};
使用效果如下
jQuery("form").serialize(); //"username=&password="
jQuery("form").serializeArray(); //[{name:"username",value:""},{name:"password",value:""}]
jQuery("form").serializeObject(); //{username:"",password:""}
jQuery 返回顶部
$('html').animate({scrollTop: '0px'}, 800);
在 safari
中需要使用 $(‘body’)
因此使用下面代码更加兼容
$('html,body').animate({scrollTop: '0px'}, 800);
直接下载blob数据
function downFile(blob, fileName)
{
if (window.navigator.msSaveOrOpenBlob)
{
navigator.msSaveBlob(blob, fileName);
}
else
{
var link = document.createElement('a');
link.style.display='none';
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
document.body.appendChild(link);
link.click();
setTimeout(function()
{
document.body.removeChild(link);
window.URL.revokeObjectURL(link.href);
},200);
}
}
兼容IE,Chrome,Firefox,Safari,注意 appendChild 这一步不能缺,否则Firefox不兼容
var blob = new Blob([res.data], {type: "application/vnd.ms-excel"}),
fileName = '下载.xls';
downFile(blob, fileName);
fetch('/files/bin/http.xz').then(res=>res.blob()).then(res=>{console.log(res);downFile(res,"http.xz")})
iso 8 html5 canvas 限制
https://stackoverflow.com/questions/18565395/why-does-canvas-context-drawimage-fail-on-iphone
ios 的canvas 有像素限制,由于像素过大,实测拍出来的图片不能使用 canvasContext.drawImage
处理.
现象是canvas画出来的图片为空白,toBlob和toDataUrl也不能取到该canvas的数据.
解决方案
https://github.com/stomita/ios-imagefile-megapixel (未测试)
还有更加全面的方案
https://github.com/blueimp/javascript-load-image
加上 https://github.com/blueimp/JavaScript-Canvas-to-Blob
能更加方便的处理图片,实测可以解决拍出的图片过大无法处理的问题.
https://blueimp.github.io/JavaScript-Load-Image/ 提供在线检查Exif meta data
资源预取
function prefetch(url)
{
var link = document.createElement("link");
link.href = url;
link.rel="prefetch";
document.head.appendChild(link);
}
用Google Analytics
统计JS错误
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
window.addEventListener('error', function (err)
{
ga('create', 'UA-xxx-1', 'auto');
var lineAndColumnInfo = err.colno ? ' line:' + err.lineno +', column:'+ err.colno : ' line:' + err.lineno;
ga('send', 'event', 'JavaScript Error', err.message, location.href+' => '+err.filename + lineAndColumnInfo + ' -> ' + navigator.userAgent, 0, true );
});
UA-xxx-1
使用自己的统计ID
jQuery并发发送ajax
$.when($.get('assets/misc/1.json'), $.get('assets/misc/2.json')).then(function(r1, r2)
{
console.log(r1[0].message + " " + r2[0].message);
})
微信内JS获取地理位置
<script type="text/javascript" src="https://apis.map.qq.com/tools/geolocation/min?key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77&referer=mywxapp"></script>
获取精确定位信息
var options = {timeout: 9000};
geolocation.getLocation(showPosition, showErr, options);
粗糙定位信息
geolocation.getIpLocation(showPosition, showErr)
Fetch跨域带cookie
fetch(url, {credentials: 'include'})
jQuery ajax 跨域带 cookie
$.ajaxSetup({xhrFields: {withCredentials: true }});
google closure-compiler
编译好的jar下载
http://dl.google.com/closure-compiler/compiler-latest.zip
http://dl.google.com/closure-compiler/compiler-latest.tar.gz
解压后包含一个jar文件
或者 https://github.com/google/closure-compiler
下载源码与查看说明
https://developers.google.com/closure/compiler/docs/api-ref
使用
java -jar compiler.jar --js_output_file=out.js in1.js in2.js in3.js ...
# Recursively include all js files in subdirs
java -jar compiler.jar --js_output_file=out.js 'src/**.js'
java -jar closure-compiler-v20180402.jar --js_output_file 1.js --language_out NO_TRANSPILE -O WHITESPACE_ONLY --strict_mode_input false yarn-1.6.0.js