DOM相關
判斷瀏覽器是否支持placeholder屬性
function placeholderSupport() { return 'placeholder' in document.createElement('input'); }
html代碼用JS動態加載進頁面
<script type="text/html" id="T-pcList"> //這里面是你要放的html代碼,例如放一個div的內容 </script>
把上面的js動態加入到頁面中:
$(function(){ var s=$("#T-pcList").html();//獲得js的html內容 $(".picScroll-left .bd").html(s);//把s的內容放到class為bd內 thisstyle();//執行某個函數 });
點擊某個div區域之外,隱藏該div
$(document).bind("click",function(e){ var target = $(e.target); if(target.closest(".city_box,#city_select a.selected").length == 0){ $(".city_box").hide(); } })
更全的方式:
$(document).click(function(e){ var _con = $(' 目標區域 '); // 設置目標區域 if(!_con.is(e.target) && _con.has(e.target).length === 0){ // Mark 1 some code... // 功能代碼 } }); /* Mark 1 的原理: 判斷點擊事件發生在區域外的條件是: 1. 點擊事件的對象不是目標區域本身 2. 事件對象同時也不是目標區域的子元素 */
如何在手機上禁止瀏覽器的網頁滾動
方法一:
<body ontouchmove="event.preventDefault()" >
方法二:
document.addEventListener('touchmove', function(event) { event.preventDefault(); })
改變type=file默認樣式,"瀏覽"等字體
<input type="file" id="browsefile" style="visibility:hidden" onchange="filepath.value=this.value"> <input type="button" id="filebutton" value="" onclick="browsefile.click()"> <input type="textfield" id="filepath">
JS動態創建css樣式添加到head內
function addCSS(cssText){ var style = document.createElement('style'); var head = document.head || document.getElementsByTagName('head')[0]; style.type = 'text/css'; if(style.styleSheet){ //IE var func = function(){ try{ //防止IE中stylesheet數量超過限制而發生錯誤 style.styleSheet.cssText = cssText; }catch(e){ } } //如果當前styleSheet還不能用,則放到異步中則行 if(style.styleSheet.disabled){ setTimeout(func,10); }else{ func(); } }else{ //w3c //w3c瀏覽器中只要創建文本節點插入到style元素中就行了 var textNode = document.createTextNode(cssText); style.appendChild(textNode); } //把創建的style元素插入到head中 head.appendChild(style); } //使用 addCSS('#demo{ height: 30px; background:#f00;}');
在IE8以及其低版本瀏覽器下,IE獨有屬性styleSheet.cssText。所以一般的兼容簡單寫法:
var style = document.createElement('style'); style.type = "text/css"; if (style.styleSheet) { //IE style.styleSheet.cssText = '/*..css content here..*/'; } else { //w3c style.innerHTML = '/*..css content here..*/'; } document.getElementsByTagName('head')[0].appendChild(style);
為什么Image對象的src屬性要寫在onload事件后面?
var image=new Image(); imgae.onload = funtion; imgae.src = 'url'
js內部是按順序逐行執行的,可以認為是同步的。
給imgae賦值src時,去加載圖片這個過程是異步的,這個異步過程完成后,如果有onload,則執行onload。
如果先賦值src,那么這個異步過程可能在你賦值onload之前就完成了(比如圖片緩存,或者是js由於某些原因被阻塞了),那么onload就不會執行。
反之,js同步執行確定onload賦值完成后才會賦值src,可以保證這個異步過程在onload賦值完成后才開始進行,也就保證了onload一定會被執行到
js實現insertAfter方法
DOM里還有一個insertBefore方法用於再節點前面附件內容,通過insertBefore和appendChild我們可以實現自己的insertAfter函數:
// 'Target'是DOM里已經存在的元素 // 'Bullet'是要插入的新元素 function insertAfter(target, bullet) { target.nextSibling ? target.parentNode.insertBefore(bullet, target.nextSibling) : target.parentNode.appendChild(bullet); } // 使用了3目表達式: // 格式:條件?條件為true時的表達式:條件為false時的表達式
上面的函數首先檢查target元素的同級下一個節點是否存在,如果存在就在該節點前面添加bullet節點,如果不存在,就說明target是最后一個節點了,直接在后面append新節點就可以了。DOM API沒有給提供insertAfter是因為真的沒必要了——我們可以自己創建。
javascript刪除元素節點
IE中有這樣一個方法:removeNode(),這個方法在IE下是好使的,但是在Firefox等標准瀏覽器中就會報錯了 removeNode is not defined,但是在核心JS中有一個操作DOM節點的方法叫:removeChild()。
我們可以先去找到要刪除節點的父節點,然后在父節點中運用removeChild來移除我們想移除的節點。我們可以定義一個方法叫removeElement:
function removeElement(_element){ var _parentElement = _element.parentNode; if(_parentElement){ _parentElement.removeChild(_element); } }
HTML代碼:
<div><input onclick="removeElement(this)" type="text" value="點擊移除該輸入框" /></div>
BOM相關
JS判斷當前窗口是否有父窗口
if(top.location!=self.location){ //有父窗口 top.location = "https://www.baidu.com"; }else{ //沒有父窗口 window.location.href = "https://www.baidu.com"; }
- "window.location.href"、"location.href"是本頁面跳轉
- "parent.location.href"是上一層頁面跳轉
- "top.location.href"是最外層的頁面跳轉
- "window.location.reload()": 當前頁面刷新
- "parent.location.reload()": 上一層頁面刷新
- "top.location.reload()": 最外層頁面刷新
使用console.time打印代碼執行時間
用console.time
和console.timeEnd
中間代碼執行時長來測試間隔時間。
console.time('console');
console.log('test'); console.timeEnd('console');
打印頁面window.print()
function Printpart(id_str){ //id-str內容中的id var el = document.getElementById(id_str); var iframe = document.createElement('IFRAME'); var doc = null; iframe.setAttribute('style', 'position:absolute;width:0px;height:0px;left:-500px;top:-500px;'); document.body.appendChild(iframe); doc = iframe.contentWindow.document; doc.write('<div>' + el.innerHTML + '</div>'); doc.close(); iframe.contentWindow.focus(); iframe.contentWindow.print(); if (navigator.userAgent.indexOf("MSIE") > 0){ document.body.removeChild(iframe); } }
參考地址:
- http://www.cnblogs.com/yeminglong/archive/2012/12/03/2799957.html
- http://www.cnblogs.com/jikey/archive/2011/06/22/2087683.html
頁面刷新location.reload和location.replace的區別
reload 方法
該方法強迫瀏覽器刷新當前頁面。
語法:
location.reload([bForceGet])
參數: bForceGet, 可選參數, 默認為 false,從客戶端緩存里取當前頁。true, 則以 GET 方式,從服務端取最新的頁面, 相當於客戶端點擊 F5("刷新")
replace 方法
該方法通過指定URL替換當前緩存在歷史里(客戶端)的項目,因此當使用replace方法之后,你不能通過“前進”和“后退”來訪問已經被替換的URL。
語法:
location.replace(URL)
在實際應用的時候,重新刷新頁面的時候,我們通常使用: location.reload() 或者是 history.go(0) 來做。因為這種做法就像是客戶端點F5刷新頁面,所以頁面的method="post"的時候,會出現“網頁過期”的提示。那是因為Session的安全保護機制。可以想到: 當調用 location.reload() 方法的時候, aspx頁面此時在服務端內存里已經存在, 因此必定是 IsPostback 的。如果有這種應用: 我們需要重新加載該頁面,也就是說我們期望頁面能夠在服務端重新被創建, 我們期望是 Not IsPostback 的。這里,location.replace() 就可以完成此任務。被replace的頁面每次都在服務端重新生成。你可以這么寫:location.replace(location.href)
JS中的文檔模式-document.compatMode(老版本)
IE對盒模型的渲染在 Standards Mode和Quirks Mode是有很大差別的,在Standards Mode下對於盒模型的解釋和其他的標准瀏覽器是一樣,但在Quirks Mode模式下則有很大差別,而在不聲明Doctype的情況下,IE默認又是Quirks Mode。所以為兼容性考慮,我們可能需要獲取當前的文檔渲染方式。
document.compatMode正好派上用場,它有兩種可能的返回值:BackCompat和CSS1Compat。
BackCompat:標准兼容模式關閉。瀏覽器客戶區寬度是document.body.clientWidth;
CSS1Compat:標准兼容模式開啟。 瀏覽器客戶區寬度是document.documentElement.clientWidth。
例如:
function getViewport(){ if (document.compatMode == "BackCompat"){ return { width: document.body.clientWidth, height: document.body.clientHeight } }else{ return { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight } } }
window.location屬性
window.location 對象所包含的屬性
屬性 | 描述 |
---|---|
hash | 從井號 (#) 開始的 URL(錨) |
host | 主機名和當前 URL 的端口號 |
hostname | 當前 URL 的主機名 |
href | 完整的 URL |
pathname | 當前 URL 的路徑部分 |
port | 當前 URL 的端口號 |
protocol | 當前 URL 的協議 |
search | 從問號 (?) 開始的 URL(查詢部分) |
protocol 屬性是一個可讀可寫的字符串,可設置或返回當前 URL 的協議。
語法:
location.protocol=path
實例:假設當前的 URL 是: http://example.com:1234/test.htm#part2:
document.write(location.protocol); //輸出:http:
JS中的Navigator對象
Navigator 對象包含有關瀏覽器的信息。
注釋:沒有應用於 navigator 對象的公開標准,不過所有瀏覽器都支持該對象。
Navigator 對象屬性:
屬性 | 描寫 |
---|---|
appCodeName | 返回瀏覽器的代碼名。 |
appMinorVersion | 返回瀏覽器的次級版本。 |
appName |
返回瀏覽器的名稱。 |
appVersion | 返回瀏覽器的平台和版本信息。 |
browserLanguage | 返回當前瀏覽器的語言。 |
cookieEnabled | 返回指明瀏覽器中是否啟用 cookie 的布爾值。 |
cpuClass | 返回瀏覽器系統的 CPU 等級。 |
onLine | 返回指明系統是否處於脫機模式的布爾值。 |
platform | 返回運行瀏覽器的操作系統平台。 |
systemLanguage | 返回 OS 使用的默認語言。 |
userAgent |
返回由客戶機發送服務器的 user-agent 頭部的值。 |
userLanguage | 返回 OS 的自然語言設置。 |
在谷歌瀏覽器中打印Navigator對象,如圖所示:
JS事件與位置坐標
跨瀏覽器添加事件
//跨瀏覽器添加事件 function addEvent(obj,type,fn){ if(obj.addEventListener){ obj.addEventListener(type,fn,false); }else if(obj.attachEvent){//IE obj.attchEvent('on'+type,fn); } }
跨瀏覽器移除事件
//跨瀏覽器移除事件 function removeEvent(obj,type,fn){ if(obj.removeEventListener){ obj.removeEventListener(type,fn,false); }else if(obj.detachEvent){//兼容IE obj.detachEvent('on'+type,fn); } }
跨瀏覽器阻止默認行為
//跨瀏覽器阻止默認行為 function preDef(ev){ var e = ev || window.event; if(e.preventDefault){ e.preventDefault(); }else{ e.returnValue =false; } }
阻止事件冒泡
function stopPro(evt) { var e = evt || window.event; window.event ? e.cancelBubble = true : e.stopPropagation(); }
跨瀏覽器獲取目標對象
//跨瀏覽器獲取目標對象 function getTarget(ev){ if(ev.target){//w3c return ev.target; }else if(window.event.srcElement){//IE return window.event.srcElement; } }
跨瀏覽器獲取滾動條位置
//跨瀏覽器獲取滾動條位置 function getSP(){ return{ top: document.documentElement.scrollTop || document.body.scrollTop, left : document.documentElement.scrollLeft || document.body.scrollLeft; } }
跨瀏覽器獲取可視窗口大小
//跨瀏覽器獲取可視窗口大小 function getWindow () { if(typeof window.innerWidth !='undefined') { //IE8及以下undefined return{ width : window.innerWidth, height : window.innerHeight } }else{ return { width : document.documentElement.clientWidth, height : document.documentElement.clientHeight } } }
跨瀏覽器獲取Style
function getStyle(element, attr) { if (typeof window.getComputedStyle != 'undefined') {//W3C return window.getComputedStyle(element, null)[attr]; } else if (typeof element.currentStyle != 'undeinfed') {//IE return element.currentStyle[attr]; } }
JS獲取相對於文檔坐標
function getMousePos(event) { var e = event || window.event; var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; var scrollY = document.documentElement.scrollTop || document.body.scrollTop; var x = e.pageX || e.clientX + scrollX; var y = e.pageY || e.clientY + scrollY; //alert('x: ' + x + '\ny: ' + y); return { 'x': x, 'y': y }; }
js拖拽效果
<!doctype html> <html lang="zn-CN"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title></title> <style type="text/css"> #login{ height: 100px; width: 100px; border: 1px solid black; position: relative; top:200px; left: 200px; background: red; } </style> </head> <body> <div id="login"></div> <script type="text/javascript"> var oDiv = document.getElementById("login"); oDiv.onmousedown = function(e){ var e = e || window.event;//window.event兼容IE,當事件發生時有效 var diffX = e.clientX - oDiv.offsetLeft;//獲取鼠標點擊的位置到所選對象的邊框的水平距離 var diffY = e.clientY - oDiv.offsetTop; document.onmousemove = function(e){ //需設為document對象才能作用於整個文檔 var e = e||window.event; oDiv.style.left = e.clientX - diffX + 'px';//style.left表示所選對象的邊框到瀏覽器左側距離 oDiv.style.top = e.clientY -diffY + 'px'; }; document.onmouseup = function(){ document.onmousemove = null;//清除鼠標釋放時的對象移動方法 document.onmouseup = null; } } </script> </body> </html>
offsetTop 返回的是數字,而 style.top 返回的是字符串,除了數字外還帶有單位:px。
上下文菜單事件:contextmenu
當我們右擊網頁的時候,會自動出現 windows 自帶的菜單。那么我們可以使用 contextmenu 事件來修改我們指定的菜單,但前提是把右擊的默認行為取消掉。
function addEvent(obj, type, fn) { //添加事件兼容 if (obj.addEventListener) { obj.addEventListener(type, fn); } else if (obj.attachEvent) { obj.attachEvent('on' + type, fn); } } function removeEvent(obj, type, fn) { //移除事件兼容 if (obj.removeEventListener) { ob j.removeEventListener(type, fn); } else if (obj.detachEvent) { obj.detachEvent('on' + type, fn); } } addEvent(window, 'load', function () { var text = document.getElementById('text'); addEvent(text, 'contextmenu', function (evt) { var e = evt || window.event; preDef(e); var menu = document.getElementById('menu'); menu.style.left = e.clientX + 'px'; menu.style.top = e.clientY + 'px'; menu.style.visibility = 'visible'; addEvent(document, 'click', function () { document.getElementById('myMenu').style.visibility = 'hidden'; }); }); });
給table表格中的每個td綁定事件,td數量為1000+,寫一下你的思路(事件委托題)
<body class="container"> <table id="table"> <tr><td>我們是@IT·平頭哥聯盟</td><td>,我是首席填坑官</td><td>蘇南</td><td>前端開發</td><td>優秀</td></tr> <tr><td>我們是@IT·平頭哥聯盟</td><td>,我是首席填坑官</td><td>蘇南</td><td>前端開發</td><td>優秀</td></tr> <tr><td>我們是@IT·平頭哥聯盟</td><td>,我是首席填坑官</td><td>蘇南</td><td>前端開發</td><td>優秀</td></tr> ………… </table> <script> let table =document.querySelector("#table"); table.addEventListener("click",(e)=>{ let {nodeName} = e.target; if(nodeName.toUpperCase() === "TD"){ console.log(e.target);//<td>N</td> } },false); </script> </body>
數組與對象
對象的判空
- 將json對象轉化成json字符串,然后進行判斷是否等於字符串'{}',直接寫{}無法進行判斷
let isObject = {};
console.log(JSON.stringify(isObject) == '{}');
- 使用for循環來判斷,若不為空,則返回false
let listObject = { a: 1, b: 3, c: 4 };
function isEmptyObject() { for(let key in listObject) { return false; } return true; } console.log(isEmptyObject());
- 使用Object.keys()來判斷,返回的是一個數組,根據數組長度來判斷
function isEmptyObject2(obj) { return Object.keys(obj).length == 0; } console.log(isEmptyObject2(isObject));
對這個對象中一定存在的屬性進行判斷
console.log(isObject.id == null);
用對象的屬性查找數組里的對象
var inventory = [ {name: 'apples', quantity: 2}, {name: 'bananas', quantity: 0}, {name: 'cherries', quantity: 5} ]; function findCherries(fruit) { return function(value){ return value.name == fruit } } console.log(inventory.find(findCherries('cherries'))); // { name: 'cherries', quantity: 5 }
將對象轉換成數組Object.values()
Object.values()
方法返回一個給定對象自身的所有可枚舉屬性值的數組,值的順序與使用for...in
循環的順序相同 ( 區別在於 for-in 循環枚舉原型鏈中的屬性 )。
var obj = { foo: 'bar', baz: 42 }; console.log(Object.values(obj)); // ['bar', 42] // array like object var obj = { 0: 'a', 1: 'b', 2: 'c' }; console.log(Object.values(obj)); // ['a', 'b', 'c'] // array like object with random key ordering // when we use numeric keys, the value returned in a numerical order according to the keys var an_obj = { 100: 'a', 2: 'b', 7: 'c' }; console.log(Object.values(an_obj)); // ['b', 'c', 'a'] // getFoo is property which isn't enumerable var my_obj = Object.create({}, { getFoo: { value: function() { return this.foo; } } }); my_obj.foo = 'bar'; console.log(Object.values(my_obj)); // ['bar'] // non-object argument will be coerced to an object console.log(Object.values('foo')); // ['f', 'o', 'o']
Object.values()詳細參考地址:《MDN:Object.values(obj)
》
將類數組對象轉換成數組
- Array.prototype.slice.call(arguments)或者[].slice.call(arguments)
/* 該方法可以將類數組對象轉換為數組,所謂類數組對象,就是含 length 和索引屬性的對象 * 返回的數組長度取決於對象 length 屬性的值,並且非索引屬性的值或索引大於 length 的值都不會被返回到數組中 * Array.prototype.slice.call(obj,start,end) start:方法中slice截取的開始位置,end終止位置,默認從0開始 * */ let testObject = { 0: 'a', 1: 'b', 2: 'c', name: 'admin', length: 3, }; /* 對象中必須定義length,且屬性值不能為非數字,非數字無法返回 */ console.log(Array.prototype.slice.call(testObject)); /* 或者簡寫為[].slice.call(testObject) */ console.log([].slice.call(testObject));
- Array.from()
/* Array、Set、Map 和字符串都是可迭代對象(WeakMap/WeakSet 並不是可迭代對象) * 這些對象都有默認的迭代器,即具有 Symbol.iterator 屬性 * 所有通過生成器創建的迭代器都是可迭代對象 * 可以用 for of 循環 * */ let testObject2 = { 0: 'a', 1: 'b', 2: 'c', name: 'admin', length: 3, }; console.log(Array.from(testObject2));
判斷是否為數組
let temporaryArray3 = [1,2,1,2,3];
console.log(temporaryArray3 instanceof Array); console.log(temporaryArray3.constructor == Array); console.log(Array.isArray(temporaryArray3)); console.log(Object.prototype.toString.call(temporaryArray3) === "[object Array]");
將數組轉換成鍵值對對象
let transformObject = Object.assign({}, temporaryArray3);
console.log(transformObject);
let transformObject2 = {...temporaryArray3}; console.log(transformObject2);
深拷貝與淺拷貝
較常用的對象深拷貝方法:
let copyObject = JSON.parse(JSON.stringify(obj));
Object.assign
- assign對對象分配賦值,實現淺拷貝,但是它有一個特殊的地方,可以處理第一層的深拷貝。
- assign(targetObject, obj, obj1) assign會改變targetObject的值,較好的做法就是將targetObject定義為空對象{}
- assign是將這個3者合並,若有相同的屬性,后面的屬性會覆蓋前面對象的屬性
let temporaryObject2 = {a: 1, d: {e: 3}};
let temporaryObject3 = {b: 1,a: 2}; let mergeObject = Object.assign({}, temporaryObject2, temporaryObject3); console.log(mergeObject); /* mergeObject.d.e不會改變temporaryObject2里a的值,但會改變temporaryObject2里e的值 */ mergeObject.a = 5; mergeObject.d.e = 5; console.log(mergeObject);
數組slice淺拷貝
let copyArray1 = copyArray.slice(0);
數組concat淺拷貝
let copyArray2 = copyArray.concat();
...擴展運算符
const a1 = [1, 2];
// 寫法一 const a2 = [...a1]; // 寫法二 const [...a2] = a1;
上面的兩種寫法,a2
都是a1
的克隆。
生成由隨機整數組成的數組,數組長度和元素大小可自定義
const genNumArr = (length, limit) =>
Array.from({ length }, _ => Math.floor(Math.random() * limit)); genNumArr(10, 100);
JS 將有父子關系的數組轉換成樹形數據
data.forEach(ele => {
let parentId = ele.parentId; if (parentId === 0) { //是根元素的hua ,不做任何操作,如果是正常的for-i循環,可以直接continue. } else { //如果ele是子元素的話 ,把ele扔到他的父親的child數組中. data.forEach(d => { if (d.id === parentId) { let childArray = d.child; if (!childArray) { childArray = [] } childArray.push(ele); d.child = childArray; } }) } }); //去除重復元素 data = data.filter(ele => ele.parentId === 0); console.log('最終等到的tree結構數據: ', data);
使用sort方法根據數組中對象的某一個屬性值進行升序或者降序排列
/**數組根據數組對象中的某個屬性值進行排序的方法 * 使用例子:newArray.sort(sortBy('number',false)) //表示根據number屬性降序排列;若第二個參數不傳遞,默認表示升序排序 * @param attr 排序的屬性 如number屬性 * @param rev true表示升序排列,false降序排序 * */ sortBy: function(attr,rev){ //第二個參數沒有傳遞 默認升序排列 if(rev == undefined){ rev = 1; }else{ rev = (rev) ? 1 : -1; } return function(a,b){ a = a[attr]; b = b[attr]; if(a < b){ return rev * -1; } if(a > b){ return rev * 1; } return 0; } }
Object.create()的不完整polyfilll
沒有 Object.create、Object.setPrototypeOf 的早期版本中,new 運算是唯一一個可以指定 [[prototype]] 的方法(當時的 mozilla 提供了私有屬性 __proto__,但是多數環境並不支持),所以,當時已經有人試圖用它來代替后來的 Object.create,我們甚至可以用它來實現一個 Object.create 的不完整的 polyfill,見以下代碼:
Object.create = function(prototype){ function F(){}; F.prototype = prototype; return new F(); }
這段代碼創建了一個空的構造函數作為類,並把傳入的原型掛在了它的 prototype,最后創建了一個它的實例,根據 new 的行為,這將產生一個以傳入的第一個參數為原型的對象。
注:這個函數無法做到與原生的 Object.create 一致,一個是不支持第二個參數,另一個是不支持 null 作為原型,所以放到今天意義已經不大了。
日期對象Date
獲取當前日期
var calculateDate = function(){ var date = newDate(); var weeks = ["日","一","二","三","四","五","六"]; return date.getFullYear()+"年"+(date.getMonth()+1)+"月"+ date.getDate()+"日 星期"+weeks[date.getDay()]; } $(function(){ $("#dateSpan").html(calculateDate()); })
時間倒計時(固定倒計時的結束時間)
functioncountdown(){
var endtime = newDate("Jan 18, 2015 23:50:00"); var nowtime = newDate(); if (nowtime >= endtime) { document.getElementById("_lefttime").innerHTML = "倒計時間結束"; return; } var leftsecond = parseInt((endtime.getTime() - nowtime.getTime()) / 1000); if (leftsecond < 0) { leftsecond = 0; } __d = parseInt(leftsecond / 3600 / 24); __h = parseInt((leftsecond / 3600) % 24); __m = parseInt((leftsecond / 60) % 60); __s = parseInt(leftsecond % 60); document.getElementById("_lefttime").innerHTML = __d + "天" + __h + "小時" + __m + "分" + __s + "秒"; } countdown(); setInterval(countdown, 1000);
js獲取某年某月的哪些天是周六和周日
function time(y,m){ var tempTime = newDate(y,m,0); var time = newDate(); var saturday = newArray(); var sunday = newArray(); for(var i=1;i<=tempTime.getDate();i++){ time.setFullYear(y,m-1,i); var day = time.getDay(); if(day == 6){ saturday.push(i); }elseif(day == 0){ sunday.push(i); } } var text = y+"年"+m+"月份"+"<br />" +"周六:"+saturday.toString()+"<br />" +"周日:"+sunday.toString(); document.getElementById("text").innerHTML = text; } time(2014,7);
內置對象Math
隨機產生lowwer - upper之間的隨機數
function selectFrom(lower, upper) { var sum = upper - lower + 1; //總數-第一個數+1 return Math.floor(Math.random() * sum + lower); };
正則表達
保留后端傳遞到前端頁面的空格
var objt = { name:' aaaa 這是一個空格多的標簽 這是一個空格多的標簽' } objt.name = objt.name.replace(/\s/g,' '); console.log(objt.name);
用firebug查看結果:
JS replace()方法全局替換變量
簡單替換字符:string.replace("a","b"); (把 a 替換成 b)
全局替換字符:string.replace(/a/g,"b");(全局把a替換成b)
但是如果是全局替換一個變量內容,如下,給一個電話號碼中間加*號:
var phone = "15512345678"; var sliceNumber = phone.slice(3,phone.length - 3); var newPhone = phone.replace(new RegExp(sliceNumber,'g'),'****'); console.log(newPhone); //155****678
正則表達式中的RegExp.$1
RegExp
是javascript
中的一個內置對象。為正則表達式。RegExp.$1
是RegExp的一個屬性,指的是與正則表達式匹配的第一個子匹配(以括號為標志)字符串,以此類推,RegExp.2, RegExp.3, ..RegExp.$99總共可以有99個匹配。
例如:
var r= /^(\d{4})-(\d{1,2})-(\d{1,2})$/; //正則表達式 匹配出生日期(簡單匹配) r.exec('1985-10-15'); s1=RegExp.$1; s2=RegExp.$2; s3=RegExp.$3; console.log(s1+" "+s2+" "+s3)//結果為1985 10 15
用JS將 386485473.88 轉換為 386,485,473.88(千位分割符)
//方法1: var separator=(num)=>{ if(!num){ return '0.00'; }; let str = parseFloat(num).toFixed(2); return str && str .toString() .replace(/(\d)(?=(\d{3})+\.)/g, function($0, $1) { return $1 + ","; }); } separator(386485473.88) //"386,485,473.88" //方法2: (386485473.88).toLocaleString('en-US') // "386,485,473.88" 由 (sRect)補充
函數
求兩個數的和 並以二進制輸出
var m=3; var n=5; var sum=m+n; var result = sum.toString(2); console.log(result); //1000
二進制輸出:toString
函數
使用 Proxy 實現觀察者模式
觀察者模式(Observer mode)指的是函數自動觀察數據對象,一旦對象有變化,函數就會自動執行。
const person = observable({
name: '張三', age: 20 }); function print() { console.log(`${person.name}, ${person.age}`) } observe(print); person.name = '李四'; // 輸出 // 李四, 20
上面代碼中,數據對象person
是觀察目標,函數print
是觀察者。一旦數據對象發生變化,print
就會自動執行。
下面,使用 Proxy 寫一個觀察者模式的最簡單實現,即實現observable
和observe
這兩個函數。思路是observable
函數返回一個原始對象的 Proxy 代理,攔截賦值操作,觸發充當觀察者的各個函數。
const queuedObservers = new Set(); const observe = fn => queuedObservers.add(fn); const observable = obj => new Proxy(obj, {set}); function set(target, key, value, receiver) { const result = Reflect.set(target, key, value, receiver); queuedObservers.forEach(observer => observer()); return result; }
上面代碼中,先定義了一個Set
集合,所有觀察者函數都放進這個集合。然后,observable
函數返回原始對象的代理,攔截賦值操作。攔截函數set
之中,會自動執行所有觀察者。
在firefox, chrome等瀏覽器里,完美模擬new操作
function A( name ){ this.name = name; } function ObjectFactory(){ var obj = {}, Constructor = Array.prototype.shift.call( arguments ); obj.__proto__ = typeof Constructor.prototype === 'number' ? Object.prototype : Constructor.prototype; var ret = Constructor.apply( obj, arguments ); return typeof ret === 'object' ? ret : obj; } var a = ObjectFactory( A, 'mr mo' ); console.log ( a.name ); //mr mo
form表單
form表單提交時設置編碼格式
<form name="form" method="post" action="XXXX" accept-charset="utf-8" onsubmit="document.charset='utf-8';"> //內容 </form>
jQuery操作
JS,Jquery獲取各種屏幕的寬度和高度
Javascript:
- 文檔可視區域寬: document.documentElement.clientWidth
- 文檔可視區域高: document.documentElement.clientHeight
- 網頁可見區域寬: document.body.clientWidth
- 網頁可見區域高: document.body.clientHeight
- 網頁可見區域寬: document.body.offsetWidth(包括邊線的寬)
- 網頁可見區域高: document.body.offsetHeight (包括邊線的高)
- 網頁正文全文寬: document.body.scrollWidth
- 網頁正文全文高: document.body.scrollHeight
- 網頁被卷去的高: document.body.scrollTop
- 網頁被卷去的左: document.body.scrollLeft
- 網頁正文部分上: window.screenTop
- 網頁正文部分左: window.screenLeft
- 屏幕分辨率的高: window.screen.height
- 屏幕分辨率的寬: window.screen.width
- 屏幕可用工作區高度: window.screen.availHeight
- 屏幕可用工作區寬度: window.screen.availWidth
JQuery:
$(document).ready(function(){ alert($(window).height()); //瀏覽器當前窗口可視區域高度 alert($(document).height()); //瀏覽器當前窗口文檔的高度 alert($(document.body).height());//瀏覽器當前窗口文檔body的高度 alert($(document.body).outerHeight(true));//瀏覽器當前窗口文檔body的總高度 包括border padding margin alert($(window).width()); //瀏覽器當前窗口可視區域寬度 alert($(document).width());//瀏覽器當前窗口文檔對象寬度 alert($(document.body).width());//瀏覽器當前窗口文檔body的寬度 alert($(document.body).outerWidth(true));//瀏覽器當前窗口文檔body的總寬度 包括border padding margin })
jQuery取得select選擇的文本與值
jquery獲取select選擇的文本、值、索引:
//獲取select 選中的 text : $("#ddlregtype").find("option:selected").text(); //獲取select選中的 value: $("#ddlregtype ").val(); //獲取select選中的索引: $("#ddlregtype ").get(0).selectedindex;
設置select選中的索引、選中的value:
//設置select 選中的索引: $("#ddlregtype ").get(0).selectedindex=index;//index為索引值 //設置select 選中的value: $("#ddlregtype ").attr("value","normal“); $("#ddlregtype ").val("normal"); $("#ddlregtype ").get(0).value = value;
jquery獲得select中option的索引實例:
html代碼:
<select class="select-green"> <option value="0">高級客戶經理</option> <option value="1">中級客戶經理</option> </select>
jquery代碼:
$(".select-green").change(function(){ var _indx = $(this).get(0).selectedIndex; $(".selectall .selectCon").hide(); $(".selectall .selectCon").eq(_indx).fadeIn(); });
注:其中(this).get(0)與(this)[0]等價
jquery中帶命名空間的事件(namespaced events)
帶命名空間的事件(namespaced events)在jQuery 1.2就被加入了,但是沒有幾個人用,舉例:
$('a').on('click', function() { // Handler 1 }); $('a').on('click', function() { // Handler 2 });
如果我們想要移除第二個handler, 使用$(‘a’).off(‘click’)確會把兩個handler都移除掉!
但是如果使用帶命名空間的事件,就可以搞定:
$('a').on('click.namespace1', function() { //Handler 1 }); $('a').on('click.namespace2', function() { //Handler 2 });
使用如下代碼移除:
$('a').off('click.namespace2');
jquery對文本框只讀狀態與可讀狀態的相互轉化
$('input').removeAttr('Readonly');
$('input').attr('Readonly','true');
移動端
js強制手機頁面橫屏顯示
<script>
// Bind an event to window.orientationchange that, when the device is turned, // gets the orientation and displays it to on screen. $( window ).on( "orientationchange", function( event ) { //alert (event.orientation ) if (event.orientation=='portrait') { $('body').css('transform', 'rotate(90deg)'); } else { $('body').css('transform', 'rotate(0deg)'); } }); // You can also manually force this event to fire. $( window ).orientationchange(); </script>
其它代碼
JS判斷用戶訪問的是PC還是mobile或者微信瀏覽器
var browser = { versions:function(){ var u = navigator.userAgent.toLowerCase(); return { trident: u.indexOf('trident') > -1, presto: u.indexOf('presto') > -1, isChrome: u.indexOf("chrome") > -1 && u.indexOf("safari") > -1 && !(u.indexOf("qqbrowser") > -1), qqbrowser: u.indexOf("qqbrowser") > -1, isFirefox: u.indexOf('firefox') > -1, isSafari: !(u.indexOf("chrome") > -1) && (/webkit|khtml/).test(u) && u.indexOf('safari') > -1, webKit: u.indexOf('applewebkit') > -1, gecko: u.indexOf('gecko') > -1 && u.indexOf('khtml') == -1, mobile: !!u.match(/applewebkit.*mobile.*/), ios: !!u.match(/\(i[^;]+;( u;)? cpu.+mac os x/), android: u.indexOf('android') > -1 || u.indexOf('linux') > -1, iPhone: u.indexOf('iphone') > -1, iPad: u.indexOf('ipad') > -1, iWinPhone: u.indexOf('windows phone') > -1, isWeiXin:!!u.match(/MicroMessenger/i) } } } if(browser.versions.mobile || browser.versions.iWinPhone){ console.log('手機'); }else{ console.log('pc'); }
js判斷變量是否未定義的代碼
一般如果變量通過var聲明,但是並未初始化的時候,變量的值為undefined,而未定義的變量則需要通過 "typeof 變量"的形式來判斷,否則會發生錯誤。
實際應用:
variable有的頁面我們不定義,但有的頁面定義了,就可以需要這樣的判斷方法,沒有定義的就不執行。
if("undefined" != typeof variable){ if(variable=="abc"){ console.log('成功'); } }
JS加入收藏代碼
function addFavorite(title, url) { url = encodeURI(url); try { window.external.addFavorite(url, title); } catch (e) { try { window.sidebar.addPanel(title, url, ""); } catch (e) { alert("加入收藏失敗,Ctrl+D進行添加"); } } } addFavorite(document.title,window.location);
獲取上傳文件的大小
html代碼:
<input type="file" id="filePath" onchange="getFileSize(this)"/>
js代碼:
//兼容IE9低版本獲取文件的大小 function getFileSize(obj){ var filesize; if(obj.files){ filesize = obj.files[0].size; }else{ try{ var path,fso; path = document.getElementById('filePath').value; fso = new ActiveXObject("Scripting.FileSystemObject"); filesize = fso.GetFile(path).size; } catch(e){ //在IE9及低版本瀏覽器,如果不容許ActiveX控件與頁面交互,點擊了否,就無法獲取size console.log(e.message); //Automation 服務器不能創建對象 filesize = 'error'; //無法獲取 } } return filesize; }
限制上傳文件的類型
如果是高版本瀏覽器,一般在HTML代碼中寫就能實現,如:
<input type="file" name="filePath" accept=".jpg,.jpeg,.doc,.docxs,.pdf">
如果限制上傳文件為圖片類型,如下:
<input type="file" class="file" value="上傳" accept="image/*"/>
但是在其它低版本瀏覽器就不管用了,需要js來判斷。
html代碼:
<input type="file" id="filePath" onchange="limitTypes()"/>
js代碼:
/* 通過擴展名,檢驗文件格式。 *@parma filePath{string} 文件路徑 *@parma acceptFormat{Array} 允許的文件類型 *@result 返回值{Boolen}:true or false */ function checkFormat(filePath,acceptFormat){ var resultBool= false, ex = filePath.substring(filePath.lastIndexOf('.') + 1); ex = ex.toLowerCase(); for(var i = 0; i < acceptFormat.length; i++){ if(acceptFormat[i] == ex){ resultBool = true; break; } } return resultBool; }; function limitTypes(){ var obj = document.getElementById('filePath'); var path = obj.value; var result = checkFormat(path,['bmp','jpg','jpeg','png']); if(!result){ alert('上傳類型錯誤,請重新上傳'); obj.value = ''; } }
js 異步加載和同步加載
異步加載也叫非阻塞模式加載,瀏覽器在下載js
的同時,同時還會執行后續的頁面處理。
在script
標簽內,用js
創建一個script
元素並插入到document
中,這種就是異步加載js
文件了:
(function() { var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = 'http://yourdomain.com/script.js'; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); })();
同步加載,平常默認用的都是同步加載。如:
<script src="http://yourdomain.com/script.js"></script>
同步模式又稱阻塞模式,會阻止流覽器的后續處理。停止了后續的文件的解析,執行,如圖像的渲染。瀏覽器之所以會采用同步模式,是因為加載的js
文件中有對dom
的操作,重定向,輸出document
等默認行為,所以同步才是最安全的。
通常會把要加載的js
放到body
結束標簽之前,使得js
可在頁面最后加載,盡量減少阻塞頁面的渲染。這樣可以先讓頁面顯示出來。
同步加載流程是瀑布模型,異步加載流程是並發模型。
跨域的幾種方式
首先了解下瀏覽器的同源策略
同源策略/SOP(Same origin policy)是一種約定,由Netscape公司1995年引入瀏覽器,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSRF等攻擊。所謂同源是指"協議+域名+端口"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。
那么怎樣解決跨域問題的呢?
1 通過jsonp跨域
1.)原生實現: <script> var script = document.createElement('script'); script.type = 'text/javascript'; // 傳參並指定回調執行函數為onBack script.src = 'http://www.....:8080/login?user=admin&callback=onBack'; document.head.appendChild(script); // 回調執行函數 function onBack(res) { alert(JSON.stringify(res)); } </script> 2、 document.domain + iframe跨域 此方案僅限主域相同,子域不同的跨域應用場景。 1.)父窗口:(http://www.domain.com/a.html) <iframe id="iframe" src="http://child.domain.com/b.html"></iframe> <script> document.domain = 'domain.com'; var user = 'admin'; </script> 2.)子窗口:(http://child.domain.com/b.html) <script> document.domain = 'domain.com'; // 獲取父窗口中變量 alert('get js data from parent ---> ' + window.parent.user); </script> 弊端:請看下面渲染加載優化 3、 nginx代理跨域 4、 nodejs中間件代理跨域 5、 后端在頭部信息里面設置安全域名
更多跨域的具體內容請看《跨域詳解》
純前端JS讀取與解析本地文本類文件
var reader = new FileReader(); reader.onload = function (event) { // event.target.result就是文件文本內容 // 然后你就可以為所欲為了 // 例如如果是JSON數據可以解析 // 如果是HTML數據,可以直接插入到頁面中 // 甚至字幕文件,各種濾鏡,自定義文件格式,都可以…… }; reader.readAsText(file);
詳細參考地址:小tips: 純前端JS讀取與解析本地文本類文件
前端通過Blob下載文件流
先看下網上一個簡單的代碼片段:
let blob = new Blob([res], { type: `application / pdf` //word文檔為msword,pdf文檔為pdf }); let objectUrl = URL.createObjectURL(blob); let link = document.createElement("a"); let fname = `我的文檔`; //下載文件的名字 link.href = objectUrl; link.setAttribute("download", fname); document.body.appendChild(link); link.click();
全面:
/** * @param {String} resource 文件流 * @param {String} fileType 文件類型 * @param {String} fileName 文件名 * */ var downloadBlob=function(resource,fileType,fileName){ var data = new Blob([resource],{ type:fileType }); if('download' in document.createElement('a')){ //非IE var downloadUrl = window.URL.createObjectURL(data); var anchor = document.createElement("a"); anchor.href = downloadUrl; anchor.download = fileName; anchor.style.display = 'none'; document.body.appendChild(anchor); anchor.click(); window.URL.revokeObjectURL(anchor.href); document.body.removeChild(anchor); }else{ //IE10+下載 navigator.msSaveBlob(data, fileName); } }
調用方式:
downloadBlob(res,'application/pdf','文檔名稱')
使用html2canvas保存頁面為圖片並下載
html2canvas官網:http://html2canvas.hertzen.com/
<script type="text/javascript" src="js/jquery-1.11.3.min.js"></script> <script type="text/javascript" src="js/html2canvas.min.js"></script> <script type="text/javascript"> $(function(){ $('#button').on('click',function(){ html2canvas(document.querySelector("#capture")).then(canvas => { document.body.appendChild(canvas); let base64 = canvas.toDataURL('images/png'); let a = document.createElement('a'); a.href = base64; a.download = 'download'; a.click(); }); }) }) </script>
vue給文本輸入框聚焦位置添加內容
/** * 文本聚焦位置添加新文本 * @param {Object} myField聚焦的DOM對象 * @param {String} myValue文本框初始值 * @result {String} 返回文本框的value值 * */ function insertTextFromFocus(myField,myValue){ //IE 瀏覽器 if (document.selection) { myField.focus(); var sel = document.selection.createRange(); sel.text = myValue; sel.select(); } //FireFox、Chrome等 else if (myField.selectionStart || myField.selectionStart == '0') { var startPos = myField.selectionStart; var endPos = myField.selectionEnd; // 保存滾動條 var restoreTop = myField.scrollTop; myField.value = myField.value.substring(0, startPos) + myValue + myField.value.substring(endPos, myField.value.length); if (restoreTop > 0) { myField.scrollTop = restoreTop; } myField.focus(); myField.selectionStart = startPos + myValue.length; myField.selectionEnd = startPos + myValue.length; } else { myField.value += myValue; myField.focus(); } return myField.value }
調用方式:
this.dialogRepTemp.content = insertTextFromFocus(this.$refs.content.$el.children[0],data.variable)
TweenMax.js用法總結
markdown語法經常遺忘操作記錄
刪除線:~~ ~~
包裹的文字會顯示刪除線 刪除線
web常用狀態碼整理
200:OK 請求成功。一般用於GET與POST請求
204:No Content 無內容。服務器成功處理,但未返回內容。在未更新網頁的情況下,可確保瀏覽器繼續顯示當前文檔
304:Not Modified 未修改。所請求的資源未修改,服務器返回此狀態碼時,不會返回任何資源。客戶端通常會緩存訪問過的資源,通過提供一個頭信息指出客戶端希望只返回在指定日期之后修改的資源
400:Bad Request 客戶端請求的語法錯誤,服務器無法理解
403:Forbidden 服務器理解請求客戶端的請求,但是拒絕執行此請求
404:Not Found 服務器無法根據客戶端的請求找到資源(網頁)。通過此代碼,網站設計人員可設置"您所請求的資源無法找到"的個性頁面
小tips
檢查加載性能
一個網站加載性能如何主要看白屏時間和首屏時間。
- 白屏時間:指從輸入網址,到頁面開始顯示內容的時間。
- 首屏時間:指從輸入網址,到頁面完全渲染的時間。
將以下腳本放在 </head>
前面就能獲取白屏時間。
<script> new Date() - performance.timing.navigationStart </script>
首屏時間比較復雜,得考慮有圖片和沒有圖片的情況。
如果沒有圖片,則在 window.onload
事件里執行 new Date() - performance.timing.navigationStart
即可獲取首屏時間。
如果有圖片,則要在最后一個在首屏渲染的圖片的 onload
事件里執行 new Date() - performance.timing.navigationStart
獲取首屏時間