1..sort 排序原理
冒泡排序法解析:冒泡排序法的原理:
比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
對每一對相鄰元素做同樣的工作,從開始第一對到結(jié)尾的最后一對。在這一點,最后的元素應(yīng)該會是最大的數(shù)。
針對所有的元素重復(fù)以上的步驟,除了最后一個。
持續(xù)每次對越來越少的元素重復(fù)上面的步驟,直到?jīng)]有任何一對數(shù)字需要比較。
示例:
var arr = [1, 5, 4, 2];
// sort()方法的比較邏輯為:
// 第一輪:1和5比,1和4比,1和2比
// 第二輪:5和4比,5和2比
// 第三輪:4和2比// 一.sort排序規(guī)則 return大于0則交換數(shù)組相鄰2個元素的位置
// 二.arr.sort(function (a,b) {})中
// a --?代表每一次執(zhí)行匿名函時候,找到的數(shù)組中的當(dāng)前項;
// b --?代表當(dāng)前項的后一項;
// 1.升序
var apple = [45, 42, 10, 147, 7, 65, -74];
// ①默認法,缺點:只根據(jù)首位排序
console.log(apple.sort());
// ②指定排序規(guī)則法,return可返回任何值
console.log(
apple.sort(function(a, b) {
return a - b; //若return返回值大于0(即a>b),則a,b交換位置
})
);
//2.降序
var arr = [45, 42, 10, 111, 7, 65, -74];
console.log(
apple.sort(function(a, b) {
return b - a; //若return返回值大于零(即b>a),則a,b交換位置
})
);參考 1、參考 2
2.JavaScript 的數(shù)據(jù)類型
JS 數(shù)據(jù)類型共有六種,分別是 String、Number、Boolean、Null、Undefined 和 Object 等, 另外,ES6 新增了 Symbol 類型。其中,Object 是引用類型,其他的都是基本類型(Primitive Type)。
3.call() 和 apply() 的含義和區(qū)別?
首先說明兩個方法的含義:
call:調(diào)用一個對象的一個方法,用另一個對象替換當(dāng)前對象。例如:B.call(A, args1,args2);即 A 對象調(diào)用 B 對象的方法。
apply:調(diào)用一個對象的一個方法,用另一個對象替換當(dāng)前對象。例如:B.apply(A, arguments);即 A 對象應(yīng)用 B 對象的方法。
call 與 apply 的相同點:
方法的含義是一樣的,即方法功能是一樣的;
第一個參數(shù)的作用是一樣的;
call 與 apply 的不同點:兩者傳入的列表形式不一樣
call 可以傳入多個參數(shù);
apply 只能傳入兩個參數(shù),所以其第二個參數(shù)往往是作為數(shù)組形式傳入
4.Zepto 的點透問題如何解決?
方案一:來得很直接 github 上有個 fastclick 可以完美解決https://github.com/ftlabs/fastclick引入 fastclick.js,因為 fastclick 源碼不依賴其他庫所以你可以在原生的 js 前直接加上
window.addEventListener(
"load",
function() {
FastClick.attach(document.body);
},
false
);
或者有 zepto 或者 jqm 的 js 里面加上
$(function() {
FastClick.attach(document.body);
});
當(dāng)然 require 的話就這樣:
var FastClick = require("fastclick");
FastClick.attach(document.body, options);
方案二:用 touchend 代替 tap 事件并阻止掉 touchend 的默認行為 preventDefault()$("#cbFinish").on("touchend", function(event) {
//很多處理比如隱藏什么的
event.preventDefault();
});
方案三:延遲一定的時間(300ms+)來處理事件
$("#cbFinish").on("tap", function(event) {
setTimeout(function() {
//很多處理比如隱藏什么的
}, 320);
});
這種方法其實很好,可以和 fadeInIn/fadeOut 等動畫結(jié)合使用
5..如何判斷當(dāng)前腳本運行在瀏覽器還是 node 環(huán)境中?
通過判斷 Global 對象是否為 window,如果不為 window,當(dāng)前腳本沒有運行在瀏覽器中
6.移動端最小觸控區(qū)域是多大?
蘋果推薦是 44pt x 44pt解析:參考
7.解釋 JavaScript 中的作用域與變量聲明提升?
對作用域的理解是只會對某個范圍產(chǎn)生作用,而不會對外產(chǎn)生影響的封閉空間。在這樣的一些空間里,外部不能訪問內(nèi)部變量,但內(nèi)部可以訪問外部變量。
所有申明都會被提升到作用域的最頂上
同一個變量申明只進行一次,并且因此其他申明都會被忽略
函數(shù)聲明的優(yōu)先級優(yōu)于變量申明,且函數(shù)聲明會連帶定義一起被提升
8.Node.js 的適用場景?
比如:RESTFUL API、實時聊天、客戶端邏輯強大的單頁 APP,具體的例子比如說:本地化的在線音樂應(yīng)用,本地化的在線搜索應(yīng)用,本地化的在線 APP 等。解析:參考
9.如何判斷一個對象是否屬于某個類?
instanceof解析:if (a instanceof Person) {
alert("yes");
}
10.bind、call、apply 的區(qū)別
call 和 apply 其實是一樣的,區(qū)別就在于傳參時參數(shù)是一個一個傳或者是以一個數(shù)組的方式來傳。
call 和 apply 都是在調(diào)用時生效,改變調(diào)用者的 this 指向。
let name = 'Jack'
const obj = {name: 'Tom'}
function sayHi() {console.log('Hi! ' + this.name)}
sayHi() // Hi! Jack
sayHi.call(obj) // Hi! Tom
bind 也是改變 this 指向,不過不是在調(diào)用時生效,而是返回一個新函數(shù)。
const newFunc = sayHi.bind(obj)
newFunc() // Hi! Tom
11.移動端的點擊事件的有延遲,時間是多久,為什么會有? 怎么解決這個延時?
300 毫秒
因為瀏覽器捕獲第一次單擊后,會先等待一段時間,如果在這段時間區(qū)間里用戶未進行下一次點擊,則瀏覽器會做單擊事件的處理。如果這段時間里用戶進行了第二次單擊操作,則瀏覽器會做雙擊事件處理。
推薦 fastclick.js
12.如何實現(xiàn)文件斷點續(xù)傳
斷點續(xù)傳最核心的內(nèi)容就是把文件“切片”然后再一片一片的傳給服務(wù)器,但是這看似簡單的上傳過程卻有著無數(shù)的坑。首先是文件的識別,一個文件被分成了若干份之后如何告訴服務(wù)器你切了多少塊,以及最終服務(wù)器應(yīng)該如何把你上傳上去的文件進行合并,這都是要考慮的。因此在文件開始上傳之前,我們和服務(wù)器要有一個“握手”的過程,告訴服務(wù)器文件信息,然后和服務(wù)器約定切片的大小,當(dāng)和服務(wù)器達成共識之后就可以開始后續(xù)的文件傳輸了。前臺要把每一塊的文件傳給后臺,成功之后前端和后端都要標(biāo)識一下,以便后續(xù)的斷點。當(dāng)文件傳輸中斷之后用戶再次選擇文件就可以通過標(biāo)識來判斷文件是否已經(jīng)上傳了一部分,如果是的話,那么我們可以接著上次的進度繼續(xù)傳文件,以達到續(xù)傳的功能。
有了 HTML5 的 File api 之后切割文件比想想的要簡單的多的多。只要用 slice 方法就可以了var packet = file.slice(start, end);
參數(shù) start 是開始切片的位置,end 是切片結(jié)束的位置 單位都是字節(jié)。通過控制 start 和 end 就可以是實現(xiàn)文件的分塊如file.slice(0,1000);
file.slice(1000,2000);
file.slice(2000,3000);
// ......
在把文件切成片之后,接下來要做的事情就是把這些碎片傳到服務(wù)器上。
如果中間掉線了,下次再傳的時候就得先從服務(wù)器獲取上一次上傳文件的位置,然后以這個位置開始上傳接下來的文件內(nèi)容。
13.使用構(gòu)造函數(shù)的注意點
一般情況下構(gòu)造函數(shù)的首字母需要大寫,因為我們在看到一個函數(shù)首字母大寫的情況,就認定這是一個構(gòu)造函數(shù),需要跟new關(guān)鍵字進行搭配使用,創(chuàng)建一個新的實例(對象)
構(gòu)造函數(shù)在被調(diào)用的時候需要跟new關(guān)鍵字搭配使用。
在構(gòu)造函數(shù)內(nèi)部通過this+屬性名的形式為實例添加一些屬性和方法。
構(gòu)造函數(shù)一般不需要返回值,如果有返回值
13.1 如果返回值是一個基本數(shù)據(jù)類型,那么調(diào)用構(gòu)造函數(shù),返回值仍舊是那么創(chuàng)建出來的對象。
13.2 如果返回值是一個復(fù)雜數(shù)據(jù)類型,那么調(diào)用構(gòu)造函數(shù)的時候,返回值就是這個return之后的那個復(fù)雜數(shù)據(jù)類型。
14.數(shù)組的常用方法
Array.map()
此方法是將數(shù)組中的每個元素調(diào)用一個提供的函數(shù),結(jié)果作為一個新的數(shù)組返回,并沒有改變原來的數(shù)組
let arr = [1, 2, 3, 4, 5];
let newArr = arr.map(x =? x * 2);
//arr= [1, 2, 3, 4, 5] 原數(shù)組保持不變
//newArr = [2, 4, 6, 8, 10] 返回新數(shù)組
Array.forEach()
此方法是將數(shù)組中的每個元素執(zhí)行傳進提供的函數(shù),沒有返回值,直接改變原數(shù)組,注意和 map 方法區(qū)分
let arr = [1, 2, 3, 4, 5];
num.forEach(x =? x * 2);
// arr = [2, 4, 6, 8, 10] 數(shù)組改變,注意和map區(qū)分
Array.filter()
此方法是將所有元素進行判斷,將滿足條件的元素作為一個新的數(shù)組返回
let arr = [1, 2, 3, 4, 5]
const isBigEnough =? value =? value ?= 3
let newArr = arr.filter(isBigEnough )
//newNum = [3, 4, 5] 滿足條件的元素返回為一個新的數(shù)組
Array.every()
此方法是將所有元素進行判斷返回一個布爾值,如果所有元素都滿足判斷條件,則返回 true,否則為 false:
let arr = [1, 2, 3, 4, 5]
const isLessThan4 =? value =? value ? 4
const isLessThan6 =? value =? value ? 6
arr.every(isLessThan4 ) //false
arr.every(isLessThan6 ) //true
Array.some()
此方法是將所有元素進行判斷返回一個布爾值,如果存在元素都滿足判斷條件,則返回 true,若所有元素都不滿足判斷條件,則返回 false:
let arr= [1, 2, 3, 4, 5]
const isLessThan4 =? value =? value ? 4
const isLessThan6 =? value =? value ? 6
arr.some(isLessThan4 ) //true
arr.some(isLessThan6 ) //false
Array.reduce()
此方法是所有元素調(diào)用返回函數(shù),返回值為最后結(jié)果,傳入的值必須是函數(shù)類型:
let arr = [1, 2, 3, 4, 5];
const add = (a, b) =? a + b;
let sum = arr.reduce(add);
//sum = 15
相當(dāng)于累加的效果與之相對應(yīng)的還有一個 Array.reduceRight() 方法,區(qū)別是這個是從右向左操作的
Array.push()
此方法是在數(shù)組的后面添加新加元素,此方法改變了數(shù)組的長度:
Array.pop()
此方法在數(shù)組后面刪除最后一個元素,并返回數(shù)組,此方法改變了數(shù)組的長度:
let arr = [1, 2, 3, 4, 5];
arr.pop();
console.log(arr); //[1, 2, 3, 4]
console.log(arr.length); //4
Array.shift()
此方法在數(shù)組后面刪除第一個元素,并返回數(shù)組,此方法改變了數(shù)組的長度:
let arr = [1, 2, 3, 4, 5];
arr.shift();
console.log(arr); //[2, 3, 4, 5]
console.log(arr.length); //4
Array.unshift()
此方法是將一個或多個元素添加到數(shù)組的開頭,并返回新數(shù)組的長度:
let arr = [1, 2, 3, 4, 5];
arr.unshift(6, 7);
console.log(arr); //[6, 7, 2, 3, 4, 5]
console.log(arr.length); //7
Array.isArray()
判斷一個對象是不是數(shù)組,返回的是布爾值
Array.concat()
此方法是一個可以將多個數(shù)組拼接成一個數(shù)組:
let arr1 = [1, 2, 3]
arr2 = [4, 5]
let arr = arr1.concat(arr2)
console.log(arr)//[1, 2, 3, 4, 5]
. Array.toString()
此方法將數(shù)組轉(zhuǎn)化為字符串:
```js
let arr = [1, 2, 3, 4, 5];
let str = arr.toString()
console.log(str)// 1,2,3,4,5
Array.join()
此方法也是將數(shù)組轉(zhuǎn)化為字符串
```js
let arr = [1, 2, 3, 4, 5];
let str1 = arr.toString()
let str2 = arr.toString(',')
let str3 = arr.toString('##')
console.log(str1)// 12345
console.log(str2)// 1,2,3,4,5
console.log(str3)// 1##2##3##4##5
通過例子可以看出和 toString 的區(qū)別,可以設(shè)置元素之間的間隔
Array.splice(開始位置, 刪除的個數(shù),元素)
萬能方法,可以實現(xiàn)增刪改:
let arr = [1, 2, 3, 4, 5];
let arr1 = arr.splice(2, 0 'haha')
let arr2 = arr.splice(2, 3)
let arr1 = arr.splice(2, 1 'haha')
console.log(arr1) //[1, 2, 'haha', 3, 4, 5]新增一個元素
console.log(arr2) //[1, 2] 刪除三個元素
console.log(arr3) //[1, 2, 'haha', 4, 5] 替換一個元素
15..如何獲取瀏覽器版本信息
window.navigator.userAgent
16..字符串常用操作
charAt(index):返回指定索引處的字符串
charCodeAt(index):返回指定索引處的字符的 Unicode 的值
concat(str1,str2,...):連接多個字符串,返回連接后的字符串的副本
fromCharCode():將 Unicode 值轉(zhuǎn)換成實際的字符串
indexOf(str):返回 str 在父串中第一次出現(xiàn)的位置,若沒有則返回-1
lastIndexOf(str):返回 str 在父串中最后一次出現(xiàn)的位置,若沒有則返回-1
match(regex):搜索字符串,并返回正則表達式的所有匹配
replace(str1,str2):str1 也可以為正則表達式,用 str2 替換 str1
search(regex):基于正則表達式搜索字符串,并返回第一個匹配的位置
slice(start,end):返回字符索引在 start 和 end(不含)之間的子串
split(sep,limit):將字符串分割為字符數(shù)組,limit 為從頭開始執(zhí)行分割的最大數(shù)量
substr(start,length):從字符索引 start 的位置開始,返回長度為 length 的子串
substring(from,to):返回字符索引在 from 和 to(不含)之間的子串
toLowerCase():將字符串轉(zhuǎn)換為小寫
toUpperCase():將字符串轉(zhuǎn)換為大寫
valueOf():返回原始字符串值
17.作用域的概念及作用
作用域 : 起作用的一塊區(qū)域
作用域的概念: 對變量起保護作用的一塊區(qū)域
作用: 作用域外部無法獲取到作用域內(nèi)部聲明的變量,作用域內(nèi)部能夠獲取到作用域外界聲明的變量。
18.call 與 apply 區(qū)別
第二個參數(shù)的類型不同解析:call 和 apply 的作用,完全一樣,唯一的區(qū)別就是在參數(shù)上面。call 接收的參數(shù)不固定,第一個參數(shù)是函數(shù)體內(nèi) this 的指向,第二個參數(shù)以下是依次傳入的參數(shù)。apply 接收兩個參數(shù),第一個參數(shù)也是函數(shù)體內(nèi) this 的指向。第二個參數(shù)是一個集合對象(數(shù)組或者類數(shù)組)
19.正則表達式構(gòu)造函數(shù) var reg = new RegExp('xxx')與正則表達字面量 var reg = // 有什么不同?
使用正則表達字面量的效率更高解析:下面的示例代碼演示了兩種可用于創(chuàng)建正則表達式以匹配反斜杠的方法:
//正則表達字面量
var re = /\\/gm;
//正則構(gòu)造函數(shù)
var reg = new RegExp("\\\\", "gm");
var foo = "abc\\123"; // foo的值為"abc\123"
console.log(re.test(foo)); //true
console.log(reg.test(foo)); //true如上面的代碼中可以看到,使用正則表達式字面量表示法時式子顯得更加簡短,而且不用按照類似類(class-like)的構(gòu)造函數(shù)方式思考。其次,在當(dāng)使用構(gòu)造函數(shù)的時候,在這里要使用四個反斜杠才能匹配單個反斜杠。這使得正則表達式模式顯得更長,更加難以閱讀和修改。正確來說,當(dāng)使用 RegExp()構(gòu)造函數(shù)的時候,不僅需要轉(zhuǎn)義引號(即"表示"),并且通常還需要雙反斜杠(即\表示一個\)。使用 new RegExp()的原因之一在于,某些場景中無法事先確定模式,而只能在運行時以字符串方式創(chuàng)建。參考
20.js 中 callee 與 caller 的作用
caller 返回一個調(diào)用當(dāng)前函數(shù)的引用 如果是由頂層調(diào)用的話 則返回 null
(舉個栗子哈 caller 給你打電話的人 誰給你打電話了 誰調(diào)用了你 很顯然是下面 a 函數(shù)的執(zhí)行 只有在打電話的時候你才能知道打電話的人是誰 所以對于函數(shù)來說 只有 caller 在函數(shù)執(zhí)行的時候才存在)
var callerTest = function() {
console.log(callerTest.caller);
};
function a() {
callerTest();
}
a(); //輸出function a() {callerTest();}
callerTest(); //輸出null
callee 返回一個正在被執(zhí)行函數(shù)的引用 (這里常用來遞歸匿名函數(shù)本身 但是在嚴(yán)格模式下不可行)
callee 是 arguments 對象的一個成員 表示對函數(shù)對象本身的引用 它有個 length 屬性(代表形參的長度)
var c = function(x, y) {
console.log(arguments.length, arguments.callee.length, arguments.callee);
};
c (1, 2, 3); //輸出3 2 function(x,y) {console.log(arguments.length,arguments.callee.length,arguments.callee)}