感覺這篇寫了很久....
都是上班無聊有想到才開來寫一下這樣
這篇也是我的學習心得之一,當然還有一些工作上常用到,但初學者可能也不太了的東西
因為本人學習還蠻不求甚解的,只要覺得好玩就會去玩一下
所以看到有一些用法很有趣,或學完之後會讓人覺得很厲害的話就會來學一下
以下就列出這些進階用法或小常識
但對一些不是初學者的人可能會覺得是個P,請多多包涵
因為實在寫得有點長,下一篇放在第二篇好了
利用 && 與 || 的特性
一般來說 && 與 || 使用來做邏輯運算,但它回傳的不是 true or false
&& 代表如果左邊的運算元成立,就會檢查右邊,右邊也成立的話就會返回右邊的運算元
|| 則是只要左邊成立就忽略右方運算元,返回左邊的運算元
ex :
0 && 'ok';
// return 0;
'left' && 'right';
// return 'right';
'left' || 'right';
// return 'left'
所以可以利用這個特性來給予初始值或是定義
ex :
var fun = fun || {};
如上,有 fun 物件就使用 fun 物件,沒有就給一個空物件
如果有需要直接將物件轉為數字,可以使用 valueOf 方法
var car = {
color: 'red',
valueOf: function () {
return 100
}
}
alert(car + 1);
// 101
要直接將物件輸出成字串用 toString 方法
var car = {
color: 'red',
valueOf: function () {
return 100
}, toString: function () {
return "123"
}
}
alert("1" + car)
// "1123"
合併物件與預設值
此例子常用在有多種輸入參數,且有提供預設值的情況
以下取網路上的例子
function doSome(option) {
return {
x : option.x || 1,
y : option.y || 2,
z : option.z || 3
};
}
var processed = doSome({
x : 10,
y : 20
});
function log(obj) {
for(var p in obj) {
console.log(p + ': ' + obj[p]);
}
}
log(processed);
函數的輸入參數
使用函數時的輸入參數,不一定要跟函數定義的參數個數一致
缺少的參數就是 undefined
ex :
function add(a, b, c) {
//這裡利用了上面講過的 || 特性給予初始值
a = a || 0; b = b || 0; c = c || 0;
return a + b + c;
}
add(10); // 10
add(10,2); // 12
add(10,2,4); // 16
也可以多給參數
多出來的參數則可以使用函數內自行產生的 arguments 去取得
arguments 中會有所有參數的資訊
ex :
function add(a, b, c) {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
add(10,2,4,5,6); // 27
陣列的操作方法
可以看之前寫的這篇 Javascript 常用的陣列操作指南
善用callback 處理執行順序
一般正常來講函數先呼叫的會先執行
拿網路上的範例來改一下,這是最一般的情況
function a() {
console.log('a');
}
function b() {
console.log('b');
}
a();
b();
結果為 :
==============
a
b
但! 如果 a() 執行時間比 b() 來的久
或是 a() 裡面根本就是個 ajax,b() 都跑完了a() 結果還沒回來
例如這樣 :
下面用 setTimeout 模擬函數 a() 需要長時間執行
function a() {
setTimeout(function () {
console.log('a');
},1000)
}
function b() {
console.log('b');
}
a();
b();
結果為 :
==============
b
a
又例如最常用的 ajax ,a 雖然先執行,但它去了 test2.html 還沒回來咧
所以雖然先呼叫,但是結果卻比 b() 還晚返回
function a() {
$.get("test2.html", function () {
alert('a');
});
}
function b() {
alert('b');
}
a();
b();
結果為 :
==============
b
a
以上的問題可以用 callback 來克服,callback 也大量運用在node.js之中
有寫過node.js的人應該會覺得很親切
由於函數的輸入參數可以是另一個函數,回傳值也可以是函數
所以用這個特性把 b() 傳進去 a() 就好了,待 a() 執行完後再執行 b() 就是正確順序
ex :
function a(callback) {
setTimeout(function () {
console.log('a');
callback();
}, 1000)
}
function b() {
console.log('b');
}
// 把 b() 傳入 a()
a(b);
結果為 :
a
b
如果是 ajax 也一樣
function a(callback) {
$.get("test2.html", function () {
alert('a');
callback()
});
}
function b() {
alert('b');
}
// 把 b() 傳入 a()
a(b);
結果為 :
a
b
減少使用全域變數
減少使用全域變數可以提高程式碼品質且更好維護
當頁面有一堆全域變數會變得很難維護
因為全域變數有可能會跟第三方套件或頁面上其他變數混用到
你可以在頁面上用一個全域的物件作為命名空間,用它來管理你的全域變數
例如這樣 :
var grobal = grobal || {};
grobal = {
changeNum: 0,
result: "",
changeControl: []
}
使用時只要這樣就好了
console.log(grobal .changeNum); // 0
給值
grobal .changeNum = 3;
除此之外也可使用立即函數來減少全域變數的產生
立即函數裡面就像是個沙盒
在函數中建立變數,可以避免該變數洩漏到全域變數作用域中
可以參考之前提過的javascript函數的多種寫法
Javascript 開發學習心得 - 函數的多種寫法與應用限制
用法如下 :
var a = (function(){
var str;
........
//return str
})();
用一個括號包住一個匿名函數 function(){}
在外面的最後一個括號 (); 則代表立即執行
立即函數除了可返回值,當然也可輸入參數
你如果常直接打開jQuery 第三方套件的話,有很大機率會看到這樣寫
(function($){
})(jQuery);
這就是立即函數,但是傳入了jQuery物件
Javascript 該放置的位置,與網頁載入阻塞(blocking)問題
script :
網頁解析的時候如果遇到 <script>標籤時,會暫停網頁元素下載,先執行<script>中的程式碼
所以如果你在網頁的<head>之前放了一堆內嵌的 Javascript 的話....(不引用js的方式)
就會讓User看到網頁一開始載入是一片空白 (因為在執行script)
等待執行完之後才會繼續載入下方的 css 圖片與網頁元素
因此最好是用引用外部js的方式來載入,會比直接寫在頁面上好很多
以上指的是舊版的瀏覽器 (IE8以下)
新版的瀏覽器已經可以同時下載js與元素,但還是會有阻塞情形
如下面搭配css的方式
css :
如果引用css的下方放入內嵌的 Javascript 的話 (不引用js直接寫在頁面上的方式)
ex :
<link href="............/style.css" rel="nofollow ugc noreferrer noopener" rel="stylesheet">
<script>
....................
</script>
就會發生阻塞情形 (圖片取自網路資料)
如上圖會等 css 載入完之後才處理 js
因此無論如何 js 盡量不要直接寫在網頁之中,尤其又放置於 head css 之後
盡量使用外部載入 js 的方式
ex : <script src="Js/myfun.js"></script>
可以參考這個網站所做的測試
http://www.cnblogs.com/shinnyChen/p/3762704.html
再來新版的瀏覽器中可以使用 defer、async
來讓有支援的瀏覽器利用非同步下載 js,避免阻塞問題
ex :
<script src="test.js" defer></script>
<script src="test.js" async></script>
defer (html4),不停止網頁繪製,JavaScript的下載會同時進行,等待網頁繪製完成會再執行JavaScript。
async (html5),不停止網頁繪製,JavaScript的下載會同時進行,當JavaScript下載完成後,再停止網頁繪製並執行JavaScript,等待執行完成後再繼續網頁繪製。
結論,最完美的放置位置如下,上面內容不想看就直接看下面就好了 :
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<link href="Css/css.css" rel="stylesheet" />
</head>
<body>
<div>
...................
網頁內容
...................
</div>
<script src="Js/myfun.js" type="text/javascript" defer></script>
</body>
</html>