異步加載JS和CSSjavascript
<script type="text/javascript"> (function () { var s = document.createElement('script'); s.async = true; s.type = 'text/javascript'; s.setAttribute('external_src', '//' + window.disqus_shortname + '.disqus.com/count.js'); (document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s); }()); </script> $(window).load(function() { $('[external_src]').each(function() { var external_src = $(this).attr("external_src"); $(this).attr("src", $(this).attr("external_src")).removeAttr("external_src"); }); });
微信分享圖標:css
<title>閃電借款 56秒極速到帳</title> <div id='wx_pic' style='margin:0 auto;display:none;'> <img src="" /> </div>
在jquery中each循環中,要用return false代替break,return true代替continue。 $.each(data, function (n, value) { if(value.status==1){ return false;//至關於break } else if(value.status==2){ return true;//至關於continue } })
JavaScript有五種基本數據類型(Undefined, null, Boolean, String, Number),還有一種複雜的數據類型,就是對象。html
Undefined 實際上是已聲明但沒有賦值的變量的輸出結果,null其實就是一個不存在的對象的結果前端
對於簡單的數據類型
它們值在佔據了內存中固定大小的空間,並被保存在棧內存中。 當一個變量向另外一個變量複製基本類型的值時,會建立這個值的副本,還有就是不能給基本類型的值添加屬性。java
1234var a = 1;var b = a;a.attr = 'long';console.log(a.attr) //undefinedjquery
上邊代碼中a就是簡單數據類型(number),b就是a的副本,它們二者都佔有不一樣位置,但相等的內存空間。android
對於複雜的數據類型
複雜的數據類型即引用類型,它的值是對象,保存在堆內存中,包含引用類型值的變量實際上包含的並非對象自己,而是一個指向該對象的指針。從一個變量向另外一個變量複製引用類型的值,複製的實際上是指針,所以兩個變量最終都指向同一個對象。ios
12345678var obj = { name: 'long', age: 0};var obj2 = obj;obj2.c = 5;console.log(obj); //Oject {name: 'long', age: 0, c: 5}console.log(obj2); //Oject {name: 'long', age: 0, c: 5}git
咱們能夠看到obj賦值給obj2後,當咱們更改其中一個對象的屬性值,兩個對象都發生了改變,究其緣由是由於obj和obj2這兩個變量都指向同一個指針,賦值是複製了指針,因此當咱們改變其中一個值,就會影響另外一個變量的值。github
淺拷貝
其實上邊的代碼就是淺拷貝,有時候咱們只是想備份數組,可是隻是簡單讓它賦給一個變量,改變其中一個,另一個就緊跟着改變,但不少時候這不是咱們想要的。
12345678var obj = { name:'wsscat', age:0 } var obj2 = obj; obj2['c'] = 5; console.log(obj);//Object {name: "wsscat", age: 0, c: 5} console.log(obj2);////Object {name: "wsscat", age: 0, c: 5}
深拷貝數組
對於數組咱們可使用slice()和concat()方法來解決上面的問題。
slice
12345var arr = ['ge', 'yu', 'long'];var arrCopy = arr.slice(0);arrCopy[0] = 'gai';console.log(arr) // ['ge', 'yu', 'long']console.log(arrCopy) // ['gai', 'yu', 'long']
concat
1234var arr = ['ge', 'yu', 'long'];var arrCopy = arr.concat();arrCopy[0] = 'gai';//console跟上邊同樣
對象
對象咱們能夠定義一個新的對象並遍歷新的屬性去實現深拷貝
原始方法:
12345678910var obj = { name: 'geyulong', age: 0};var obj2 = new Object();obj2.name = obj.name;obj2.age = obj.age;obj.name = "gaiyulong";console.log(obj); // Object {name: 'geyulong', age: 0}console.log(obj2); // Object {name: 'gaiyulong', age: 0}
固然咱們是要封裝一個方法來實現深拷貝。
123456789101112var deepCopy = function(source) { var result = {}; for(var key in source) { if(typeof source[key] === 'object') { result[key] = deepCopy(source[key]) } else { result[key] = source[key] } } return result;}var obj2 = deepCopy(obj);
Meta基礎知識:
H5頁面窗口自動調整到設備寬度,並禁止用戶縮放頁面
//1、HTML頁面結構
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
// width 設置viewport寬度,爲一個正整數,或字符串‘device-width’
// height 設置viewport高度,通常設置了寬度,會自動解析出高度,能夠不用設置
// initial-scale 默認縮放比例,爲一個數字,能夠帶小數
// minimum-scale 容許用戶最小縮放比例,爲一個數字,能夠帶小數
// maximum-scale 容許用戶最大縮放比例,爲一個數字,能夠帶小數
// user-scalable 是否容許手動縮放
//2、JS動態判斷
var phoneWidth = parseInt(window.screen.width);
var phoneScale = phoneWidth/640;
var ua = navigator.userAgent;
if (/Android (\d+\.\d+)/.test(ua)){
var version = parseFloat(RegExp.$1);
if(version>2.3){
document.write('<meta name="viewport" content="width=640, minimum-scale = '+phoneScale+', maximum-scale = '+phoneScale+', target-densitydpi=device-dpi">');
}else{
document.write('<meta name="viewport" content="width=640, target-densitydpi=device-dpi">');
}
} else {
document.write('<meta name="viewport" content="width=640, user-scalable=no, target-densitydpi=device-dpi">');
}
空白頁基本meta標籤
<!-- 設置縮放 -->
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimal-ui" />
<!-- 可隱藏地址欄,僅針對IOS的Safari(注:IOS7.0版本之後,safari上已看不到效果) -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<!-- 僅針對IOS的Safari頂端狀態條的樣式(可選default/black/black-translucent ) -->
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<!-- IOS中禁用將數字識別爲電話號碼/忽略Android平臺中對郵箱地址的識別 -->
<meta name="format-detection"content="telephone=no, email=no" />
其餘meta標籤
<!-- 啓用360瀏覽器的極速模式(webkit) -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 針對手持設備優化,主要是針對一些老的不識別viewport的瀏覽器,好比黑莓 -->
<meta name="HandheldFriendly" content="true">
<!-- 微軟的老式瀏覽器 -->
<meta name="MobileOptimized" content="320">
<!-- uc強制豎屏 -->
<meta name="screen-orientation" content="portrait">
<!-- QQ強制豎屏 -->
<meta name="x5-orientation" content="portrait">
<!-- UC強制全屏 -->
<meta name="full-screen" content="yes">
<!-- QQ強制全屏 -->
<meta name="x5-fullscreen" content="true">
<!-- UC應用模式 -->
<meta name="browsermode" content="application">
<!-- QQ應用模式 -->
<meta name="x5-page-mode" content="app">
<!-- windows phone 點擊無高光 -->
<meta name="msapplication-tap-highlight" content="no">
常見問題:
移動端如何定義字體font-family
打電話發短信寫郵件怎麼實現
// 1、打電話
<a href="tel:0755-10086">打電話給:0755-10086</a>
// 2、發短信,winphone系統無效
<a href="sms:10086">發短信給: 10086</a>
// 3、寫郵件
//注:在添加這些功能時,第一個功能以"?"開頭,後面的以"&"開頭
//1.普通郵件
<a href="mailto:863139978@qq.com">點擊我發郵件</a>
//2.收件地址後添加?cc=開頭,可添加抄送地址(Android存在兼容問題)
<a href="mailto:863139978@qq.com?cc=zhangqian0406@yeah.net">點擊我發郵件</a>
//3.跟着抄送地址後,寫上&bcc=,可添加密件抄送地址(Android存在兼容問題)
<a href="mailto:863139978@qq.com?cc=zhangqian0406@yeah.net&bcc=384900096@qq.com">點擊我發郵件</a>
//4.包含多個收件人、抄送、密件抄送人,用分號(;)隔開多個郵件人的地址
<a href="mailto:863139978@qq.com;384900096@qq.com">點擊我發郵件</a>
//5.包含主題,用?subject=
<a href="mailto:863139978@qq.com?subject=郵件主題">點擊我發郵件</a>
//6.包含內容,用?body=;如內容包含文本,使用%0A給文本換行
<a href="mailto:863139978@qq.com?body=郵件主題內容%0A騰訊誠信%0A期待您的到來">點擊我發郵件</a>
//7.內容包含連接,含http(s)://等的文本自動轉化爲連接
<a href="mailto:863139978@qq.com?body=http://www.baidu.com">點擊我發郵件</a>
//8.內容包含圖片(PC不支持)
<a href="mailto:863139978@qq.com?body=<img src="" />">點擊我發郵件</a>
//9.完整示例
<a href="mailto:863139978@qq.com;384900096@qq.com?cc=zhangqian0406@yeah.net&bcc=993233461@qq.com&subject=[郵件主題]&body=騰訊誠邀您參與%0A%0Ahttp://www.baidu.com%0A%0A<img src="" />">點擊我發郵件</a>
移動端touch事件(區分webkit和winphone)
/* 當用戶手指放在移動設備在屏幕上滑動會觸發的touch事件 */
// 如下支持webkit
touchstart——當手指觸碰屏幕時候發生。無論當前有多少隻手指
touchmove——當手指在屏幕上滑動時連續觸發。一般咱們再滑屏頁面,會調用event的preventDefault()能夠阻止默認狀況的發生:阻止頁面滾動
touchend——當手指離開屏幕時觸發
touchcancel——系統中止跟蹤觸摸時候會觸發。例如在觸摸過程當中忽然頁面alert()一個提示框,此時會觸發該事件,這個事件比較少用
//TouchEvent說明:
touches:屏幕上全部手指的信息
targetTouches:手指在目標區域的手指信息
changedTouches:最近一次觸發該事件的手指信息
touchend時,touches與targetTouches信息會被刪除,changedTouches保存的最後一次的信息,最好用於計算手指信息
//參數信息(changedTouches[0])
clientX、clientY在顯示區的座標
target:當前元素
//事件響應順序
ontouchstart > ontouchmove > ontouchend > onclick
// 如下支持winphone 8
MSPointerDown——當手指觸碰屏幕時候發生。無論當前有多少隻手指
MSPointerMove——當手指在屏幕上滑動時連續觸發。一般咱們再滑屏頁面,會調用css的html{-ms-touch-action: none;}能夠阻止默認狀況的發生:阻止頁面滾動
MSPointerUp——當手指離開屏幕時觸發
移動端click屏幕產生200-300ms的延時響應
說明:移動設備上的web網頁是有300ms延遲的,玩玩會形成按鈕點擊延遲甚至是點擊失效。
如下是歷史緣由,來源一個公司內一個同事的分享:
2007年蘋果發佈首款iphone上IOS系統搭載的safari爲了將適用於PC端上大屏幕的網頁能比較好的展現在手機端上,使用了雙擊縮放(double tap to zoom)的方案,好比你在手機上用瀏覽器打開一個PC上的網頁,你可能在看到頁面內容雖然能夠撐滿整個屏幕,可是字體、圖片都很小看不清,此時能夠快速雙擊屏幕上的某一部分,你就能看清該部分放大後的內容,再次雙擊後能回到原始狀態。
雙擊縮放是指用手指在屏幕上快速點擊兩次,iOS 自帶的 Safari 瀏覽器會將網頁縮放至原始比例。
緣由就出在瀏覽器須要如何判斷快速點擊上,當用戶在屏幕上單擊某一個元素時候,例如跳轉連接<a href="#"></a>,此處瀏覽器會先捕獲該次單擊,但瀏覽器不能決定用戶是單純要點擊連接仍是要雙擊該部分區域進行縮放操做,因此,捕獲第一次單擊後,瀏覽器會先Hold一段時間t,若是在t時間區間裏用戶未進行下一次點擊,則瀏覽器會作單擊跳轉連接的處理,若是t時間裏用戶進行了第二次單擊操做,則瀏覽器會禁止跳轉,轉而進行對該部分區域頁面的縮放操做。那麼這個時間區間t有多少呢?在IOS safari下,大概爲300毫秒。這就是延遲的由來。形成的後果用戶純粹單擊頁面,頁面須要過一段時間才響應,給用戶慢體驗感受,對於web開發者來講是,頁面js捕獲click事件的回調函數處理,須要300ms後才生效,也就間接致使影響其餘業務邏輯的處理。
//解決方案:
fastclick能夠解決在手機上點擊事件的300ms延遲
zepto的touch模塊,tap事件也是爲了解決在click的延遲問題
Rentina顯示屏原理及設計方案
說明:retina屏是一種具有超高像素密度的液晶屏,一樣大小的屏幕上顯示的像素點由1個變爲多個,如在一樣帶下的屏幕上,蘋果設備的retina顯示屏中,像素點1個變爲4個。
在高清顯示屏中的位圖被放大,圖片會變得模糊,所以移動端的視覺稿一般會設計爲傳統PC的2倍。
那麼,前端的應對方案是:設計稿切出來的圖片長寬保證爲偶數,並使用backgroud-size把圖片縮小爲原來的1/2
//例如圖片寬高爲:200px*200px,那麼寫法以下
.css{width:100px;height:100px;background-size:100px 100px;}
//其它元素的取值爲原來的1/2,例如視覺稿40px的字體,使用樣式的寫法爲20px
.css{font-size:20px}
//image-set設計Rentina背景圖
image-set,webkit私有屬性,也是CSS4的屬性,爲解決Rentina屏幕下的圖像而生。
.css {
background: url(images/bg.jpg) no-repeat center;
background: -webkit-image-set(
url(images/bg.jpg) 1x, //支持image-set普通屏
url(images/bg-2x.jpg) 2x); //支持image-set的Rentinan
}
點擊元素產生背景或邊框怎麼去掉
/ios用戶點擊一個連接,會出現一個半透明灰色遮罩, 若是想要禁用,可設置-webkit-tap-highlight-color的alpha值爲0去除灰色半透明遮罩;
//android用戶點擊一個連接,會出現一個邊框或者半透明灰色遮罩, 不一樣生產商定義出來額效果不同,可設置-webkit-tap-highlight-color的alpha值爲0去除部分機器自帶的效果;
//winphone系統,點擊標籤產生的灰色半透明背景,能經過設置<meta name="msapplication-tap-highlight" content="no">去掉;
//特殊說明:有些機型去除不了,如小米2。對於按鈕類還有個辦法,不使用a或者input標籤,直接用div標籤
a,button,input,textarea {
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-user-modify:read-write-plaintext-only; //-webkit-user-modify有個反作用,就是輸入法再也不可以輸入多個字符
}
// 也能夠
* { -webkit-tap-highlight-color: rgba(0,0,0,0); }
//winphone下
<meta name="msapplication-tap-highlight" content="no">
美化表單元素
//1、使用appearance改變webkit瀏覽器的默認外觀
input,select { -webkit-appearance:none; appearance: none; }
//2、winphone下,使用僞元素改變表單元素默認外觀
//1.禁用select默認箭頭,::-ms-expand修改表單控件下拉箭頭,設置隱藏並使用背景圖片來修飾
select::-ms-expand { display:none; }
//2.禁用radio和checkbox默認樣式,::-ms-check修改表單複選框或單選框默認圖標,設置隱藏並使用背景圖片來修飾
input[type=radio]::-ms-check,
input[type=checkbox]::-ms-check { display:none; }
//3.禁用pc端表單輸入框默認清除按鈕,::-ms-clear修改清除按鈕,設置隱藏並使用背景圖片來修飾
input[type=text]::-ms-clear,
input[type=tel]::-ms-clear,
input[type=number]::-ms-clear { display:none; }
移動端字體單位font-size選擇px仍是rem
// 如需適配多種移動設備,建議使用rem。如下爲參考值:
html { font-size: 62.5%; } //10*16 = 62.5%
//設置12px字體 這裏注意在rem前要加上對應的px值,解決不支持rem的瀏覽器的兼容問題,作到優雅降級
body { font-size:12px; font-size:1.2rem; }
超實用的CSS樣式
//去掉webkit的滾動條——display: none;
//其餘參數
::-webkit-scrollba //滾動條總體部分
::-webkit-scrollbar-thumb //滾動條內的小方塊
::-webkit-scrollbar-track //滾動條軌道
::-webkit-scrollbar-button //滾動條軌道兩端按鈕
::-webkit-scrollbar-track-piece //滾動條中間部分,內置軌道
::-webkit-scrollbar-corner //邊角,兩個滾動條交匯處
::-webkit-resizer //兩個滾動條的交匯處上用於經過拖動調整元素大小的小控件
// 禁止長按連接與圖片彈出菜單
a,img { -webkit-touch-callout: none }
// 禁止ios和android用戶選中文字
html,body {-webkit-user-select:none; user-select: none; }
// 改變輸入框placeholder的顏色值
::-webkit-input-placeholder { /* WebKit browsers */
color: #999; }
:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
color: #999; }
::-moz-placeholder { /* Mozilla Firefox 19+ */
color: #999; }
:-ms-input-placeholder { /* Internet Explorer 10+ */
color: #999; }
input:focus::-webkit-input-placeholder{ color:#999; }
// android上去掉語音輸入按鈕
input::-webkit-input-speech-button {display: none}
// 阻止windows Phone的默認觸摸事件
/*說明:winphone下默認觸摸事件事件使用e.preventDefault是無效的,可經過樣式來禁用,如:*/
html { -ms-touch-action:none; } //禁止winphone默認觸摸事件
取消input在ios下,輸入的時候英文首字母的默認大寫
<input autocapitalize="off" autocorrect="off" />
手機拍照和上傳圖片
//IOS有拍照、錄像、選取本地圖片功能,部分Android只有選擇本地圖片功能。Winphone不支持
<input type="file" accept="images/*" />
<input type="file" accept="video/*" />
屏幕旋轉的事件和樣式
//JS處理
function orientInit(){
var orientChk = document.documentElement.clientWidth > document.documentElement.clientHeight?'landscape':'portrait';
if(orientChk =='lapdscape'){
//這裏是橫屏下須要執行的事件
}else{
//這裏是豎屏下須要執行的事件
}
}
orientInit();
window.addEventListener('onorientationchange' in window?'orientationchange':'resize', function(){
setTimeout(orientInit, 100);
},false)
//CSS處理
//豎屏時樣式
@media all and (orientation:portrait){ }
//橫屏時樣式
@media all and (orientation:landscape){ }
audio元素和video元素在ios和andriod中沒法自動播放
//音頻,寫法一
<audio src="music/bg.mp3" autoplay loop controls>你的瀏覽器還不支持哦</audio>
//音頻,寫法二
<audio controls="controls">
<source src="music/bg.ogg" type="audio/ogg"></source>
<source src="music/bg.mp3" type="audio/mpeg"></source>
優先播放音樂bg.ogg,不支持在播放bg.mp3
</audio>
//JS綁定自動播放(操做window時,播放音樂)
$(window).one('touchstart', function(){
music.play();
})
//微信下兼容處理
document.addEventListener("WeixinJSBridgeReady", function () {
music.play();
}, false);
//小結
//1.audio元素的autoplay屬性在IOS及Android上沒法使用,在PC端正常
//2.audio元素沒有設置controls時,在IOS及Android會佔據空間大小,而在PC端Chrome是不會佔據任何空間
重力感應事件
// 運用HTML5的deviceMotion,調用重力感應事件
if(window.DeviceMotionEvent){
document.addEventListener('devicemotion', deviceMotionHandler, false)
}
var speed = 30;
var x = y = z = lastX = lastY = lastZ = 0;
function deviceMotionHandler(eventData){
var acceleration = event.accelerationIncludingGravity;
x = acceleration.x;
y = acceleration.y;
z = acceleration.z;
if(Math.abs(x-lastX)>speed || Math.abs(y-lastY)>speed || Math.abs(z-lastZ)>speed ){
//這裏是搖動後要執行的方法
yaoAfter();
}
lastX = x;
lastY = y;
lastZ = z;
}
function yaoAfter(){
//do something
}
微信瀏覽器用戶調整字體大小後頁面矬了,怎麼阻止用戶調整
//如下代碼可以使Android機頁面再也不受用戶字體縮放強制改變大小,可是會有1S左右延時,期間能夠考慮loading來處理
if (typeof(WeixinJSBridge) == "undefined") {
document.addEventListener("WeixinJSBridgeReady", function (e) {
setTimeout(function(){
WeixinJSBridge.invoke('setFontSizeCallback', { 'fontSize':0}, function(res){
alert(JSON.stringify(res));
})
}, 0)
});
}else{
setTimeout(function(){
WeixinJSBridge.invoke('setFontSizeCallback', { 'fontSize':0}, function(res){
alert(JSON.stringify(res));
})
}, 0)
}
//IOS下可以使用 -webkit-text-size-adjust禁止用戶調整字體大小
body { -webkit-text-size-adjust:100%!important; }
//最好的解決方案:最好使用rem或百分比佈局
定位的坑
//fixed定位
//1.ios下fixed元素容易定位出錯,軟鍵盤彈出時,影響fixed元素定位
//2.android下fixed表現要比iOS更好,軟鍵盤彈出時,不會影響fixed元素定位
//3.ios4下不支持position:fixed
//解決方案:使用[Iscroll](http://cubiq.org/iscroll-5),如:
<div id="wrapper">
<ul>
<li></li>
.....
</ul>
</div>
<script src="iscroll.js"></script>
<script>
var myscroll;
function loaded(){
myscroll=new iScroll("wrapper");
}
window.addEventListener("DOMContentLoaded",loaded,false);
</script>
//position定位
//Android下彈出軟鍵盤彈出時,影響absolute元素定位
//解決方案:
var ua = navigator.userAgent.indexOf('Android');
if(ua>-1){
$('.ipt').on('focus', function(){
$('.css').css({'visibility':'hidden'})
}).on('blur', function(){
$('.css').css({'visibility':'visible'})
})
}
播放視頻不全屏
<!--
1.ios7+支持自動播放
2.支持Airplay的設備(如:音箱、Apple TV)播放
x-webkit-airplay="true"
3.播放視頻不全屏
webkit-playsinline="true"
-->
<video x-webkit-airplay="true" webkit-playsinline="true" preload="auto" autoplay src="http://"></video>
JS判斷設備
function deviceType(){
var ua = navigator.userAgent;
var agent = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
for(var i=0; i<len,len = agent.length; i++){
if(ua.indexOf(agent[i])>0){
break;
}
}
}
deviceType();
window.addEventListener('resize', function(){
deviceType();
})
JS判斷微信瀏覽器
function isWeixin(){
var ua = navigator.userAgent.toLowerCase();
if(ua.match(/MicroMessenger/i)=='micromessenger'){
return true;
}else{
return false;
}
}
android 2.3 bug
//1.@-webkit-keyframes 須要以0%開始100%結束,0%的百分號不能去掉
//2.after和before僞類沒法使用動畫animation
//3.border-radius不支持%單位,如要兼容,能夠給radius設置一下較大的值
//4.translate百分比的寫法和scale在一塊兒會致使失效,例如:
-webkit-transform: translate(-50%,-50%) scale(-0.5, 1)
android 4.x bug
//1.三星 Galaxy S4中自帶瀏覽器不支持border-radius縮寫
//2.同時設置border-radius和背景色的時候,背景色會溢出到圓角之外部分
//3.部分手機(如三星),a連接支持鼠標:visited事件,也就是說連接訪問後文字變爲紫色
//4.android沒法同時播放多音頻audio
消除transition閃屏
.css {
-webkit-transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
-webkit-perspective: 1000;
}
開啓硬件加速
//目前,像Chrome/Filefox/Safari/IE9+以及最新版本Opera都支持硬件加速,當檢測到某個DOM元素應用了某些CSS規則時就會自動開啓,從而解決頁面閃白,保證動畫流暢。
.css {
-webkit-transform: translate3d(0,0,0);
-moz-transform: translate3d(0,0,0);
-ms-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);
}
渲染優化
//1.禁止使用iframe(阻塞父文檔onload事件)
//2.禁止使用gif圖片實現loading效果(下降CPU消耗,提高渲染性能)
//使用CSS3代碼代替JS動畫;
//開啓GPU加速;
//使用base64位編碼圖片(不小圖而言,大圖不建議使用)
// 對於一些小圖標,可使用base64位編碼,以減小網絡請求。但不建議大圖使用,比較耗費CPU。小圖標優點在於:
//1.減小HTTP請求;
//2.避免文件跨域;
//3.修改及時生效;
目錄
在javascript開發中,比較操做是十分常見的。因爲顯式/隱式強制類型轉換機制的存在,咱們在使用比較運算時顯得過於隨意,也許表面上看並無什麼錯誤(好比在if()語句中判斷兩值相等時順手就寫成 == ),可是這可能會埋下不少不易發現的隱患。對於比較操做(相等關係和不等關係),在javascript中實際上是有一套完善的機制的。本文依據ES5規範《ECMAScript Language Specification ECMA-262
5.1 Edition / June 2011》的11.8節和11.9節:
對javascript中比較操做相關內容進行系統總結。
嚴格相等
嚴格相等指「===」,它不容許比較雙方進行強制類型轉換。所以,問題考慮變得簡單,對於x === y
,javascript引擎在進行判斷時所遵循的算法以下:
寬鬆相等
寬鬆相等指「==」,它會對比較雙方進行隱式強制類型轉換。下面先根據ES5規範進行系統說明:
valueOf()
方法,若是有該方法且返回基本類型值,就使用該值進行強制類型轉換;若是不存在,就調用該對象上的toString()
方法,若是有該方法,就使用其返回值來進行強制類型轉換;若是這兩個方法都不存在,就產生TypeError錯誤。),返回 x == ToPrimitive(y) 的結果。注:針對以上10條有幾點注意事項:
1.對a,b強制按字符串string類型進行比較,可採用以下方法:"" + a == "" + b
2.對a,b強制按數字number類型進行比較,可採用以下方法:
+a == +b
3.對a,b強制按布爾值boolean類型進行比較,可採用以下方法:
!!a == !!b
4.相等比較操做有如下恆等性:
- A != B 等價於 !(A == B)
- A == B 等價於 B == A (除非A B有順序上的互相計算關係)
5.相等操做並非總具備傳遞性。
new String(「a」) == 「a」 和 「a」 == new String(「a」) 結果都返回true;
new String(「a」) == new String(「a」) 卻返回false。
由於new String(「a」)是一個對象,按照上述規則會被轉換爲」a」,所以相等;而new String(「a」) == new String(「a」),==左右兩邊是兩個不一樣的對象,在內存中位於不一樣地址,所以結果返回false。
因爲強制類型轉換的存在,寬鬆相等的狀況變得複雜,比較容易出現問題的有如下幾種:
更改內置原生原型後的相等比較
12345Number.prototype.valueOf = function(){ return 3;}new Number(2) == 3; // true
這只是爲了說明這種狀況的存在,應該不會有人這麼去改原型上的方法。
假值的相等比較
這部分應該是比較複雜的:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152"0" == null; //false"0" == undefined; //false"0" == false; //true"0" == NaN; //false"0" == 0; //true"0" == ""; //falsefalse == null; //falsefalse == undefined; //falsefalse == NaN; //falsefalse == 0; //truefalse == ""; //truefalse == []; //truefalse == {}; //false"" == null; //false"" == undefined; //false"" == NaN; //false"" == 0; //true"" == []; //true"" == {}; //false0 == null; //false0 == undefined; //false0 == NaN; //false0 == []; //true0 == {}; //false
解釋以下:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051"0" == null; //false:null轉換爲"null""0" == undefined; //false:undefined轉換爲"undefined""0" == false; //true:false轉換爲0;"0"轉換爲0"0" == NaN; //false:NaN轉換爲"NaN""0" == 0; //true:"0"轉換爲0"0" == ""; //false:都是字符串,值不一樣false == null; //false:false轉換爲0;null轉換爲"null",進而轉換爲數字,獲得NaNfalse == undefined; //false:false轉換爲0;undefined轉換爲"undefined",進而轉換爲數字,獲得NaNfalse == NaN; //false:false轉換爲0;與NaN不一樣false == 0; //true:false轉換爲0false == ""; //true:false轉換爲0;""轉換爲0false == []; //true:false轉換爲0;[]轉換爲0false == {}; //false:false轉換爲0;{}轉換爲NaN"" == null; //false:""轉換爲0;null轉換爲"null",進而轉換爲數字,獲得NaN"" == undefined; //false:""轉換爲0;undefined轉換爲"undefined",進而轉換爲數字,獲得NaN"" == NaN; //false:""轉換爲0;與NaN不一樣"" == 0; //true:""轉換爲0"" == []; //true:""轉換爲0;[]轉換爲0"" == {}; //false:""轉換爲0;{}轉換爲NaN0 == null; //false:null轉換爲"null",進而轉換爲數字,獲得NaN0 == undefined; //false:undefined轉換爲"undefined",進而轉換爲數字,獲得NaN0 == NaN; //false:0與NaN不一樣0 == []; //true:[]轉換爲00 == {}; //false:{}轉換爲NaN
一些極端狀況
a. [] == ![]; //true
[]被轉換爲0,![]被轉換爲false,進而被轉換爲0。
b. 2 == [2]; //true
[2]調用數組的valueOf()
方法,返回」2」,進而被轉換爲2。
c. 「」 == [null]; //true
[null]調用數組的valueOf()
方法,進而調用toString()
方法,返回」」。
一些選用的原則
typeof x == "function"
、typeof x != "undefined"
這樣的用法是徹底正確且安全的,開發中也經常使用。經典的相等比較關係圖
GitHub上有一個經典的比較關係圖,http://dorey.github.io/JavaScript-Equality-Table/,以表格的形式系統總結了寬鬆相等==,嚴格相等===,if()條件語句中使用不一樣數據類型對應的結果,頗有意義:
!= 和 !==
只要搞清楚上面詳細描述的==和===,對應取反便可。
> < >= <=
這些比較的基礎是 x < y:
x < y會返回true或者false或者undefined。若是返回undefined,說明x,y二者至少有一個是NaN。比較算法中須要使用一個布爾值的標記LeftFirst做爲參數。這個參數的做用是控制可能具備反作用的操做做用於x和y的順序。這個標誌是有必要的,由於在ECMAScript指定了從左到右的運算順序,LeftFirst的默認值是true,表示x的表達式是在y的表達式左邊的。若是LeftFirst值爲false,狀況相反,代表關於y的操做必須先於x進行。據此,比較操做規則以下:
- 若是LeftFirst值爲true:
1.1 ToPrimitive(x, hint Number)的結果記爲px
1.2 ToPrimitive(y, hint Number)的結果記爲py- 不然,運算順序改成從右向左:
2.1 ToPrimitive(y, hint Number)的結果記爲py
2.2 ToPrimitive(x, hint Number)的結果記爲px- 通過如上轉換,若是px和py至少有一個的類型不爲string:
3.1 ToNumber(px)的結果記爲nx
3.2 ToNumber(py)的結果記爲ny
3.3 若是nx是NaN,返回undefined
3.4 若是ny是NaN,返回undefined
3.5 若是nx和ny的值相同,返回false
3.6 若是nx是+0,ny是-0,返回false
3.7 若是nx是-0,ny是+0,返回false
3.8 若是nx是+Infinity,返回false
3.9 若是ny是+Infinity,返回true
3.10 若是ny是-Infinity,返回false
3.11 若是nx是-Infinity,返回true
3.12 若是nx的值小於ny,返回true;不然,返回false- 若是px和py都是string:
4.1 若是py是px的前綴,返回false
4.2 若是px是py的前綴,返回true
4.3 設置變量k,k表示px和py對應位上出現不一樣值時,位置的索引。
4.4 記px的位置k上的字母對應的字符編碼值爲m
4.5 記py的位置k上的字母對應的字符編碼值爲n
4.6 若是m < n,返回true;不然返回false
所以,> < >= <=就有以下的規則:
RelationalExpression > ShiftExpression
RelationalExpression < ShiftExpression
RelationalExpression >= ShiftExpression
RelationalExpression <= ShiftExpression
文章主要介紹了數組Array.prototype方法的使用,須要的朋友能夠參考下,若是你是大神,請直接無視。
在ES6即將普及的時代,我相信這些方法對FE開發者是很是實用的必備技能,接下來我將經過實例幫你們替換for循環大法,更高效的來操做數組。
一、indexOf
indexOf()方法返回在該數組中第一個找到的元素位置,若是它不存在則返回-1。
使用for:
使用indexOf:
二、lastindexOf
lastIndexOf() 方法返回在該數組中最後一個找到的元素位置,和 indexof相反。
三、every()
evety()但是檢測數組中的每一項是否符合條件
使用for:
使用every:
四、some()
some()能夠檢測數組中是否有某一項符合條件
使用for:
使用some:
五、 forEach()
forEach爲每一個元素執行對應的方法
使用for:
使用forEach():
forEach是用來替換for循環的
六、 map()
map()對數組的每一個元素進行必定操做(映射)後,會返回一個新的數組,
使用for:
使用map:
map()是處理服務器返回數據時是一個很是實用的函數。
forEach 與map的區別:
語法:forEach和map都支持2個參數:一個是回調函數(item,index,list)和上下文;
forEach:用來遍歷數組中的每一項;這個方法執行是沒有返回值的,對原來數組也沒有影響;數組中有幾項,那麼傳遞進去的匿名回調函數就須要執行幾回;每一次執行匿名函數的時候,還給其傳遞了三個參數值:數組中的當前項item,當前項的索引index,原始數組list;理論上這個方法是沒有返回值的,僅僅是遍歷數組中的每一項,不對原來數組進行修改;可是咱們能夠本身經過數組的索引來修改原來的數組;
forEach方法中的this是ary,匿名回調函數中的this默認是window;
map: 和forEach很是類似,都是用來遍歷數組中的每一項值的,用來遍歷數組中的每一項;
區別:map的回調函數中支持return返回值;return的是啥,至關於把數組中的這一項變爲啥(並不影響原來的數組,只是至關於把原數組克隆一份,把克隆的這一份的數組中的對應項改變了);
無論是forEach仍是map 都支持第二個參數值,第二個參數的意思是把匿名回調函數中的this進行修改。
七、 filter
該filter()方法建立一個新的匹配過濾條件的數組。
使用for:
使用 filter():
八、 reduce()
reduce()能夠實現一個累加器的功能,將數組的每一個值(從左到右)將其下降到一個值。 說實話剛開始理解這句話有點難度,它太抽象了。
場景: 統計一個數組中有多少個不重複的單詞
使用for:
讓我先解釋一下我本身對reduce的理解。reduce(callback, initialValue)會傳入兩個變量。回調函數(callback)和初始值(initialValue)。假設函數它有個傳入參數,prev和next,index和array。prev和next你是必需要了解的。通常來說prev是從數組中第一個元素開始的,next是第二個元素。可是當你傳入初始值(initialValue)後,第一個prev將是initivalValue,next將是數組中的第一個元素。
9.reduceRight()
reduceRight的語法以及回調函數的規則和reduce方法是同樣的,區別就是在與reduce是升序,即角標從0開始,而reduceRight是降序,即角標從arr.length-1開始。
方法可應用於字符串。
一個不會寫文章的程序猿,但願對你有幫助~