來源:BAT及各大互聯網公司2014前端筆試面試題--JavaScript篇
1、JavaScript是一門什么樣的語言,它有哪些特點?
JavaScript是一種動態語言
所謂的動態類型語言,意思就是類型的檢查是在運行時做的。
而靜態類型語言的類型判斷是在運行前判斷(如編譯階段),比如C#、java就是靜態類型語言,靜態類型語言為了達到多態會采取一些類型鑒別手段,如繼承、接口,而動態類型語言卻不需要,所以一般動態語言都會采用dynamic typing,常出現于腳本語言中.
腳本語言是一種解釋性的語言,例如Python、vbscript,javascript,installshield script,ActionScript等等,它不象c\c++等可以編譯成二進制代碼,以可執行文件的形式存在,腳本語言不需要編譯,可以直接用,由解釋器來負責解釋。
弱類型、事件驅動(參考:JavaScript特點、優缺點及常用框架)
2、JavaScript的數據類型都有什么?
基本數據類型:String,Boolean,Number,Undefined, Null。
null表示"沒有對象",即該處不應該有值。典型用法是:
(1) 作為函數的參數,表示該函數的參數不是對象。
(2) 作為對象原型鏈的終點。
Object.getPrototypeOf(Object.prototype)// null
獲取元素時,如果當前文檔中特定元素不存在則返回null.
undefined表示"缺少值",就是此處應該有一個值,但是還沒有定義。典型用法是:
(1)變量被聲明了,但沒有賦值時,就等于undefined。
(2) 調用函數時,應該提供的參數沒有提供,該參數等于undefined。
(3)對象沒有賦值的屬性,該屬性的值為undefined。
(4)函數沒有返回值時,默認返回undefined。
引用數據類型:Object(Array,Date,RegExp,Function)
那么問題來了,如何判斷某變量是否為數組數據類型?(參考:http://www.cnblogs.com/SanMaoSpace/archive/2013/06/14/3136774.html)
通過調用Object上的方法
function isArrayFn(value){
if (typeof Array.isArray === "function") {
return Array.isArray(value);
}else{
return Object.prototype.toString.call(value) === "[object Array]";
}
}
3、已知ID的Input輸入框,希望獲取這個輸入框的輸入值,怎么做?(不使用第三方框架)
document.getElementById(“ID”).value
4、希望獲取到頁面中所有的checkbox怎么做?(不使用第三方框架)
var domList = document.getElementsByTagName(‘input’)
var checkBoxList = [];
var len = domList.length; //緩存到局部變量
while (len--) { //使用while的效率會比for循環更高
if (domList[len].type == ‘checkbox’) {
checkBoxList.push(domList[len]);
}
}```
###5、設置一個已知ID的DIV的html內容為xxxx,字體顏色設置為黑色(不使用第三方框架)
var dom = document.getElementById(“ID”);
dom.innerHTML = “xxxx”;
dom.style.color = “#000”;
###6、當一個DOM節點被點擊時候,我們希望能夠執行一個函數,應該怎么做?
直接在DOM里綁定事件:`<div onclick=”test()”></div>`
在JS里通過onclick綁定:`xxx.onclick = test `
通過事件添加進行綁定:`addEventListener(xxx, ‘click’, test) `
**那么問題來了,Javascript的事件流模型都有什么?**
“事件冒泡”:事件開始由最具體的元素接受,然后逐級向上傳播
“事件捕捉”:事件由最不具體的節點先接收,然后逐級向下,一直到最具體的
“DOM事件流”:三個階段:事件捕捉,目標階段,事件冒泡
>IE9、Safari、Chrome、Firefox和Opera9.5及更高版本都會在捕獲階段觸發事件對象上的事件,就是**有兩個機會在目標對象上面操作事件**。(盡管DOM2級事件規范明確要求捕獲階段不涉及事件目標)。(高程p348)
html
<div id="outer">outer
<div id="inner">inner</div>
</div>
js
var outerDiv = document.querySelector("#outer");
var innerDiv = document.querySelector("#inner");
innerDiv.addEventListener("click", function(e) {
console.log("inner");
})
outerDiv.addEventListener("click", function(e) {
console.log("outer");
}, true)
//默認為false,指定outer上的事件 在冒泡階段觸發,點擊inner,輸出inner,outer
//為true,指定outer上的事件在捕獲階段觸發,點擊inner,輸出outer,inner
//只點擊outer非inner的部分,當然只觸發outer的事件
//inner上的事件就是在目標階段觸發
###7、什么是Ajax和JSON,它們的優缺點。
Ajax是異步JavaScript和XML,用于在Web頁面中實現異步數據交互。
**優點:**
可以使得頁面不重載全部內容的情況下加載局部內容,降低數據傳輸量
避免用戶不斷刷新或者跳轉頁面,提高用戶體驗
**缺點:**
對搜索引擎不友好(
要實現ajax下的前后退功能成本較大
可能造成請求數的增加
跨域問題限制
JSON是一種輕量級的數據交換格式,ECMA的一個子集
優點:輕量級、易于人的閱讀和編寫,便于機器(JavaScript)解析,支持復合數據類型(數組、對象、字符串、數字)
###8、看下列代碼輸出為何?解釋原因。
var a;
alert(typeof a); // undefined
alert(b); // 報錯
typeof(null)//"object"
解釋:Undefined是一個只有一個值的數據類型,這個值就是“undefined”,在使用var聲明變量但并未對其賦值進行初始化時,這個變量的值就是undefined。而b由于未聲明將報錯。注意未申明的變量和聲明了未賦值的是不一樣的。
null是一個只有一個值的數據類型,這個值就是null。表示一個空指針對象,所以用typeof檢測會返回”object”。
###9、看下列代碼,輸出什么?解釋原因。
var undefined;
undefined == null; // true
1 == true; // true
2 == true; // false
0 == false; // true
0 == ''; // true
NaN == NaN; // false
[] == false; // true
[] == ![]; // true
undefined與null相等,但不恒等(===)
一個是number一個是string時,會嘗試將string轉換為number
嘗試將boolean轉換為number,0或1
嘗試將Object轉換成number或string,取決于另外一個對比量的類型
所以,對于0、空字符串的判斷,建議使用 “===” ?!?==”會先判斷兩邊的值類型,類型不匹配時為false。
那么問題來了,看下面的代碼,輸出什么,foo的類型為什么?
var foo = "11"+2-"1";
console.log(foo);
console.log(typeof foo);
執行完后foo的值為111,foo的類型為Number。
var foo = "11"+2+"1"; //體會加一個字符串'1' 和 減去一個字符串'1'的不同
console.log(foo);
console.log(typeof foo);
執行完后foo的值為1121(此處是字符串拼接),foo的類型為String。
###10、看代碼給答案。
var a = new Object();
a.value = 1;
b = a;
b.value = 2;
alert(a.value);
答案:2(考察引用數據類型細節)
###11、已知數組var stringArray = [“This”, “is”, “Baidu”, “Campus”],Alert出”This is Baidu Campus”。
答案:alert(stringArray.join(" "))
那么問題來了,已知有字符串foo="get-element-by-id",寫一個function將其轉化成駝峰表示法"getElementById"。
function combo(msg){
var arr = msg.split("-");
var len = arr.length; //將arr.length存儲在一個局部變量可以提高for循環效率
for(var i=1;i<len;i++){
arr[i]=arr[i].charAt(0).toUpperCase()+arr[i].substr(1,arr[i].length-1);
}
msg=arr.join("");
return msg;
}
(考察基礎API)
###12、var numberArray = [3,6,2,4,1,5]; (考察基礎API)
1) 實現對該數組的倒排,輸出[5,1,4,2,6,3]
2) 實現對該數組的降序排列,輸出[6,5,4,3,2,1]
var numberArray = [3,6,2,4,1,5];
numberArray.reverse(); // 5,1,4,2,6,3
numberArray.sort(function(a,b){ //6,5,4,3,2,1
return b-a;
})
>*arr*.sort([*compareFunction*])
如果指明了 compareFunction
,那么數組會按照調用該函數的返回值排序。記 a 和 b 是兩個將要被比較的元素:
如果 compareFunction(a, b)
小于 0 ,那么 a 會被排列到 b 之前;
如果 compareFunction(a, b)
等于 0 , a 和 b 的相對位置不變。備注: ECMAScript 標準并不保證這一行為,而且也不是所有瀏覽器都會遵守(例如 Mozilla 在 2003 年之前的版本);
如果 compareFunction(a, b)
大于 0 , b 會被排列到 a 之前。
compareFunction(a, b)
必須總是對相同的輸入返回相同的比較結果,否則排序的結果將是不確定的。
###13、輸出今天的日期,以YYYY-MM-DD的方式,比如今天是2014年9月26日,則輸出2014-09-26
var d = new Date();
// 獲取年,getFullYear()返回4位的數字,注意是FullYear
var year = d.getFullYear();
// 獲取月,月份比較特殊,0是1月,11是12月
var month = d.getMonth() + 1;
// 變成兩位
month = month < 10 ? '0' + month : month;
// 獲取日
var day = d.getDate();
day = day < 10 ? '0' + day : day;
###14、將字符串`<tr><td>{$id}</td><td>{$id}</td><td>{$id}_{$name}</td></tr>`,{id}替換成10,{name}替換成Tony (使用正則表達式)
注意轉義字符
`"<tr><td>{$id}</td><td>{$id}</td><td>{$id}_{$name}</td></tr>".replace(/{\$id}/g, '10').replace(/{\$name}/g, 'Tony')`
###15、為了保證頁面輸出安全,我們經常需要對一些特殊的字符進行轉義,請寫一個函數escapeHtml,將<, >, &, “進行轉義
function escapeHtml(str) {
return str.replace(/[<>”&]/g, function(match) {
switch (match) {
case “<”:
return “<”;
case “>”:
return “>”;
case “&”:
return “&”;
case “\””:
return “"”;
}
});
}
###16? 看下列代碼,將會輸出什么?(變量聲明提升)**
var foo = 1;
function(){
console.log(foo);
var foo = 2;
console.log(foo);
}
###17?用js實現隨機選取10--100之間的10個數字,存入一個數組,并排序。
* 生成[min,max]的隨機數
function getRandom(min, max){
var ran = Math.random();
console.log(ran);//[0,1)
//[min, max)的小數
//return ran(max-min) + min;
//[min,max)的整數
//return Math.floor(ran(max-min)) + min;
//[min, max]的整數,進行了向下取整
return Math.floor(ran*(max-min+1)) + min;
// return Math.round((Math.random() * (max - min) + min) * 10) / 10
}
console.log(getRandom(2,6))
* 3.47->3.5
```Math.round(num*10)/10```
###18?把兩個數組合并,并刪除第二個元素。
字符串沒有splice方法,只有slice,數組有splice
concat()。字符串和數組都有
var a1 = [1,2,3]
var a2 = [4,5,6]
var a3 = a1.concat(a2);
a3.splice(1,1)
console.log(a3);
###19?怎樣添加、移除、移動、復制、創建和查找節點(原生JS,實在基礎,沒細寫每一步)**
* 1)創建新節點
createDocumentFragment() //創建一個DOM片段
createElement() //創建一個具體的元素
createTextNode() //創建一個文本節點
* 2)添加、移除、替換、插入
appendChild() //添加
removeChild() //移除
replaceChild() //替換
insertBefore() //插入
* 3)查找
getElementsByTagName() //通過標簽名稱
getElementsByName() //通過元素的Name屬性的值
getElementById() //通過元素Id,唯一性
###20?有這樣一個URL:http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e,請寫一段JS程序提取URL中的各個GET參數(參數名和參數個數不確定),將其按key-value形式返回到一個json結構中,如{a:'1', b:'2', c:'', d:'xxx', e:undefined}。
function serilizeUrl(url) {
var result = {};
url = url.split("?")[1];
var map = url.split("&");
for(var i = 0, len = map.length; i < len; i++) {
result[map[i].split("=")[0]] = map[i].split("=")[1];
}
return result;
}
###21?正則表達式構造函數var reg=new RegExp("xxx")與正則表達字面量var reg=//有什么不同?匹配郵箱的正則表達式?
當使用RegExp()構造函數的時候,不僅需要轉義引號(即\"表示"),并且還需要雙反斜杠(即\\表示一個\)。**使用正則表達字面量的效率更高。 **
**郵箱**的正則匹配:
var regMail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/;
###22?看下面代碼,給出輸出結果。
for(var i=1;i<=3;i++){
setTimeout(function(){
console.log(i);
},0);
};
改進:
for(var i=1;i<=3;i++){
setTimeout(function(a){
console.log(a);
}(i),0);
};
###23?寫一個function,清除字符串前后的空格。(兼容所有瀏覽器)
str.replace(/^\s+/,"").replace(/\s+$/,"")
或
str.replace(/^\s+|\s+$/g,"")
###24?Javascript中callee和caller的作用?
**caller: 返回一個對函數的引用,該函數調用了當前函數。**
>對于函數來說,**caller 屬性只有在函數執行時才有定義**。 如果函數是由 Javascript 程序的頂層調用的,那么 caller 包含的就是 null 。(fn.caller), 各下面一樣為了避免強耦合,通常會這樣調用:arguments.callee.caller;
**callee: 返回正被執行的 Function 對象,也就是所指定的 Function 對象的正文。**( arguments.callee)
>callee 屬性是 arguments 對象的一個成員,它表示對函數對象本身的引用,這有利于匿名函數的遞歸或者保證函數的封裝性,例如下邊示例的遞歸計算1到n的自然數之和。而該屬性僅當相關函數正在執行時才可用。還有需要注意的是callee擁有length屬性,這個屬性有時候用于驗證還是比較好的。arguments.length是實參長度,arguments.callee.length是形參長度,由此可以判斷調用時形參長度是否和實參長度一致。
callee實現階乘: 使用callee不用fn就是為了避免強耦合
比如 var fn2 = fn; fn= function()(){};fn2(100)會找不到原來的fn
function fn(n){
if(n <= 1){
return 1
}
return n * arguments.callee(n-1)
}
斐波那契數列
var result=[];
function fn(n){ //典型的斐波那契數列
if(n==1){
return 1;
}else if(n==2){
return 1;
}else{
if(result[n]){
return result[n];
}else{
//argument.callee()表示fn()
result[n]=arguments.callee(n-1)+arguments.callee(n-2);
return result[n];
}
}
}