function placeholderSupport() { return 'placeholder' in document.createElement('input'); }
<script type="text/html" id="T-pcList"> //這裏面是你要放的html代碼,例如放一個div的內容 </script>
把上面的js動態加入到頁面中:javascript
$(function(){ var s=$("#T-pcList").html();//得到js的html內容 $(".picScroll-left .bd").html(s);//把s的內容放到class爲bd內 thisstyle();//執行某個函數 });
$(document).bind("click",function(e){ var target = $(e.target); if(target.closest(".city_box,#city_select a.selected").length == 0){ $(".city_box").hide(); } })
更全的方式:css
$(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. 事件對象同時也不是目標區域的子元素 */
方法一:html
<body ontouchmove="event.preventDefault()" >
方法二:前端
document.addEventListener('touchmove', function(event) { event.preventDefault(); })
<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">
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。因此通常的兼容簡單寫法:vue
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);
var image=new Image(); imgae.onload = funtion; imgae.src = 'url'
js內部是按順序逐行執行的,能夠認爲是同步的。
給imgae賦值src時,去加載圖片這個過程是異步的,這個異步過程完成後,若是有onload,則執行onload。java
若是先賦值src,那麼這個異步過程可能在你賦值onload以前就完成了(好比圖片緩存,或者是js因爲某些緣由被阻塞了),那麼onload就不會執行。
反之,js同步執行肯定onload賦值完成後纔會賦值src,能夠保證這個異步過程在onload賦值完成後纔開始進行,也就保證了onload必定會被執行到node
DOM裏還有一個insertBefore方法用於再節點前面附件內容,經過insertBefore和appendChild咱們能夠實現本身的insertAfter函數:jquery
// '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是由於真的不必了——咱們能夠本身建立。linux
IE中有這樣一個方法:removeNode(),這個方法在IE下是好使的,可是在Firefox等標準瀏覽器中就會報錯了 removeNode is not defined,可是在覈心JS中有一個操做DOM節點的方法叫:removeChild()。
咱們能夠先去找到要刪除節點的父節點,而後在父節點中運用removeChild來移除咱們想移除的節點。咱們能夠定義一個方法叫removeElement:android
function removeElement(_element){ var _parentElement = _element.parentNode; if(_parentElement){ _parentElement.removeChild(_element); } }
HTML代碼:
<div><input onclick="removeElement(this)" type="text" value="點擊移除該輸入框" /></div>
if(top.location!=self.location){ //有父窗口 top.location = "https://www.baidu.com"; }else{ //沒有父窗口 window.location.href = "https://www.baidu.com"; }
用console.time
和console.timeEnd
中間代碼執行時長來測試間隔時間。
console.time('console');
console.log('test'); console.timeEnd('console');
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); } }
參考地址:
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)
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 對象所包含的屬性
屬性 | 描述 |
---|---|
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:
Navigator 對象包含有關瀏覽器的信息。
註釋:沒有應用於 navigator 對象的公開標準,不過全部瀏覽器都支持該對象。
Navigator 對象屬性:
屬性 | 描寫 |
---|---|
appCodeName | 返回瀏覽器的代碼名。 |
appMinorVersion | 返回瀏覽器的次級版本。 |
appName |
返回瀏覽器的名稱。 |
appVersion | 返回瀏覽器的平臺和版本信息。 |
browserLanguage | 返回當前瀏覽器的語言。 |
cookieEnabled | 返回指明瀏覽器中是否啓用 cookie 的布爾值。 |
cpuClass | 返回瀏覽器系統的 CPU 等級。 |
onLine | 返回指明系統是否處於脫機模式的布爾值。 |
platform | 返回運行瀏覽器的操做系統平臺。 |
systemLanguage | 返回 OS 使用的默認語言。 |
userAgent |
返回由客戶機發送服務器的 user-agent 頭部的值。 |
userLanguage | 返回 OS 的天然語言設置。 |
在谷歌瀏覽器中打印Navigator對象,如圖所示:
//跨瀏覽器添加事件 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 } } }
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]; } }
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 }; }
<!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。
當咱們右擊網頁的時候,會自動出現 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'; }); }); });
<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>
let isObject = {};
console.log(JSON.stringify(isObject) == '{}');
let listObject = { a: 1, b: 3, c: 4 };
function isEmptyObject() { for(let key in listObject) { return false; } return true; } console.log(isEmptyObject());
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()
方法返回一個給定對象自身的全部可枚舉屬性值的數組,值的順序與使用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)
》
/* 該方法能夠將類數組對象轉換爲數組,所謂類數組對象,就是含 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、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
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);
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);
/**數組根據數組對象中的某個屬性值進行排序的方法 * 使用例子: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、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 做爲原型,因此放到今天意義已經不大了。
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);
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);
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查看結果:
簡單替換字符: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
是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
//方法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
函數
觀察者模式(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
之中,會自動執行全部觀察者。
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 name="form" method="post" action="XXXX" accept-charset="utf-8" onsubmit="document.charset='utf-8';"> //內容 </form>
Javascript:
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選擇的文本、值、索引:
//獲取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]等價
帶命名空間的事件(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');
$('input').removeAttr('Readonly');
$('input').attr('Readonly','true');
<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>
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'); }
通常若是變量經過var聲明,可是並未初始化的時候,變量的值爲undefined,而未定義的變量則須要經過 "typeof 變量"的形式來判斷,不然會發生錯誤。
實際應用:
variable有的頁面咱們不定義,但有的頁面定義了,就能夠須要這樣的判斷方法,沒有定義的就不執行。
if("undefined" != typeof variable){ if(variable=="abc"){ console.log('成功'); } }
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
的同時,同時還會執行後續的頁面處理。
在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> 二、 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中間件代理跨域 五、 後端在頭部信息裏面設置安全域名
更多跨域的具體內容請看《跨域詳解》
var reader = new FileReader(); reader.onload = function (event) { // event.target.result就是文件文本內容 // 而後你就能夠隨心所欲了 // 例如若是是JSON數據能夠解析 // 若是是HTML數據,能夠直接插入到頁面中 // 甚至字幕文件,各類濾鏡,自定義文件格式,均可以…… }; reader.readAsText(file);
詳細參考地址:小tips: 純前端JS讀取與解析本地文本類文件
先看下網上一個簡單的代碼片斷:
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官網: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>
/** * 文本聚焦位置添加新文本 * @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)
刪除線:~~ ~~
包裹的文字會顯示刪除線 刪除線
200:OK 請求成功。通常用於GET與POST請求
204:No Content 無內容。服務器成功處理,但未返回內容。在未更新網頁的狀況下,可確保瀏覽器繼續顯示當前文檔
304:Not Modified 未修改。所請求的資源未修改,服務器返回此狀態碼時,不會返回任何資源。客戶端一般會緩存訪問過的資源,經過提供一個頭信息指出客戶端但願只返回在指定日期以後修改的資源
400:Bad Request 客戶端請求的語法錯誤,服務器沒法理解
403:Forbidden 服務器理解請求客戶端的請求,可是拒絕執行此請求
404:Not Found 服務器沒法根據客戶端的請求找到資源(網頁)。經過此代碼,網站設計人員可設置"您所請求的資源沒法找到"的個性頁面