閱讀目錄
本篇收錄了一些面試中經常會遇到的經典面試題以及自己面試過程中遇到的一些問題,並且都給出了我在網上收集的答案。馬上就要過春節了,開年就是嶄新的一年,相信很多的前端開發者會有一些跳槽的悸動,通過對本篇知識的整理以及經驗的總結,希望能幫到更多的前端面試者。(如有錯誤或更好的答案,歡迎指正,水平有限,望各位不吝指教。:)
另外,宣傳一下自己發布不久的一個前端vue的項目:基於vue2.0 +vuex+ element-ui后台管理系統。希望有興趣的同學,可以一起共同學習。
javascript:
JavaScript中如何檢測一個變量是一個String類型?請寫出函數實現
方法1、
function isString(obj){ return typeof(obj) === "string"? true: false; // returntypeof obj === "string"? true: false; }
方法2、
function isString(obj){ return obj.constructor === String? true: false; }
方法3.
function isString(obj){ return Object.prototype.toString.call(obj) === "[object String]"?true:false; } 如: var isstring = isString('xiaoming'); console.log(isstring); // true
請用js去除字符串空格?
方法一:使用replace正則匹配的方法
去除所有空格: str = str.replace(/\s*/g,"");
去除兩頭空格: str = str.replace(/^\s*|\s*$/g,"");
去除左空格: str = str.replace( /^\s*/, “”);
去除右空格: str = str.replace(/(\s*$)/g, "");
str為要去除空格的字符串,實例如下:
var str = " 23 23 "; var str2 = str.replace(/\s*/g,""); console.log(str2); // 2323
方法二:使用str.trim()方法
str.trim()局限性:無法去除中間的空格,實例如下:
var str = " xiao ming "; var str2 = str.trim(); console.log(str2); //xiao ming
同理,str.trimLeft(),str.trimRight()分別用於去除字符串左右空格。
方法三:使用jquery,$.trim(str)方法
$.trim(str)局限性:無法去除中間的空格,實例如下:
var str = " xiao ming "; var str2 = $.trim(str) console.log(str2); // xiao ming
你如何獲取瀏覽器URL中查詢字符串中的參數?
測試地址為:http://www.runoob.com/jquery/misc-trim.html?channelid=12333&name=xiaoming&age=23
實例如下:
function showWindowHref(){ var sHref = window.location.href; var args = sHref.split('?'); if(args[0] == sHref){ return ""; } var arr = args[1].split('&'); var obj = {}; for(var i = 0;i< arr.length;i++){ var arg = arr[i].split('='); obj[arg[0]] = arg[1]; } return obj; } var href = showWindowHref(); // obj console.log(href['name']); // xiaoming
js 字符串操作函數
我這里只是列舉了常用的字符串函數,具體使用方法,請參考網址。
-
concat() – 將兩個或多個字符的文本組合起來,返回一個新的字符串。
-
indexOf() – 返回字符串中一個子串第一處出現的索引。如果沒有匹配項,返回 -1 。
-
charAt() – 返回指定位置的字符。
-
lastIndexOf() – 返回字符串中一個子串最后一處出現的索引,如果沒有匹配項,返回 -1 。
-
match() – 檢查一個字符串是否匹配一個正則表達式。
-
substr() 函數 -- 返回從string的startPos位置,長度為length的字符串
-
substring() – 返回字符串的一個子串。傳入參數是起始位置和結束位置。
-
slice() – 提取字符串的一部分,並返回一個新字符串。
-
replace() – 用來查找匹配一個正則表達式的字符串,然后使用新字符串代替匹配的字符串。
-
search() – 執行一個正則表達式匹配查找。如果查找成功,返回字符串中匹配的索引值。否則返回 -1 。
-
split() – 通過將字符串划分成子串,將一個字符串做成一個字符串數組。
-
length – 返回字符串的長度,所謂字符串的長度是指其包含的字符的個數。
-
toLowerCase() – 將整個字符串轉成小寫字母。
-
toUpperCase() – 將整個字符串轉成大寫字母。
怎樣添加、移除、移動、復制、創建和查找節點?
1)創建新節點
createDocumentFragment() //創建一個DOM片段
createElement() //創建一個具體的元素
createTextNode() //創建一個文本節點
2)添加、移除、替換、插入
appendChild() //添加
removeChild() //移除
replaceChild() //替換
insertBefore() //插入
3)查找
getElementsByTagName() //通過標簽名稱
getElementsByName() //通過元素的Name屬性的值
getElementById() //通過元素Id,唯一性
寫出3個使用this的典型應用
(1)、在html元素事件屬性中使用,如:
<input type=”button” onclick=”showInfo(this);” value=”點擊一下”/>
(2)、構造函數
function Animal(name, color) { this.name = name; this.color = color; }
(3)、input點擊,獲取值
<input type="button" id="text" value="點擊一下" /> <script type="text/javascript"> var btn = document.getElementById("text"); btn.onclick = function() { alert(this.value); //此處的this是按鈕元素 } </script>
(4)、apply()/call()求數組最值
var numbers = [5, 458 , 120 , -215 ]; var maxInNumbers = Math.max.apply(this, numbers); console.log(maxInNumbers); // 458 var maxInNumbers = Math.max.call(this,5, 458 , 120 , -215); console.log(maxInNumbers); // 458
比較typeof與instanceof?
相同點:JavaScript 中 typeof 和 instanceof 常用來判斷一個變量是否為空,或者是什么類型的。
typeof的定義和用法:返回值是一個字符串,用來說明變量的數據類型。
細節:
(1)、typeof 一般只能返回如下幾個結果:number,boolean,string,function,object,undefined。
(2)、typeof 來獲取一個變量是否存在,如 if(typeof a!="undefined"){alert("ok")},而不要去使用 if(a) 因為如果 a 不存在(未聲明)則會出錯。
(3)、對於 Array,Null 等特殊對象使用 typeof 一律返回 object,這正是 typeof 的局限性。
Instanceof定義和用法:instanceof 用於判斷一個變量是否屬於某個對象的實例。
實例演示:
a instanceof b?alert("true"):alert("false"); //a是b的實例?真:假
var a = new Array(); alert(a instanceof Array); // true
alert(a instanceof Object) // true
如上,會返回 true,同時 alert(a instanceof Object) 也會返回 true;這是因為 Array 是 object 的子類。
function test(){}; var a = new test(); alert(a instanceof test) // true
細節:
(1)、如下,得到的結果為‘N’,這里的 instanceof 測試的 object 是指 js 語法中的 object,不是指 dom 模型對象。
if (window instanceof Object){ alert('Y')} else { alert('N');} // 'N'
如何理解閉包?
1、定義和用法:當一個函數的返回值是另外一個函數,而返回的那個函數如果調用了其父函數內部的其它變量,如果返回的這個函數在外部被執行,就產生了閉包。
2、表現形式:使函數外部能夠調用函數內部定義的變量。
3、實例如下:
(1)、根據作用域鏈的規則,底層作用域沒有聲明的變量,會向上一級找,找到就返回,沒找到就一直找,直到window的變量,沒有就返回undefined。這里明顯count 是函數內部的flag2 的那個count 。
var count=10; //全局作用域 標記為flag1 function add(){ var count=0; //函數全局作用域 標記為flag2 return function(){ count+=1; //函數的內部作用域 alert(count); } } var s = add() s();//輸出1 s();//輸出2
4、變量的作用域
要理解閉包,首先必須理解Javascript特殊的變量作用域。
變量的作用域分類:全局變量和局部變量。
特點:
1、函數內部可以讀取函數外部的全局變量;在函數外部無法讀取函數內的局部變量。
2、函數內部聲明變量的時候,一定要使用var命令。如果不用的話,你實際上聲明了一個全局變量!
5、使用閉包的注意點
1)濫用閉包,會造成內存泄漏:由於閉包會使得函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導致內存泄露。解決方法是,在退出函數之前,將不使用的局部變量全部刪除。
2)會改變父函數內部變量的值。所以,如果你把父函數當作對象(object)使用,把閉包當作它的公用方法(Public Method),把內部變量當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數內部變量的值。
什么是跨域?跨域請求資源的方法有哪些?
1、什么是跨域?
由於瀏覽器同源策略,凡是發送請求url的協議、域名、端口三者之間任意一與當前頁面地址不同即為跨域。存在跨域的情況:
-
網絡協議不同,如http協議訪問https協議。
-
端口不同,如80端口訪問8080端口。
-
域名不同,如qianduanblog.com訪問baidu.com。
-
子域名不同,如abc.qianduanblog.com訪問def.qianduanblog.com。
-
域名和域名對應ip,如www.a.com訪問20.205.28.90.
2、跨域請求資源的方法:
(1)、porxy代理
定義和用法:proxy代理用於將請求發送給后台服務器,通過服務器來發送請求,然后將請求的結果傳遞給前端。
實現方法:通過nginx代理;
注意點:1、如果你代理的是https協議的請求,那么你的proxy首先需要信任該證書(尤其是自定義證書)或者忽略證書檢查,否則你的請求無法成功。
(2)、CORS 【Cross-Origin Resource Sharing】
定義和用法:是現代瀏覽器支持跨域資源請求的一種最常用的方式。
使用方法:一般需要后端人員在處理請求數據的時候,添加允許跨域的相關操作。如下:
res.writeHead(200, { "Content-Type": "text/html; charset=UTF-8", "Access-Control-Allow-Origin":'http://localhost', 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'X-Requested-With, Content-Type' });
(3)、jsonp
定義和用法:通過動態插入一個script標簽。瀏覽器對script的資源引用沒有同源限制,同時資源加載到頁面后會立即執行(沒有阻塞的情況下)。
特點:通過情況下,通過動態創建script來讀取他域的動態資源,獲取的數據一般為json格式。
實例如下:
<script> function testjsonp(data) { console.log(data.name); // 獲取返回的結果 } </script> <script> var _script = document.createElement('script'); _script.type = "text/javascript"; _script.src = "http://localhost:8888/jsonp?callback=testjsonp"; document.head.appendChild(_script); </script>
缺點:
1、這種方式無法發送post請求(這里)
2、另外要確定jsonp的請求是否失敗並不容易,大多數框架的實現都是結合超時時間來判定。
談談垃圾回收機制方式及內存管理
回收機制方式
1、定義和用法:垃圾回收機制(GC:Garbage Collection),執行環境負責管理代碼執行過程中使用的內存。
2、原理:垃圾收集器會定期(周期性)找出那些不在繼續使用的變量,然后釋放其內存。但是這個過程不是實時的,因為其開銷比較大,所以垃圾回收器會按照固定的時間間隔周期性的執行。
3、實例如下:
function fn1() { var obj = {name: 'hanzichi', age: 10}; } function fn2() { var obj = {name:'hanzichi', age: 10}; return obj; } var a = fn1(); var b = fn2();
fn1中定義的obj為局部變量,而當調用結束后,出了fn1的環境,那么該塊內存會被js引擎中的垃圾回收器自動釋放;在fn2被調用的過程中,返回的對象被全局變量b所指向,所以該塊內存並不會被釋放。
4、垃圾回收策略:標記清除(較為常用)和引用計數。
標記清除:
定義和用法:當變量進入環境時,將變量標記"進入環境",當變量離開環境時,標記為:"離開環境"。某一個時刻,垃圾回收器會過濾掉環境中的變量,以及被環境變量引用的變量,剩下的就是被視為准備回收的變量。
到目前為止,IE、Firefox、Opera、Chrome、Safari的js實現使用的都是標記清除的垃圾回收策略或類似的策略,只不過垃圾收集的時間間隔互不相同。
引用計數:
定義和用法:引用計數是跟蹤記錄每個值被引用的次數。
基本原理:就是變量的引用次數,被引用一次則加1,當這個引用計數為0時,被視為准備回收的對象。
內存管理
1、什么時候觸發垃圾回收?
垃圾回收器周期性運行,如果分配的內存非常多,那么回收工作也會很艱巨,確定垃圾回收時間間隔就變成了一個值得思考的問題。
IE6的垃圾回收是根據內存分配量運行的,當環境中的變量,對象,字符串達到一定數量時觸發垃圾回收。垃圾回收器一直處於工作狀態,嚴重影響瀏覽器性能。
IE7中,垃圾回收器會根據內存分配量與程序占用內存的比例進行動態調整,開始回收工作。
2、合理的GC方案:(1)、遍歷所有可訪問的對象; (2)、回收已不可訪問的對象。
3、GC缺陷:(1)、停止響應其他操作;
4、GC優化策略:(1)、分代回收(Generation GC);(2)、增量GC
開發過程中遇到的內存泄露情況,如何解決的?
1、定義和用法:
內存泄露是指一塊被分配的內存既不能使用,又不能回收,直到瀏覽器進程結束。C#和Java等語言采用了自動垃圾回收方法管理內存,幾乎不會發生內存泄露。我們知道,瀏覽器中也是采用自動垃圾回收方法管理內存,但由於瀏覽器垃圾回收方法有bug,會產生內存泄露。
2、內存泄露的幾種情況:
(1)、當頁面中元素被移除或替換時,若元素綁定的事件仍沒被移除,在IE中不會作出恰當處理,此時要先手工移除事件,不然會存在內存泄露。
實例如下:
<div id="myDiv"> <input type="button" value="Click me" id="myBtn"> </div> <script type="text/javascript"> var btn = document.getElementById("myBtn"); btn.onclick = function(){ document.getElementById("myDiv").innerHTML = "Processing..."; } </script>
解決方法如下:
<div id="myDiv"> <input type="button" value="Click me" id="myBtn"> </div> <script type="text/javascript"> var btn = document.getElementById("myBtn"); btn.onclick = function(){ btn.onclick = null; document.getElementById("myDiv").innerHTML = "Processing..."; } </script>
function bindEvent(){ var obj=document.createElement("XXX"); obj.onclick=function(){ //Even if it's a empty function } }
解決方法如下:
function bindEvent(){ var obj=document.createElement("XXX"); obj.onclick=function(){ //Even if it's a empty function } obj=null; }
javascript面向對象中繼承實現?
面向對象的基本特征有:封閉、繼承、多態。
在JavaScript中實現繼承的方法:
1. 原型鏈(prototype chaining)
2. call()/apply()
3. 混合方式(prototype和call()/apply()結合)
4. 對象冒充
繼承的方法如下:
1、prototype原型鏈方式:

function teacher(name){ this.name = name; } teacher.prototype.sayName = function(){ console.log("name is "+this.name); } var teacher1 = new teacher("xiaoming"); teacher1.sayName(); function student(name){ this.name = name; } student.prototype = new teacher() var student1 = new student("xiaolan"); student1.sayName(); // name is xiaoming // name is xiaolan

function teacher(name,age){ this.name = name; this.age = age; this.sayhi = function(){ alert('name:'+name+", age:"+age); } } function student(){ var args = arguments; teacher.call(this,args[0],args[1]); // teacher.apply(this,arguments); } var teacher1 = new teacher('xiaoming',23); teacher1.sayhi(); var student1 = new student('xiaolan',12); student1.sayhi(); // alert: name:xiaoming, age:23 // alert: name:xiaolan, age:12

function teacher(name,age){ this.name = name; this.age = age; } teacher.prototype.sayName = function(){ console.log('name:'+this.name); } teacher.prototype.sayAge = function(){ console.log('age:'+this.age); } function student(){ var args = arguments; teacher.call(this,args[0],args[1]); } student.prototype = new teacher(); var student1 = new student('xiaolin',23); student1.sayName(); student1.sayAge(); // name:xiaolin // age:23

function Person(name,age){ this.name = name; this.age = age; this.show = function(){ console.log(this.name+", "+this.age); } } function Student(name,age){ this.student = Person; //將Person類的構造函數賦值給this.student this.student(name,age); //js中實際上是通過對象冒充來實現繼承的 delete this.student; //移除對Person的引用 } var s = new Student("小明",17); s.show(); var p = new Person("小花",18); p.show(); // 小明, 17 // 小花, 18
javascript相關程序計算題
1、判斷一個字符串中出現次數最多的字符,統計這個次數
var str = 'asdfssaaasasasasaa'; var json = {}; for (var i = 0; i < str.length; i++) { if(!json[str.charAt(i)]){ json[str.charAt(i)] = 1; }else{ json[str.charAt(i)]++; } }; var iMax = 0; var iIndex = ''; for(var i in json){ if(json[i]>iMax){ iMax = json[i]; iIndex = i; } }
console.log('出現次數最多的是:'+iIndex+'出現'+iMax+'次');
結果如下:出現次數最多的是:a出現9次
JavaScript 數組(Array)對象
1、Array相關的屬性和方法
這里只是做了相關的列舉,具體的使用方法,請參考網址。
Array 對象屬性
constructor 返回對創建此對象的數組函數的引用。

var test=new Array(); if (test.constructor==Array) { document.write("This is an Array"); } if (test.constructor==Boolean) { document.write("This is a Boolean"); } if (test.constructor==Date) { document.write("This is a Date"); } if (test.constructor==String) { document.write("This is a String"); }
length 設置或返回數組中元素的數目。
prototype 使您有能力向對象添加屬性和方法。
Array 對象方法
concat() 連接兩個或更多的數組,並返回結果。

var arr = [1,2,3,4]; var arr2 = [5,6,7,8]; var arr3 = arr.concat(arr2); console.log(arr3); // 連接之后返回的數組為:[1, 2, 3, 4, 5, 6, 7, 8]
join() 把數組的所有元素放入一個字符串。元素通過指定的分隔符進行分隔。

var arr = ['xiao','lin','qiqi','mingtian']; var arr2 = arr.join(','); console.log(arr2); // 根據','隔開返回的字符串為:"xiao,lin,qiqi,mingtian"
pop() 刪除並返回數組的最后一個元素。

var arr = [2,3,4,5]; var arr2 = arr.pop(); console.log(arr2); // 刪除的數組的最后一個元素為:5 console.log(arr); // 刪除元素之后的數組為:[2, 3, 4]
shift() 刪除並返回數組的第一個元素

var arr = [2,3,4,5]; var arr2 = arr.shift(); console.log(arr2); // 刪除的數組的第一個元素為:2 console.log(arr); // 刪除元素之后的數組為:[3, 4,5]
push() 向數組的末尾添加一個或更多元素,並返回新的長度。

var arr = [2,3,4,5]; var arr2 = arr.push(6); console.log(arr2); // 返回的數組長度:5 console.log(arr); // [2, 3, 4, 5, 6]
unshift() 向數組的開頭添加一個或更多元素,並返回新的長度。

var arr = ['xiao','ming','qiqi','aiming']; var arr1 = arr.unshift('lang'); console.log(arr1); // 返回的數組的長度: 5 console.log(arr); //向數組開頭添加元素返回的結果:["lang", "xiao", "ming", "qiqi", "aiming"]
reverse() 顛倒數組中元素的順序。

var arr = [2,3,4,5]; arr.reverse(); console.log(arr); // [5, 4, 3, 2]
slice() 從某個已有的數組返回選定的元素

var arr = [2,3,4,5]; var arr2 = arr.slice(1,3); console.log(arr2); // 截取區間返回的數組為:[3, 4] console.log(arr); // [2, 3, 4, 5]
sort() 對數組的元素進行排序

借助排序函數,實現數值由小到大排序 function sortNumber(a,b){ return a - b } var arr = [23,30,42,5]; var arr2 = arr.sort(sortNumber); console.log(arr2); // [5, 23, 30, 42] console.log(arr); // [5, 23, 30, 42] 借助排序函數,實現數值由大到小排序 function sortNumber(a,b){ return b - a } var arr = [23,30,42,5]; var arr2 = arr.sort(sortNumber); console.log(arr2); // [42, 30, 23, 5] console.log(arr); // [42, 30, 23, 5]
splice() 刪除元素,並向數組添加新元素。

語法:arrayObject.splice(index,howmany,item1,.....,itemX) index:必需。整數,規定添加/刪除項目的位置,使用負數可從數組結尾處規定位置。 howmany:必需。要刪除的項目數量。如果設置為 0,則不會刪除項目。 item1, ..., itemX:可選。向數組添加的新項目。 // 創建一個新數組,並向其添加一個元素 var arr = [1,2,3,4]; arr.splice(2,0,5); console.log(arr); // [1, 2, 5, 3, 4] // 刪除位於 index 2 的元素,並添加一個新元素來替代被刪除的元素: var arr = [1,2,3,4]; arr.splice(2,1,5); console.log(arr); // [1, 2, 5, 4]
toSource() 返回該對象的源代碼。

瀏覽器支持 只有 Gecko 核心的瀏覽器(比如 Firefox)支持該方法,也就是說 IE、Safari、Chrome、Opera 等瀏覽器均不支持該方法。 <script type="text/javascript"> function employee(name,job,born){ this.name=name; this.job=job; this.born=born; } var bill = new employee("Bill Gates","Engineer",1985); document.write(bill.toSource()); </script> 輸出:({name:"Bill Gates", job:"Engineer", born:1985})
toString() 把數組轉換為字符串,並返回結果。

var arr = ['xiao','ming','qiqi','aiming']; arr.toString(); console.log(arr); // ["xiao", "ming", "qiqi", "aiming"]
toLocaleString() 把數組轉換為本地數組,並返回結果。

var arr = ['xiao','ming','qiqi','aiming']; arr.toLocaleString(); console.log(arr); // ["xiao", "ming", "qiqi", "aiming"]
valueOf() 返回數組對象的原始值

var arr = ['xiao','ming','qiqi','aiming']; arr.valueOf('lang'); console.log(arr); // ["xiao", "ming", "qiqi", "aiming"]
2、編寫一個方法 去掉一個數組的重復元素
方法一:
var arr = [0,2,3,4,4,0,2]; var obj = {}; var tmp = []; for(var i = 0 ;i< arr.length;i++){ if( !obj[arr[i]] ){ obj[arr[i]] = 1; tmp.push(arr[i]); } } console.log(tmp);
結果如下: [0, 2, 3, 4]
方法二:
var arr = [2,3,4,4,5,2,3,6], arr2 = []; for(var i = 0;i< arr.length;i++){ if(arr2.indexOf(arr[i]) < 0){ arr2.push(arr[i]); } } console.log(arr2);
結果為:[2, 3, 4, 5, 6]
方法三:
var arr = [2,3,4,4,5,2,3,6];
var arr2 = arr.filter(function(element,index,self){
return self.indexOf(element) === index;
});
console.log(arr2);
結果為:[2, 3, 4, 5, 6]
3、求數組的最值?
方法一:
- 求數組最大值:Math.max.apply(null,arr);
var arr = [3,43,23,45,65,90];
var max = Math.max.apply(null,arr);
console.log(max);
// 90
- 求數組最小值:Math.min.apply(null,arr);
var arr = [3,43,23,45,65,90];
var min = Math.min.apply(null,arr);
console.log(min);
// 3
方法二:Array.max = function(arr){} / Array.min = function(arr){}
var array = [3,43,23,45,65,90]; Array.max = function( array ){ return Math.max.apply( Math, array ); }; Array.min = function( array ){ return Math.min.apply( Math, array ); }; var max = Array.max(array); console.log(max); // 90 var min = Array.min(array); console.log(min); // 3
方法三:Array.prototype.max = function(){};Array.prototype.min = function(){};
-
求數組最大值(基本思路:將數組中的第一個值賦值給變量max ,將數組進行循環與max進行比較,將數組中的大值賦給max,最后返回max;)
var arr = [3,43,23,45,65,90]; Array.prototype.max = function() { var max = this[0]; var len = this.length; for (var i = 0; i < len; i++){ if (this[i] > max) { max = this[i]; } } return max; } var max = arr.max(); console.log(max); // 90
- 求數組最小值:
var arr = [3,43,23,45,65,90]; Array.prototype.min = function() { var min = this[0]; var len = this.length; for(var i = 0;i< len;i++){ if(this[i] < min){ min = this[i]; } } return min; } var min = arr.min(); console.log(min); // 3
4、數組排序相關
結合sort和函數排序:
- 數組由小到大進行排序:sort,sortnum;
var arr = [3,43,23,45,65,90]; function sortnum(a,b){ return a-b; } arr = arr.sort(sortnum); console.log(arr); // [3, 23, 43, 45, 65, 90]
- 數組由大到小進行排序:sort,sortnum;
var arr = [3,43,23,45,65,90]; function sortnum(a,b){ return a+b; } arr = arr.sort(sortnum); console.log(arr); // [90, 65, 45, 23, 43, 3]
冒泡排序:即實現數組由小到大進行排序;思路為:每次比較相鄰的兩個數,如果后一個比前一個小,換位置。如果要實現由大到小排序,使用reverse()即可;
var arr = [3, 1, 4, 6, 5, 7, 2]; function bubbleSort(arr) { var len = arr.length; for (var i = len; i >= 2; --i) { for (var j = 0; j < i - 1; j++) { if (arr[j + 1] < arr[j]) { var temp; temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } return arr; } var arr2 = bubbleSort(arr);
console.log(arr2); // [1, 2, 3, 4, 5, 6, 7]
var arr3 = arr2.reverse();
console.log(arr3); // [7, 6, 5, 4, 3, 2, 1]
快速排序:
思路:采用二分法,取出中間數,數組每次和中間數比較,小的放到左邊,大的放到右邊。
var arr = [3, 1, 4, 6, 5, 7, 2]; function quickSort(arr) { if(arr.length == 0) { return []; // 返回空數組 } var cIndex = Math.floor(arr.length / 2); var c = arr.splice(cIndex, 1); var l = []; var r = []; for (var i = 0; i < arr.length; i++) { if(arr[i] < c) { l.push(arr[i]); } else { r.push(arr[i]); } } return quickSort(l).concat(c, quickSort(r)); } console.log(quickSort(arr)); //[1, 2, 3, 4, 5, 6, 7]
5、數組的翻轉(非reverse())
方法一:
var arr = [1,2,3,4]; var arr2 = []; while(arr.length) { var num = arr.pop(); //刪除數組最后一個元素並返回被刪除的元素 arr2.push(num); } console.log(arr2); // [4, 3, 2, 1]
方法二:
var arr = [1,2,3,4]; var arr2 = []; while(arr.length){ var num = arr.shift(); //刪除數組第一個元素並返回被刪除的元素 arr2.unshift(num); } console.log(arr2);
jquery相關
1、 jQuery 庫中的 $() 是什么?
$() 函數是 jQuery() 函數的別稱。$() 函數用於將任何對象包裹成 jQuery 對象,接着你就被允許調用定義在 jQuery 對象上的多個不同方法。你可以將一個選擇器字符串傳入 $() 函數,它會返回一個包含所有匹配的 DOM 元素數組的 jQuery 對象。
2、如何找到所有 HTML select 標簽的選中項?
$('[name=selectname] :selected')
3、$(this) 和 this 關鍵字在 jQuery 中有何不同?
$(this) 返回一個 jQuery 對象,你可以對它調用多個 jQuery 方法,比如用 text() 獲取文本,用val() 獲取值等等。
而 this 代表當前元素,它是 JavaScript 關鍵詞中的一個,表示上下文中的當前 DOM 元素。你不能對它調用 jQuery 方法,直到它被 $() 函數包裹,例如 $(this)。
4、jquery怎么移除標簽onclick屬性?
獲得a標簽的onclick屬性: $("a").attr("onclick")
刪除onclick屬性:$("a").removeAttr("onclick");
設置onclick屬性:$("a").attr("onclick","test();");
5、jquery中addClass,removeClass,toggleClass的使用。
$(selector).addClass(class):為每個匹配的元素添加指定的類名
$(selector).removeClass(class):從所有匹配的元素中刪除全部或者指定的類,刪除class中某個值;
$(selector).toggleClass(class):如果存在(不存在)就刪除(添加)一個類
$(selector).removeAttr(class);刪除class這個屬性;
6、JQuery有幾種選擇器?
(1)、基本選擇器:#id,class,element,*;
(2)、層次選擇器:parent > child,prev + next ,prev ~ siblings
(3)、基本過濾器選擇器::first,:last ,:not ,:even ,:odd ,:eq ,:gt ,:lt
(4)、內容過濾器選擇器: :contains ,:empty ,:has ,:parent
(5)、可見性過濾器選擇器::hidden ,:visible
(6)、屬性過濾器選擇器:[attribute] ,[attribute=value] ,[attribute!=value] ,[attribute^=value] ,[attribute$=value] ,[attribute*=value]
(7)、子元素過濾器選擇器::nth-child ,:first-child ,:last-child ,:only-child
(8)、表單選擇器: :input ,:text ,:password ,:radio ,:checkbox ,:submit 等;
(9)、表單過濾器選擇器::enabled ,:disabled ,:checked ,:selected
7、jQuery中的Delegate()函數有什么作用?
delegate()會在以下兩個情況下使用到:
1、如果你有一個父元素,需要給其下的子元素添加事件,這時你可以使用delegate()了,代碼如下:
$("ul").delegate("li", "click", function(){ $(this).hide(); });
2、當元素在當前頁面中不可用時,可以使用delegate()
8、$(document).ready()方法和window.onload有什么區別?
(1)、window.onload方法是在網頁中所有的元素(包括元素的所有關聯文件)完全加載到瀏覽器后才執行的。
(2)、$(document).ready() 方法可以在DOM載入就緒時就對其進行操縱,並調用執行綁定的函數。
9、如何用jQuery禁用瀏覽器的前進后退按鈕?
實現代碼如下:
<script type="text/javascript" language="javascript"> $(document).ready(function() { window.history.forward(1); //OR window.history.forward(-1); }); </script>
10、 jquery中$.get()提交和$.post()提交有區別嗎?
相同點:都是異步請求的方式來獲取服務端的數據;
異同點:
1、請求方式不同:$.get() 方法使用GET方法來進行異步請求的。$.post() 方法使用POST方法來進行異步請求的。
2、參數傳遞方式不同:get請求會將參數跟在URL后進行傳遞,而POST請求則是作為HTTP消息的實體內容發送給Web服務器的,這種傳遞是對用戶不可見的。
3、數據傳輸大小不同:get方式傳輸的數據大小不能超過2KB 而POST要大的多
4、安全問題: GET 方式請求的數據會被瀏覽器緩存起來,因此有安全問題。
11、寫出一個簡單的$.ajax()的請求方式?
$.ajax({ url:'http://www.baidu.com', type:'POST', data:data, cache:true, headers:{}, beforeSend:function(){}, success:function(){}, error:function(){}, complete:function(){} });
12、jQuery的事件委托方法bind 、live、delegate、on之間有什么區別?
(1)、bind 【jQuery 1.3之前】
定義和用法:主要用於給選擇到的元素上綁定特定事件類型的監聽函數;
語法:bind(type,[data],function(eventObject));
特點:
(1)、適用於頁面元素靜態綁定。只能給調用它的時候已經存在的元素綁定事件,不能給未來新增的元素綁定事件。
(2)、當頁面加載完的時候,你才可以進行bind(),所以可能產生效率問題。
實例如下:$( "#members li a" ).bind( "click", function( e ) {} );
(2)、live 【jQuery 1.3之后】
定義和用法:主要用於給選擇到的元素上綁定特定事件類型的監聽函數;
語法:live(type, [data], fn);
特點:
(1)、live方法並沒有將監聽器綁定到自己(this)身上,而是綁定到了this.context上了。
(2)、live正是利用了事件委托機制來完成事件的監聽處理,把節點的處理委托給了document,新添加的元素不必再綁定一次監聽器。
(3)、使用live()方法但卻只能放在直接選擇的元素后面,不能在層級比較深,連綴的DOM遍歷方法后面使用,即$(“ul”").live...可以,但$("body").find("ul").live...不行;
實例如下:$( document ).on( "click", "#members li a", function( e ) {} );
(3)、delegate 【jQuery 1.4.2中引入】
定義和用法:將監聽事件綁定在就近的父級元素上
語法:delegate(selector,type,[data],fn)
特點:
(1)、選擇就近的父級元素,因為事件可以更快的冒泡上去,能夠在第一時間進行處理。
(2)、更精確的小范圍使用事件代理,性能優於.live()。可以用在動態添加的元素上。
實例如下:
$("#info_table").delegate("td","click",function(){/*顯示更多信息*/});
$("table").find("#info").delegate("td","click",function(){/*顯示更多信息*/});
(4)、on 【1.7版本整合了之前的三種方式的新事件綁定機制】
定義和用法:將監聽事件綁定到指定元素上。
語法:on(type,[selector],[data],fn)
實例如下:$("#info_table").on("click","td",function(){/*顯示更多信息*/});參數的位置寫法與delegate不一樣。
說明:on方法是當前JQuery推薦使用的事件綁定方法,附加只運行一次就刪除函數的方法是one()。
總結:.bind(), .live(), .delegate(),.on()分別對應的相反事件為:.unbind(),.die(), .undelegate(),.off()
HTML & CSS:
1、什么是盒子模型?
在網頁中,一個元素占有空間的大小由幾個部分構成,其中包括元素的內容(content),元素的內邊距(padding),元素的邊框(border),元素的外邊距(margin)四個部分。這四個部分占有的空間中,有的部分可以顯示相應的內容,而有的部分只用來分隔相鄰的區域或區域。4個部分一起構成了css中元素的盒模型。
2、行內元素有哪些?塊級元素有哪些? 空(void)元素有那些?
行內元素:a、b、span、img、input、strong、select、label、em、button、textarea
塊級元素:div、ul、li、dl、dt、dd、p、h1-h6、blockquote
空元素:即系沒有內容的HTML元素,例如:br、meta、hr、link、input、img
3、CSS實現垂直水平居中
一道經典的問題,實現方法有很多種,以下是其中一種實現:
HTML結構:
<div class="wrapper"> <div class="content"></div> </div>
CSS:
.wrapper { position: relative; width: 500px; height: 500px; border: 1px solid red; } .content{ position: absolute; width: 200px; height: 200px; /*top、bottom、left和right 均設置為0*/ top: 0; bottom: 0; left: 0; right: 0; /*margin設置為auto*/ margin:auto; border: 1px solid green; }
效果如下:
4、簡述一下src與href的區別
href 是指向網絡資源所在位置,建立和當前元素(錨點)或當前文檔(鏈接)之間的鏈接,用於超鏈接。
src是指向外部資源的位置,指向的內容將會嵌入到文檔中當前標簽所在位置;在請求src資源時會將其指向的資源下載並應用到文檔內,例如js腳本,img圖片和frame等元素。
當瀏覽器解析到該元素時,會暫停其他資源的下載和處理,直到將該資源加載、編譯、執行完畢,圖片和框架等元素也如此,類似於將所指向資源嵌入當前標簽內。這也是為什么將js腳本放在底部而不是頭部。
5、簡述同步和異步的區別
同步是阻塞模式,異步是非阻塞模式。
同步就是指一個進程在執行某個請求的時候,若該請求需要一段時間才能返回信息,那么這個進程將會一直等待下去,直到收到返回信息才繼續執行下去;
異步是指進程不需要一直等下去,而是繼續執行下面的操作,不管其他進程的狀態。當有消息返回時系統會通知進程進行處理,這樣可以提高執行的效率。
6、px和em的區別
相同點:px和em都是長度單位;
異同點:px的值是固定的,指定是多少就是多少,計算比較容易。em得值不是固定的,並且em會繼承父級元素的字體大小。
瀏覽器的默認字體高都是16px。所以未經調整的瀏覽器都符合: 1em=16px。那么12px=0.75em, 10px=0.625em。
7、瀏覽器的內核分別是什么?
8、什么叫優雅降級和漸進增強?
漸進增強 progressive enhancement:
針對低版本瀏覽器進行構建頁面,保證最基本的功能,然后再針對高級瀏覽器進行效果、交互等改進和追加功能達到更好的用戶體驗。
優雅降級 graceful degradation:
一開始就構建完整的功能,然后再針對低版本瀏覽器進行兼容。
區別:
a. 優雅降級是從復雜的現狀開始,並試圖減少用戶體驗的供給
b. 漸進增強則是從一個非常基礎的,能夠起作用的版本開始,並不斷擴充,以適應未來環境的需要
c. 降級(功能衰減)意味着往回看;而漸進增強則意味着朝前看,同時保證其根基處於安全地帶
9、sessionStorage 、localStorage 和 cookie 之間的區別
共同點:用於瀏覽器端存儲的緩存數據
不同點:
(1)、存儲內容是否發送到服務器端:當設置了Cookie后,數據會發送到服務器端,造成一定的寬帶浪費;
web storage,會將數據保存到本地,不會造成寬帶浪費;
(2)、數據存儲大小不同:Cookie數據不能超過4K,適用於會話標識;web storage數據存儲可以達到5M;
(3)、數據存儲的有效期限不同:cookie只在設置了Cookid過期時間之前一直有效,即使關閉窗口或者瀏覽器;
sessionStorage,僅在關閉瀏覽器之前有效;localStorage,數據存儲永久有效;
(4)、作用域不同:cookie和localStorage是在同源同窗口中都是共享的;sessionStorage不在不同的瀏覽器窗口中共享,即使是同一個頁面;
10、Web Storage與Cookie相比存在的優勢:
(1)、存儲空間更大:IE8下每個獨立的存儲空間為10M,其他瀏覽器實現略有不同,但都比Cookie要大很多。
(2)、存儲內容不會發送到服務器:當設置了Cookie后,Cookie的內容會隨着請求一並發送的服務器,這對於本地存儲的數據是一種帶寬浪費。而Web Storage中的數據則僅僅是存在本地,不會與服務器發生任何交互。
(3)、更多豐富易用的接口:Web Storage提供了一套更為豐富的接口,如setItem,getItem,removeItem,clear等,使得數據操作更為簡便。cookie需要自己封裝。
(4)、獨立的存儲空間:每個域(包括子域)有獨立的存儲空間,各個存儲空間是完全獨立的,因此不會造成數據混亂。
11、Ajax的優缺點及工作原理?
定義和用法:
AJAX = Asynchronous JavaScript and XML(異步的 JavaScript 和 XML)。Ajax 是一種用於創建快速動態網頁的技術。Ajax 是一種在無需重新加載整個網頁的情況下,能夠更新部分網頁的技術。
傳統的網頁(不使用 Ajax)如果需要更新內容,必須重載整個網頁頁面。
優點:
1.減輕服務器的負擔,按需取數據,最大程度的減少冗余請求
2.局部刷新頁面,減少用戶心理和實際的等待時間,帶來更好的用戶體驗
3.基於xml標准化,並被廣泛支持,不需安裝插件等,進一步促進頁面和數據的分離
缺點:
1.AJAX大量的使用了javascript和ajax引擎,這些取決於瀏覽器的支持.在編寫的時候考慮對瀏覽器的兼容性.
2.AJAX只是局部刷新,所以頁面的后退按鈕是沒有用的.
3.對流媒體還有移動設備的支持不是太好等
AJAX的工作原理:
1.創建ajax對象(XMLHttpRequest/ActiveXObject(Microsoft.XMLHttp))
2.判斷數據傳輸方式(GET/POST)
3.打開鏈接 open()
4.發送 send()
5.當ajax對象完成第四步(onreadystatechange)數據接收完成,判斷http響應狀態(status)200-300之間或者304(緩存)執行回調函數
12、請指出document load和document ready的區別?
共同點:這兩種事件都代表的是頁面文檔加載時觸發。
異同點:
ready 事件的觸發,表示文檔結構已經加載完成(不包含圖片等非文字媒體文件)。
onload 事件的觸發,表示頁面包含圖片等文件在內的所有元素都加載完成。
正則表達式
1、寫一個function,清除字符串前后的空格。(兼容所有瀏覽器)
function trim(str) { if (str && typeof str === "string") { return str.replace(/(^\s*)|(\s*)$/g,""); //去除前后空白符 } }
2、使用正則表達式驗證郵箱格式
var reg = /^(\w)+(\.\w+)*@(\w)+((\.\w{2,3}){1,3})$/; var email = "example@qq.com"; console.log(reg.test(email)); // true
開發及性能優化
1、規避javascript多人開發函數重名問題
- 命名空間
- 封閉空間
- js模塊化mvc(數據層、表現層、控制層)
- seajs
- 變量轉換成對象的屬性
- 對象化
2、請說出三種減低頁面加載時間的方法
- 壓縮css、js文件
- 合並js、css文件,減少http請求
- 外部js、css文件放在最底下
- 減少dom操作,盡可能用變量替代不必要的dom操作
3、你所了解到的Web攻擊技術
(1)XSS(Cross-Site Scripting,跨站腳本攻擊):指通過存在安全漏洞的Web網站注冊用戶的瀏覽器內運行非法的HTML標簽或者JavaScript進行的一種攻擊。
(2)SQL注入攻擊
(3)CSRF(Cross-Site Request Forgeries,跨站點請求偽造):指攻擊者通過設置好的陷阱,強制對已完成的認證用戶進行非預期的個人信息或設定信息等某些狀態更新。
4、web前端開發,如何提高頁面性能優化?
內容方面:
1.減少 HTTP 請求 (Make Fewer HTTP Requests)
2.減少 DOM 元素數量 (Reduce the Number of DOM Elements)
3.使得 Ajax 可緩存 (Make Ajax Cacheable)
針對CSS:
1.把 CSS 放到代碼頁上端 (Put Stylesheets at the Top)
2.從頁面中剝離 JavaScript 與 CSS (Make JavaScript and CSS External)
3.精簡 JavaScript 與 CSS (Minify JavaScript and CSS)
4.避免 CSS 表達式 (Avoid CSS Expressions)
針對JavaScript :
1. 腳本放到 HTML 代碼頁底部 (Put Scripts at the Bottom)
2. 從頁面中剝離 JavaScript 與 CSS (Make JavaScript and CSS External)
3. 精簡 JavaScript 與 CSS (Minify JavaScript and CSS)
4. 移除重復腳本 (Remove Duplicate Scripts)
面向圖片(Image):
1.優化圖片
2 不要在 HTML 中使用縮放圖片
3 使用恰當的圖片格式
4 使用 CSS Sprites 技巧對圖片優化
5、前端開發中,如何優化圖像?圖像格式的區別?
優化圖像:
1、不用圖片,盡量用css3代替。 比如說要實現修飾效果,如半透明、邊框、圓角、陰影、漸變等,在當前主流瀏覽器中都可以用CSS達成。
2、 使用矢量圖SVG替代位圖。對於絕大多數圖案、圖標等,矢量圖更小,且可縮放而無需生成多套圖。現在主流瀏覽器都支持SVG了,所以可放心使用!
3.、使用恰當的圖片格式。我們常見的圖片格式有JPEG、GIF、PNG。
基本上,內容圖片多為照片之類的,適用於JPEG。
而修飾圖片通常更適合用無損壓縮的PNG。
GIF基本上除了GIF動畫外不要使用。且動畫的話,也更建議用video元素和視頻格式,或用SVG動畫取代。
4、按照HTTP協議設置合理的緩存。
5、使用字體圖標webfont、CSS Sprites等。
6、用CSS或JavaScript實現預加載。
7、WebP圖片格式能給前端帶來的優化。WebP支持無損、有損壓縮,動態、靜態圖片,壓縮比率優於GIF、JPEG、JPEG2000、PG等格式,非常適合用於網絡等圖片傳輸。
圖像格式的區別:
矢量圖:圖標字體,如 font-awesome;svg
位圖:gif,jpg(jpeg),png
區別:
1、gif:是是一種無損,8位圖片格式。具有支持動畫,索引透明,壓縮等特性。適用於做色彩簡單(色調少)的圖片,如logo,各種小圖標icons等。
2、JPEG格式是一種大小與質量相平衡的壓縮圖片格式。適用於允許輕微失真的色彩豐富的照片,不適合做色彩簡單(色調少)的圖片,如logo,各種小圖標icons等。
3、png:PNG可以細分為三種格式:PNG8,PNG24,PNG32。后面的數字代表這種PNG格式最多可以索引和存儲的顏色值。
關於透明:PNG8支持索引透明和alpha透明;PNG24不支持透明;而PNG32在24位的PNG基礎上增加了8位(256階)的alpha通道透明;
優缺點:
1、能在保證最不失真的情況下盡可能壓縮圖像文件的大小。
2、對於需要高保真的較復雜的圖像,PNG雖然能無損壓縮,但圖片文件較大,不適合應用在Web頁面上。
6、瀏覽器是如何渲染頁面的?
渲染的流程如下:
1.解析HTML文件,創建DOM樹。
自上而下,遇到任何樣式(link、style)與腳本(script)都會阻塞(外部樣式不阻塞后續外部腳本的加載)。
2.解析CSS。優先級:瀏覽器默認設置<用戶設置<外部樣式<內聯樣式<HTML中的style樣式;
3.將CSS與DOM合並,構建渲染樹(Render Tree)
4.布局和繪制,重繪(repaint)和重排(reflow)