1、考察this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var length = 10; function fn() { console.log(this.length); } var obj = { length: 5, method: function(fn) { fn(); arguments[0](); } }; obj.method(fn, 1); |
輸出:10 2
第一次輸出10應該沒有問題。我們知道取物件屬於除了點操作符還可以用中括號,所以第二次執行時相當於arguments呼叫方法,this指向arguments,而這裡傳了兩個引數,故輸出arguments長度為2。
2、var和函式的提前宣告
1 2 3 4 5 6 7 8 |
function fn(a) { console.log(a); var a = 2; function a() {} console.log(a); } fn(1); |
輸出:function a() {} 2
我們知道var和function是會提前宣告的,而且function是優先於var宣告的(如果同時存在的話),所以提前宣告後輸出的a是個function,然後程式碼往下執行a進行重新賦值了,故第二次輸出是2。
3、區域性變數和全域性變數
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var f = true; if (f === true) { var a = 10; } function fn() { var b = 20; c = 30; } fn(); console.log(a); console.log(b); console.log(c); |
輸出:10 報錯 30
這是個我犯了很久的錯誤,很長一段時間我都以為{…}內的新宣告的變數是區域性變數,後來我才發現function內的新宣告的變數才是區域性變數,而沒有用var宣告的變數在哪裡都是全域性變數。再次提醒切記只有function(){}內新宣告的才能是區域性變數,while{…}、if{…}、for(..) 之內的都是全域性變數(除非本身包含在function內)。
4、變數隱式宣告
1 2 3 4 5 |
if('a' in window) { var a = 10; } alert(a); |
答案:10
前面我說過function和var會提前宣告,而其實{…}內的變數也會提前宣告。於是程式碼還沒執行前,a變數已經被宣告,於是 ‘a’ in window 返回true,a被賦值。
5、給基本型別資料新增屬性,不報錯,但取值時是undefined
1 2 3 4 5 6 7 |
var a = 10; a.pro = 10; console.log(a.pro + a); var s = 'hello'; s.pro = 'world'; console.log(s.pro + s); |
答案:NaN undefinedhello
給基本型別資料加屬性不報錯,但是引用的話返回undefined,10+undefined返回NaN,而undefined和string相加時轉變成了字串。
6、函式宣告優於變數宣告
1 2 3 |
console.log(typeof fn); function fn() {}; var fn; |
答案:function
因為函式宣告優於變數宣告。我們知道在程式碼逐行執行前,函式宣告和變數宣告會提前進行,而函式宣告又會優於變數宣告,這裡的優於可以理解為晚於變數宣告後,如果函式名和變數名相同,函式宣告就能覆蓋變數宣告。所以以上程式碼將函式宣告和變數宣告調換順序還是一樣結果。
7、判斷一個字串中出現次數最多的字元,並統計次數
- hash table方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
var s = 'aaabbbcccaaabbbaaa'; var obj = {}; var maxn = -1; var letter; for(var i = 0; i < s.length; i++) { if(obj[s[i]]) { obj[s[i]]++; if(obj[s[i]] > maxn) { maxn = obj[s[i]]; letter = s[i]; } } else { obj[s[i]] = 1; if(obj[s[i]] > maxn) { maxn = obj[s[i]]; letter = s[i]; } } } alert(letter + ': ' + maxn); |
- 正則方式:
1 2 3 4 5 6 7 8 9 10 |
var s = 'aaabbbcccaaabbbaaabbbbbbbbbb'; var a = s.split(''); a.sort(); s = a.join(''); var pattern = /(\w)\1*/g; var ans = s.match(pattern); ans.sort(function(a, b) { return a.length < b.length; });; console.log(ans[0][0] + ': ' + ans[0].length); |
8、經典閉包
1 2 3 4 5 6 7 8 |
<!-- 實現一段指令碼,使得點選對應連結alert出相應的編號 --> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <body> <a href='#'> 第一個連結 </a> </br> <a href='#'> 第二個連結 </a> </br> <a href='#'> 第三個連結 </a> </br> <a href='#'> 第四個連結 </a> </br> </body> |
- dom汙染法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!-- 實現一段指令碼,使得點選對應連結alert出相應的編號 --> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <body> <a href='#'> 第一個連結 </a> </br> <a href='#'> 第二個連結 </a> </br> <a href='#'> 第三個連結 </a> </br> <a href='#'> 第四個連結 </a> </br> <script type="text/javascript"> var lis = document.links; for(var i = 0, length = lis.length; i < length; i++) { lis[i].index = i; lis[i].onclick = function() { alert(this.index); }; } </script> </body> |
- 閉包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<!-- 實現一段指令碼,使得點選對應連結alert出相應的編號 --> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <body> <a href='#'> 第一個連結 </a> </br> <a href='#'> 第二個連結 </a> </br> <a href='#'> 第三個連結 </a> </br> <a href='#'> 第四個連結 </a> </br> <script type="text/javascript"> var lis = document.links; for(var i = 0, length = lis.length; i < length; i++) { (function(i) { lis[i].onclick = function() { alert(i + 1); }; })(i); } </script> </body> |
9、this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
function JSClass() { this.m_Text = 'division element'; this.m_Element = document.createElement('div'); this.m_Element.innerHTML = this.m_Text; this.m_Element.addEventListener('click', this.func); // this.m_Element.onclick = this.func; } JSClass.prototype.Render = function() { document.body.appendChild(this.m_Element); } JSClass.prototype.func = function() { alert(this.m_Text); }; var jc = new JSClass(); jc.Render(); // add div jc.func(); // 輸出 division element //click新增的div元素division element會輸出underfined,為什麼? |
答案:division element undefined
第一次輸出很好理解,第二次的話仔細看,this其實已經指向了this.m_Element,因為是this.m_Element呼叫的addEventListener函式,所以內部的this全指向它了。可以試著加上一行程式碼this.m_Element.m_Text = ‘hello world’,就會alert出hello world了。
10、split
請編寫一個JavaScript函式 parseQueryString,它的用途是把URL引數解析為一個物件,如: var url = “http://witmax.cn/index.php?key0=0&key1=1&key2=2″
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function parseQueryString(url) { var obj = {}; var a = url.split('?'); if(a === 1) return obj; var b = a[1].split('&'); for(var i = 0, length = b.length; i < length; i++) { var c = b[i].split('='); obj[c[0]] = c[1]; } return obj; } var url = 'http://witmax.cn/index.php?key0=0&key1=1&key2=2'; var obj = parseQueryString(url); console.log(obj.key0, obj.key1, obj.key2); // 0 1 2 |
如有意見建議歡迎交流斧正~