1、一般常用工具函数
1.获取变量的数据类型(jQuery源码)
function getType (obj) { var class2type = {}; if (obj == null) { return obj + ""; } return typeof obj === "object" || typeof obj === "function" ? class2type[toString.call(obj)] || "object" : typeof obj;}
2.对象转 query string 参数(jQuery代码)
function objectToQueryString(a, traditional) { var getType = function (obj) { var class2type = {}; if (obj == null) { return obj + ""; } return typeof obj === "object" || typeof obj === "function" ? class2type[toString.call(obj)] || "object" : typeof obj; } var isPlainObject = function (obj) { var proto, Ctor; // Detect obvious negatives // Use toString instead of jQuery.type to catch host objects if (!obj || toString.call(obj) !== "[object Object]") { return false; } proto = Object.getPrototypeOf(obj); // Objects with no prototype (e.g., `Object.create( null )`) are plain if (!proto) { return true; } // Objects with prototype are plain iff they were constructed by a global Object function Ctor = ({}).hasOwnProperty.call(proto, "constructor") && proto.constructor; return typeof Ctor === "function" && ({}).toString.call(Ctor) === ({}).toString.call(Object); }; var rbracket = /\[\]$/; var isFunction = function isFunction(obj) { return typeof obj === "function" && typeof obj.nodeType !== "number"; }; var isWindow = function isWindow(obj) { return obj != null && obj === obj.window; }; var isArrayLike = function (obj) { var length = !!obj && "length" in obj && obj.length, type = getType(obj); if (isFunction(obj) || isWindow(obj)) { return false; } return type === "array" || length === 0 || typeof length === "number" && length > 0 && (length - 1) in obj; } var each = function (obj, callback) { var length, i = 0; if (isArrayLike(obj)) { length = obj.length; for (; i < length; i++) { if (callback.call(obj[i], i, obj[i]) === false) { break; } } } else { for (i in obj) { if (callback.call(obj[i], i, obj[i]) === false) { break; } } } return obj; } var buildParams = function (prefix, obj, traditional, add) { var name; if (Array.isArray(obj)) { // Serialize array item. each(obj, function (i, v) { if (traditional || rbracket.test(prefix)) { // Treat each array item as a scalar. add(prefix, v); } else { // Item is non-scalar (array or object), encode its numeric index. buildParams( prefix + "[" + (typeof v === "object" && v != null ? i : "") + "]", v, traditional, add ); } }); } else if (!traditional && getType(obj) === "object") { // Serialize object item. for (name in obj) { buildParams(prefix + "[" + name + "]", obj[name], traditional, add); } } else { // Serialize scalar item. add(prefix, obj); } } var prefix, s = [], add = function (key, valueOrFunction) { // If value is a function, invoke it and use its return value var value = typeof valueOrFunction == 'function' ? valueOrFunction() : valueOrFunction; s[s.length] = encodeURIComponent(key) + "=" + encodeURIComponent(value == null ? "" : value); }; if (a == null) { return ""; } // If an array was passed in, assume that it is an array of form elements. if (Array.isArray(a) || (a.jquery && !isPlainObject(a))) { // Serialize the form elements each(a, function () { add(this.name, this.value); }); } else { // If traditional, encode the "old" way (the way 1.3.2 or older // did it), otherwise encode params recursively. for (prefix in a) { buildParams(prefix, a[prefix], traditional, add); } } // Return the resulting serialization return s.join("&");}
3.获取url参数(jQuery代码)
function getUrlParams(queryString) { if (!queryString) { return; } if (queryString.search(/\?/) > -1) { queryString = queryString.split('?')[1]; }else{ return {}; } var queryStringArr = decodeURIComponent(queryString).split('&'); var res = {}; var reg = /\[\]$/; queryStringArr.forEach(function (item) { var itemArr = item.split('='); var name = itemArr[0]; var value = itemArr[1]; // 如果是数字则将其转换成number类型 if (/^\d+$/.test(value) && (value.length < 11)) { value = value * 1; } // 判断是否是多选的 if (reg.test(name)) { name = name.replace(/\[\]/, ''); if (res[name]) { res[name].push(value); } else { res[name] = [value]; } } else { res[name] = value; } }); return res;}
4.革除字符串两端空格,蕴含换行符、制表符
function trim (str) { if (str.length === 0) { return str; } str += ''; // 革除字符串两端空格,蕴含换行符、制表符 return str.replace(/(^[\s\n\t]+|[\s\n\t]+$)/g, '');}
5.将迷信计数法的值转换成失常数字
function toNonExponential (num) { var m = num.toExponential().match(/\d(?:\.(\d*))?e([+-]\d+)/); return num.toFixed(Math.max(0, (m[1] || '').length - m[2])); }
6.依据指定url获取url的域名
function getBaseUrl (_url) { if(!_url){ return ''; } let aEle = document.createElement('a'); let url = ''; aEle.href = _url; url += aEle.protocol + '//' + aEle.host; aEle = null; return url;}
7.获取url的根本信息
function getUrlInfo(_url){ let aEle = document.createElement('a'); aEle.href = _url || location.href; let obj = { protocol: aEle.protocol, host: aEle.host, pathname: aEle.pathname, search: aEle.search, hash: aEle.hash }; return obj;}
8.获取元素在数组中的下标
/** * 获取数组中符合条件的元素的索引 * @param arr 数组 * @param fn 一个函数,如果函数返回true,则返回该项的下标,如果没有找到则返回-1 * */ function getIndex (arr, fn) { if (!arr || arr.length === 0 || !fn || (typeof fn !== 'function')) { return -1; } if (arr.findIndex) { return arr.findIndex(fn); } let len = arr.length; let i = 0; let index = -1; for (; i < len; i++) { let item = arr[i]; if (fn(item, index, arr) === true) { index = i; break; } } return index;}
9.获取浏览器应用的语言
function getBrowserLang () { var type = navigator.appName; let lang = ''; if (type === 'Netscape') { // 获取浏览器配置语言,反对非IE浏览器 lang = navigator.language; } else { // 获取浏览器配置语言,反对IE5+ == navigator.systemLanguage lang = navigator.userLanguage; } return lang.toLowerCase();}
10.给数字后面补零
/** * 给数字后面补零 * 如:padStartZero(10) => 10 * padStartZero(5) => 05 * @param num * @returns {string} */ function padStartZero (num) { return ('00' + num).substr((num + '').length); }
11.截取数字整数位长度(从低位往高位截)
/** * 如:limitInt(12, 3) => 12 * limitInt(145678, 3) => 145 * limitInt(1456.78, 3) => 145.78 * @param num * @param maxSize * @returns {string} */function limitInt(num, maxSize) { num = num + ""; let numArr = num.split("."); let len = (numArr[0] + "").length; if (len > maxSize) { numArr[0] = numArr[0].substring(0, maxSize); } else { return num; } return numArr.join(".");}
12.截取数字小数位长度
/** * 如:limeDecimal(12, 3) => 12 * limeDecimal(14.5678, 3) => 14.557 * limeDecimal(1456.78, 3) => 1456.78 * @param num * @param maxSize * @returns {string} */function limitDecimal(num, maxSize) { if (typeof maxSize == "undefined") { return num; } num = num + ""; let numArr = num.split("."); if (numArr.length == 1) { return num; } if ((numArr[1] + "").length > maxSize) { numArr[1] = numArr[1].substr(0, maxSize); } else { return num; } return numArr.join(".");}
13.将数字格式化到指定位数的小数
/** * 如:decimalPadZero(10,2) => 10.00 * decimalPadZero(10.5,2) => 10.50 * decimalPadZero(10.5678,2) => 10.56 * @param number 数字 * @param scall 保留小数后多少位 * @returns {string} */function decimalRetain(number, scale) { if (isNaN(Number(number))) { return number; } let result = ['', '']; let num = number.toString(); if (num.indexOf('.') !== -1) { let arr = num.split('.'); result[0] = arr[0]; if (arr[1].length === scale) { result[0] += '.' + arr[1]; } else if (arr[1].length > scale) { result[1] = '.'; result[1] += arr[1].substring(0, scale - 1); } else if (arr[1].length < scale) { let zeros = (scale + 1) - arr[1].length; result[0] += '.' + arr[1]; result[1] = Array(zeros).join(0); } } else { result[0] = num; result[1] = '.' + (Array(scale + 1).join(0)); } return result.join("").replace(/\.+$/, "");}
14.数字后面补零
/** * 如:padStartZero(10) => 10 * padStartZero(5) => 05 * @param num * @returns {string} */function padStartZero (num) { return ('00' + num).substr((num + '').length);}
15.判断对象是否是一个空对象
/** * 判断对象是否是一个空对象 * @param obj */function isEmptyObject (obj) { for (var attr in obj) { return false; } return true;}
16.下载文件
/** * 下载文件 * @param fileData 文件数据 * @param fileName 文件名称 * @param mimeType 文件类型 * @param notSupportCallback 浏览器不反对下载时的回调 */function downloadFile (fileData, fileName, mimeType, notSupportCallback) { if (!window.Blob) { notSupportCallback(); return; } // console.log('数据类型:', typeof fileData); if (!(fileData instanceof Blob)) { // 默认为文本文件 let type = typeof mimeType === 'string' ? mimeType : 'text/plain'; fileData = new Blob([fileData], { type }); } let eleA = document.createElement('a'); if ('download' in eleA) { // 非IE下载 let url = URL.createObjectURL(fileData); eleA.href = url; eleA.download = fileName; eleA.style.display = 'none'; document.body.append(eleA); let timer = setTimeout(() => { clearTimeout(timer); eleA.click(); URL.revokeObjectURL(url); document.body.removeChild(eleA); eleA = null; url = null; }, 0); } else if (navigator.msSaveBlob) { // IE10下载 navigator.msSaveBlob(fileData, fileName); }}
17.下载网络图片
(function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define([], factory); } else if (typeof exports === 'object') { // Node. Does not work with strict CommonJS, but // only CommonJS-like environments that support module.exports, // like Node. module.exports = factory(); } else { // Browser globals (root is window) root.download = factory(); }}(this, function () { return function download(data, strFileName, strMimeType) { var self = window, // this script is only for browsers anyway... defaultMime = "application/octet-stream", // this default mime also triggers iframe downloads mimeType = strMimeType || defaultMime, payload = data, url = !strFileName && !strMimeType && payload, anchor = document.createElement("a"), toString = function(a){return String(a);}, myBlob = (self.Blob || self.MozBlob || self.WebKitBlob || toString), fileName = strFileName || "download", blob, reader; myBlob= myBlob.call ? myBlob.bind(self) : Blob ; if(String(this)==="true"){ //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback payload=[payload, mimeType]; mimeType=payload[0]; payload=payload[1]; } if(url && url.length< 2048){ // if no filename and no mime, assume a url was passed as the only argument fileName = url.split("/").pop().split("?")[0]; anchor.href = url; // assign href prop to temp anchor if(anchor.href.indexOf(url) !== -1){ // if the browser determines that it's a potentially valid url path: var ajax=new XMLHttpRequest(); ajax.open( "GET", url, true); ajax.responseType = 'blob'; ajax.onload= function(e){ download(e.target.response, fileName, defaultMime); }; setTimeout(function(){ ajax.send();}, 0); // allows setting custom ajax headers using the return: return ajax; } // end if valid url? } // end if url? //go ahead and download dataURLs right away if(/^data\:[\w+\-]+\/[\w+\-]+[,;]/.test(payload)){ if(payload.length > (1024*1024*1.999) && myBlob !== toString ){ payload=dataUrlToBlob(payload); mimeType=payload.type || defaultMime; }else{ return navigator.msSaveBlob ? // IE10 can't do a[download], only Blobs: navigator.msSaveBlob(dataUrlToBlob(payload), fileName) : saver(payload) ; // everyone else can save dataURLs un-processed } }//end if dataURL passed? blob = payload instanceof myBlob ? payload : new myBlob([payload], {type: mimeType}) ; function dataUrlToBlob(strUrl) { var parts= strUrl.split(/[:;,]/), type= parts[1], decoder= parts[2] == "base64" ? atob : decodeURIComponent, binData= decoder( parts.pop() ), mx= binData.length, i= 0, uiArr= new Uint8Array(mx); for(i;i<mx;++i) uiArr[i]= binData.charCodeAt(i); return new myBlob([uiArr], {type: type}); } function saver(url, winMode){ if ('download' in anchor) { //html5 A[download] anchor.href = url; anchor.setAttribute("download", fileName); anchor.className = "download-js-link"; anchor.innerHTML = "downloading..."; anchor.style.display = "none"; document.body.appendChild(anchor); setTimeout(function() { anchor.click(); document.body.removeChild(anchor); if(winMode===true){setTimeout(function(){ self.URL.revokeObjectURL(anchor.href);}, 250 );} }, 66); return true; } // handle non-a[download] safari as best we can: if(/(Version)\/(\d+)\.(\d+)(?:\.(\d+))?.*Safari\//.test(navigator.userAgent)) { url=url.replace(/^data:([\w\/\-\+]+)/, defaultMime); if(!window.open(url)){ // popup blocked, offer direct download: if(confirm("Displaying New Document\n\nUse Save As... to download, then click back to return to this page.")){ location.href=url; } } return true; } //do iframe dataURL download (old ch+FF): var f = document.createElement("iframe"); document.body.appendChild(f); if(!winMode){ // force a mime that will download: url="data:"+url.replace(/^data:([\w\/\-\+]+)/, defaultMime); } f.src=url; setTimeout(function(){ document.body.removeChild(f); }, 333); }//end saver if (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL) return navigator.msSaveBlob(blob, fileName); } if(self.URL){ // simple fast and modern way using Blob and URL: saver(self.URL.createObjectURL(blob), true); }else{ // handle non-Blob()+non-URL browsers: if(typeof blob === "string" || blob.constructor===toString ){ try{ return saver( "data:" + mimeType + ";base64," + self.btoa(blob) ); }catch(y){ return saver( "data:" + mimeType + "," + encodeURIComponent(blob) ); } } // Blob but not URL support: reader=new FileReader(); reader.onload=function(e){ saver(this.result); }; reader.readAsDataURL(blob); } return true; }; /* end download() */}));// 下载一张图片function downloadImg(url, imgName, fn){ var x=new XMLHttpRequest(); var name = imgName ? (imgName + '.png') : (new Date().getTime() + '.png'); x.open("GET", url, true); x.responseType = 'blob'; x.onload = function (e) { download(x.response, name, "image/png" ); console.log('图片下载实现'); if(typeof fn === 'function'){ fn(); } } x.send();}// 批量下载function downloadImgBatch(imgArr){ let timer = setInterval(function () { console.log('imgArr.length', imgArr.length); if(imgArr.length > 0){ let img = imgArr.shift(0); downloadImg(img.url, img.name); }else{ clearInterval(timer); } }, 500);}
2.DOM常用工具函数
1.绑定事件
/** * 绑定事件 * @param ele dom元素 * @param eventName 事件名称 * @param fn 事件回调函数 */ function bindEvent (ele, eventName, fn) { if (!ele) { console.error('on(ele, eventName, fn)函数第一个参数必须是一个dom元素!'); return; } if (!eventName || typeof eventName !== 'string') { console.error('on(ele, eventName, fn)函数第二个参数必须是一个字符串!'); return; } if (!fn || typeof fn !== 'function') { console.error('on(ele, eventName, fn)函数第三个参数必须是一个函数!'); return; } if (!ele._events) { ele._events = {}; } if (!(eventName in ele._events)) { ele._events[eventName] = [fn]; if (document.addEventListener) { var eventFn = function (e) { var events = ele._events[eventName]; if (events && events.length > 0) { for (var i = 0, len = events.length; i < len; i++) { if (events[i]) { events[i].call(ele, e); } } } }; ele.addEventListener(eventName, eventFn, false); // 把事件回调函数也存起来,这样在移除事件的时候能力真正的把该事件移除掉 ele._events[eventName + '_fn'] = eventFn; } else if (window.attachEvent) { var eventFn = function () { var events = ele._events[eventName]; var e = window.event; e.preventDefault = function () { e.returnValue = false; }; e.stopPropagation = function () { e.cancelBubble = true; }; for (var i = 0, len = events.length; i < len; i++) { events[i].call(ele, e); } }; ele.attachEvent('on' + eventName, eventFn); ele._events[eventName + '_fn'] = eventFn; } } else { //ele._events[eventName] = [fn]; var index = this.getIndex(ele._events[eventName], function (item) { return item === fn; }); if (index < 0 || typeof index === 'undefined') { ele._events[eventName].push(fn); } }}
2.解绑事件
/** * 解绑事件 * @param ele dom元素 * @param eventName 事件名称 * @param fn 事件回调函数 */function unBindEvent (ele, eventName, fn) { if (!ele) { console.error('off(ele, eventName, fn)函数第一个参数必须是一个dom元素!'); return; } if (!eventName || typeof eventName !== 'string') { console.error('off(ele, eventName, fn)函数第二个参数必须是一个字符串!'); return; } if (!ele._events) { return; } if (!eventName) { return; } console.log('off', eventName, ele); var events = ele._events[eventName]; var eventFn = ele._events[eventName + '_fn']; // 如果只传递了事件名称而未传递具体的事件,则将指定事件名称的所有回调函数全副革除 if (eventName && !fn) { if (document.removeEventListener) { //for(var i = 0, len = events.length; i < len; i++){ ele.removeEventListener(eventName, eventFn, false); //} } else if (window.detachEvent) { //for(var i = 0, len = events.length; i < len; i++){ ele.detachEvent('on' + eventName, eventFn); //} } delete ele._events[eventName]; delete ele._events[eventName + '_fn']; } else if (eventName && fn) { if (!events) { return; } if (document.removeEventListener) { var index = this.getIndex(events, function (item) { return item === fn; }); if (index > -1) { events.splice(index, 1); } if (events.length === 0) { delete ele._events[eventName]; delete ele._events[eventName + '_fn']; } } else if (window.detachEvent) { if (!events) { return; } var index = this.getIndex(events, function (item) { return item === fn; }); if (index > -1) { events.splice(index, 1); } if (events.length === 0) { delete ele._events[eventName]; delete ele._events[eventName + '_fn']; } } } events = null;}
3.给指定元素增加class
/** * @param ele * @param classname */function addClass (ele, classname) { if (!ele || !classname || ele.nodeType !== 1) { return; } let classArr = classname.split(' '); if (ele.classList) { for (var i = 0, len = classArr.length; i < len; i++) { let item = classArr[i]; if (!ele.classList.contains(item)) { ele.classList.add(item); } } return ele; } else { let classNameArr = ele.className && ele.className.length > 0 ? ele.className.split(' ') : []; if (classNameArr.length === 0) { ele.className = classname; return; } // 合并两个数组 Array.prototype.push.apply(classNameArr, classArr); classNameArr = tool.arrayNoReapeat(classNameArr); ele.className = classNameArr.join(' '); return ele; }}
4.给指定元素移除class
/** * @param ele * @param classname */function removeClass (ele, classname) { if (!ele || !classname || ele.nodeType !== 1) { return; } let classArr = classname.split(' '); if (ele.classList) { for (var i = 0, len = classArr.length; i < len; i++) { let item = classArr[i]; if (ele.classList.contains(item)) { ele.classList.remove(item); } } return ele; } else { let classNameArr = ele.className && ele.className.length > 0 ? ele.className.split(' ') : []; if (classNameArr.length === 0) { return; } for (var i = classNameArr.length; i >= 0; i--) { for (var j = 0, len2 = classArr.length; j < len2; j++) { if (classNameArr[i] === classArr[j]) { classNameArr.splice(i, 1); } } } ele.className = classNameArr.join(' '); return ele; }}
5.判断元素是否蕴含指定className
/** * 判断元素是否蕴含指定className * @param ele dom元素 * @param className className * @returns {boolean} */function hasClass (ele, className) { if (!ele || !ele.nodeName) { console.error('ele 必须是一个dom元素'); return; } if (!className) { console.error('className 必须是一个字符串'); return; } if (ele.classList) { return ele.classList.contains(className); } else { let flag = false; let classNameArr = ele.className.split(' '); for (let i = 0, len = classNameArr.length; i < len; i++) { if (classNameArr[i] === className) { flag = true; break; } } return flag; }}
6.获取元素的css属性值
/** * 获取元素的css属性值 * @param ele dom元素 * @param cssAttribute css属性名称 */function getStyle (ele, cssAttribute) { if (!ele || !ele.nodeName) { console.error('ele 必须是一个dom元素'); return; } if (!cssAttribute) { console.error('cssAttribute 必须是一个字符串'); return; } let val = ''; if (window.getComputedStyle) { val = window.getComputedStyle(ele, null)[cssAttribute]; } else if (ele.currentStyle) { val = ele.currentStyle[cssAttribute]; } if (!isNaN(parseFloat(val))) { return parseFloat(val); } else { return val; }}
7.给元素设置css属性
/** * 给元素设置css属性 * @param ele dom元素 * @param attr css属性名 * @param val css属性值,如果不传递attr参数,则该参数能够为一个对象,就像jquery的css()办法一样 */function setCss (ele, attrs, val) { if (!ele || !ele.nodeName) { console.error('ele 必须是一个dom元素'); return; } let type1 = ({}).toString.call(attrs); // 须要字段加单位的css属性 let autoAddUnitAttr = { width: 1, height: 1, margin: 1, padding: 1, borderRadius: 1, top: 1, left: 1, marginLeft: 1, marginRight: 1, marginTop: 1, marginBottom: 1, right: 1, bottom: 1, paddingLeft: 1, paddingRight: 1, paddingTop: 1, paddingBottom: 1, borderTopLeftRadius: 1, borderTopRightRadius: 1, borderBottomLeftRadius: 1, borderBottomRightRadius: 1, fontSize: 1, lineHeight: 1, textIndent: 1, minWidth: 1, maxWith: 1 }; if (type1 === '[object String]' && typeof val !== 'undefined') { attrs = attrs.replace(/\-(\w)/g, function (matched, $1) { return $1.toUpperCase(); }); if (attrs in autoAddUnitAttr && !isNaN(Number(val))) { ele.style[attrs] = val + 'px'; } else { ele.style[attrs] = val; } } else if (type1 === '[object Object]') { let style = ele.style; for (let attr in attrs) { let val2 = attrs[attr]; let isNumber = Number(val2); attr = attr.replace(/\-(\w)/g, function (matched, $1) { return $1.toUpperCase(); }); if (attr in autoAddUnitAttr && !isNaN(isNumber)) { style[attr] = val2 + 'px'; } else { style[attr] = val2; } } }}
8.获取兄弟节点
/** * 获取兄弟节点 * @param elm * @returns {Array} */function siblings (elm) { let a = []; let p = elm.parentNode.children; for (let i = 0, pl = p.length; i < pl; i++) { if (p[i] !== elm) a.push(p[i]); } return a;}
9.判断两个元素是否是蕴含关系
/** * 判断两个元素是否是蕴含关系 * @param ele 父元素 * @param childEle 子元素 * @returns {Boolean} */function elementContains (ele, childEle) { if (ele === childEle) { return false; } if (typeof ele.contains === 'function') { return ele.contains(childEle); } else { while (true) { if (!childEle) { return false; } if (childEle === ele) { return true; } else { childEle = childEle.parentNode; } } return false; }}
10.将滚动条滚动到指定元素所在位置
/** * 将滚动条滚动到指定元素所在位置 * @param ele dom元素 * @param extraTop 额定的高度,比方在元素的地位根底上加10px,或减10px * @param autofocus 如果是表单元素的话是否滚动完后主动取得焦点 */function scrollToElement (ele, extraTop, autofocus) { if (!ele || !ele.nodeName) { console.error('ele 必须是一个dom元素'); return; } autofocus = !!autofocus; let top = ele.offsetTop; let offsetParent = ele.offsetParent; while (offsetParent != null) { top += offsetParent.offsetTop; offsetParent = offsetParent.offsetParent; } top += extraTop; window.scrollTo(0, top); if (autofocus && ele.focus) { ele.focus(); }}
11.获取元素的指定父级元素
/** * 获取元素的指定父级元素 * @param el dom 元素 * @param className 父元素的class name * @returns {dom、undefined} */function parents (el, className) { if (!el || !el.nodeName || !className) { return; } var classNameArr = className.split(' '); var parent = el.parentElement; while (parent) { var flag = true; for (var i = 0, len = classNameArr.length; i < len; i++) { if (!this.hasClass(parent, classNameArr[i])) { flag = false; break; } } if (flag) { return parent; } else { parent = parent.parentElement; } }}
12.获取元素距浏览器最顶部及最右边的间隔
/** * 获取元素距浏览器最顶部及最右边的间隔 * @param ele dom元素 */function offset (ele) { let positon = { top: 0, left: 0, }; let offsetParent = ele.offsetParent; positon.top = ele.offsetTop; positon.left = ele.offsetLeft; while (offsetParent != null) { positon.top += offsetParent.offsetTop; positon.left += offsetParent.offsetLeft; offsetParent = offsetParent.offsetParent; } return positon;}
13.获取浏览器滚动条的地位
function scrollTop () { return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;}