1、undeclared 與 undefined的區別?
undefined:宣告瞭變數,但是沒有賦值
undecalared:沒有宣告變數就直接使用
var a; //undefined
b; // b is not defined
2、let & const與 var 的區別?
var存在變數提升,可重複宣告同一變數,宣告的變數均可改
let沒有變數提升,不可重複宣告同一變數,宣告的變數均可改
const沒有變數提升,不可重複宣告同一變數,宣告的基本資料型別不可改,引用型別可改屬性,不可只宣告變數而不賦值
3、獲取DOM元素有哪些方法?
方法 | 描述 |
---|---|
document.getElementById(id) | 通過id獲取dom |
document.getElementsByTagName(tagName) | 通過標籤名獲取dom |
document.getElementsByClassName(class) | 通過class獲取dom |
document.getElementsByName(name) | 通過標籤的屬性name獲取dom |
document.querySelector(選擇器) | 通過選擇器獲取dom |
document.querySelectorAll(選擇器) | 通過選擇器獲取dom |
4、操作DOM元素有哪些方法
方法 | 描述 |
---|---|
createElement | 建立一個標籤節點 |
createTextNode | 建立一個文字節點 |
cloneNode(deep) | 複製一個節點,連同屬性與值都複製,deep為true時,連同後代節點一起復制,不傳或者傳false,則只複製當前節點 |
createDocumentFragment | 建立一個文件碎片節點 |
appendChild | 追加子元素 |
insertBefore | 將元素插入前面 |
removeChild | 刪除子元素 |
replaceChild | 替換子元素 |
getAttribute | 獲取節點的屬性 |
createAttribute | 建立屬性 |
setAttribute | 設定節點屬性 |
romoveAttribute | 刪除節點屬性 |
element.attributes | 將屬性生成類陣列物件 |
5、DOM的型別有哪幾種?
元素節點 Node.ELEMENT_NODE(1)
屬性節點 Node.ATTRIBUTE_NODE(2)
文字節點 Node.TEXT_NODE(3)
CDATA節點 Node.CDATA_SECTION_NODE(4)
實體引用名稱節點 Node.ENTRY_REFERENCE_NODE(5)
實體名稱節點 Node.ENTITY_NODE(6)
處理指令節點 Node.PROCESSING_INSTRUCTION_NODE(7)
註釋節點 Node.COMMENT_NODE(8)
文件節點 Node.DOCUMENT_NODE(9)
文件型別節點 Node.DOCUMENT_TYPE_NODE(10)
文件片段節點 Node.DOCUMENT_FRAGMENT_NODE(11)
DTD宣告節點 Node.NOTATION_NODE(12)
6、JS的作用域及作用域鏈
什麼是作用域呢?
在 Javascript 中,作用域分為 全域性作用域 和 函式作用域
全域性作用域:程式碼在程式任何地方都能訪問,window物件的內建屬性都屬於全域性作用域
函式作用域:在固定的程式碼片段才能被訪問
什麼是作用域鏈?
一般情況下,變數取值到 建立 這個變數 的函式的作用域中取值
但是如果在當前作用域中沒有查到值,就會向上級作用域去查,直到查到全域性作用域,這麼一個查詢過程形成的鏈條就叫做作用域鏈
var x = 10;
function fn(){
console.log(x);
}
function show(f){
var x = 20;
f(); // 10
}
show(fn);
7、陣列的splice 與 slice 的區別?
方法 | 引數 |
---|---|
splice | splice(start, num, item1, item2, ...) |
slice | slice(start, end) |
8、substr 和 substring 的區別?
方法 | 引數 |
---|---|
substr | substr(start,length) |
substring | substring(start,end) |
9、includes 比 indexOf好在哪?
includes可以檢測NaN,indexOf不能檢測NaN,includes內部使用了Number.isNaN對NaN進行了匹配
10、下面程式碼輸出的結果?
for(var i = 0; i < 3; i++){
setTimeout(function(){
console.log(i);
},0);
};
答案:3,3,3
解決方法
for(let i = 0; i < 3; i++){
setTimeout(function(){
console.log(i);
},0);
};
// 0 1 2
for (var i = 0; i < 3; i++) {
(function(i) {
setTimeout(function () {
console.log(i);
}, 0, i)
})(i)
};
// 0 1 2
11、什麼是async/await?解決了什麼問題?
是generator + Promise的語法糖,主要的作用是用同步方式執行非同步操作,await只能在async函式中使用,async函式執行會返回一個Promise,值由函式的return值所決定
12、JS延遲載入的方法有哪些?
1、<script async src="script.js"></script>:給script標籤加async屬性,則載入和渲染後續文件元素的過程將和 script.js 的載入與執行並行進行(非同步)
2、<script defer src="script.js"></script>:給script標籤加defer屬性,載入後續文件元素的過程將和 script.js 的載入並行進行(非同步),但是 script.js 的執行要在所有元素解析完成之後,DOMContentLoaded 事件觸發之前完成
3、動態建立script標籤:等到DOMContentLoaded 事件觸發時,生成一個script標籤,渲染到頁面上上
4、setTimeout定時器延遲程式碼執行
13、new操作符為什麼能建立一個例項物件?
分析一下new的整個過程:
1、建立一個空物件
2、繼承建構函式的原型
3、this指向obj,並呼叫建構函式
4、返回物件
簡單實現一下new:
function myNew (fn, ...args) {
// 第一步:建立一個空物件
const obj = {}
// 第二步:繼承建構函式的原型
obj.__proto__ = fn.prototype
// 第三步:this指向obj,並呼叫建構函式
fn.apply(obj, args)
// 第四步:返回物件
return obj
}
14、什麼是文件碎片?
是什麼:一個容器,用於暫時存放建立的dom元素,使用document.createDocumentFragment()建立
有什麼用:將需要新增的大量元素先新增到文件碎片中,再將文件碎片新增到需要插入的位置,大大減少dom操作,提高效能
var oFragmeng = document.createDocumentFragment();
for(var i=0;i<10000;i++)
{
var op = document.createElement("span");
var oText = document.createTextNode(i);
op.appendChild(oText);
//先附加在文件碎片中
oFragmeng.appendChild(op);
}
//最後一次性新增到document中
document.body.appendChild(oFragmeng);
15、巨集任務與微任務有哪些?
巨集任務
# | 瀏覽器 | Node |
---|---|---|
I/O | ✅ | ✅ |
setTimeout | ✅ | ✅ |
setInterval | ✅ | ✅ |
setImmediate | ❌ | ✅ |
requestAnimationFrame | ✅ | ❌ |
微任務
# | 瀏覽器 | Node |
---|---|---|
Promise.prototype.then catch finally | ✅ | ✅ |
process.nextTick | ❌ | ✅ |
MutationObserver | ✅ | ❌ |
16、Object.defineProperty(target, key, options),options可傳什麼引數?
value:給target[key]設定初始值
get:呼叫target[key]時觸發
set:設定target[key]時觸發
writable:預設false,為true時此屬性才能被賦值運算子修改
enumerable:預設false,為true時此屬性才能被列舉
configurable:預設為false,為true時此屬性的描述符才能被修改,才能被刪除
17、什麼是防抖?什麼是節流?
操作 | 描述 | 場景 |
---|---|---|
防抖 | 頻繁去觸發一個事件,但是隻觸發最後一次。以最後一次為準 | 1、電腦息屏時間,每動一次電腦又重新計算時間 2、input框變化頻繁觸發事件可加防抖 3、頻繁點選按鈕提交表單可加防抖 |
節流 | 頻繁去觸發一個事件,但是隻能每隔一段時間觸發一次 | 1、滾動頻繁請求列表可加節流 2、遊戲里長按滑鼠,但是動作都是每隔一段時間做一次 |
18、什麼是高階函式?簡單實現一個?
高階函式:JavaScript的函式其實都指向某個變數。既然變數可以指向函式,函式的引數能接收變數,那麼一個函式就可以接收另一個函式作為引數,這種函式就稱之為高階函式。
// 簡單的高階函式
function add(x, y, f) {
return f(x) + f(y);
}
//用程式碼驗證一下:
add(-5, 6, Math.abs); // 11
像陣列的map、reduce、filter這些都是高階函式
19、什麼是函式柯里化?簡單實現一個?
柯里化,是把接受多個引數的函式變換成接受一個單一引數(最初函式的第一個引數)的函式,並且返回接受餘下的引數而且返回結果的新函式的技術。
// 普通的add函式
function add(x, y) {
return x + y
}
// Currying後
function curryingAdd(x) {
return function (y) {
return x + y
}
}
add(1, 2) // 3
curryingAdd(1)(2) // 3
好處
1、引數複用
// 正常正則驗證字串 reg.test(txt)
// 普通情況
function check(reg, txt) {
return reg.test(txt)
}
check(/\d+/g, 'test') //false
check(/[a-z]+/g, 'test') //true
// Currying後
function curryingCheck(reg) {
return function(txt) {
return reg.test(txt)
}
}
var hasNumber = curryingCheck(/\d+/g)
var hasLetter = curryingCheck(/[a-z]+/g)
hasNumber('test1') // true
hasNumber('testtest') // false
hasLetter('21212') // false
2、延遲執行 其實Function.prototype.bind就是科裡化的實現例子
function sayKey(key) {
console.log(this[key])
}
const person = {
name: 'Sunshine_Lin',
age: 23
}
// call不是科裡化
sayKey.call(person, 'name') // 立即輸出 Sunshine_Lin
sayKey.call(person, 'age') // 立即輸出 23
// bind是科裡化
const say = sayKey.bind(person) // 不執行
// 想執行再執行
say('name') // Sunshine_Lin
say('age') // 23
20、箭頭函式與普通函式的區別?
1、箭頭函式不能作為建構函式,不能new
2、箭頭函式沒有自己的this
3、箭頭函式沒有arguments物件
4、箭頭函式沒有原型物件
21、Symbol的應用場景?
使用Symbol充當屬性名
使用Symbol充當變數
使用Symbol實現私有屬性
22、AMD 和 CMD 的區別?
模組化 | 代表應用 | 特點 |
---|---|---|
AMD | require.js | 1、AMD的api預設一個當多個用 2、依賴前置,非同步執行 |
CMD | sea.js | 1、CMD的api嚴格區分,推崇職責單一 2、依賴就近,按需載入,同步執行 |
23、Commonjs 和 ES6 Module的區別?
1、前者是拷貝輸出,後者是引用輸出
2、前者可修改引入值,後者只讀
3、前者是執行時,後者是編譯時
24、為什麼Commonjs不適用於瀏覽器
var math = require('math');
math.add(2, 3);
第二行math.add(2, 3),在第一行require('math')之後執行,因此必須等math.js載入完成。也就是說,如果載入時間很長,整個應用就會停在那裡等。
這對伺服器端不是一個問題,因為所有的模組都存放在本地硬碟,可以同步載入完成,等待時間就是硬碟的讀取時間。但是,對於瀏覽器,這卻是一個大問題,因為模組都放在伺服器端,等待時間取決於網速的快慢,可能要等很長時間,瀏覽器處於"假死"狀態。
因此,瀏覽器端的模組,不能採用"同步載入"(synchronous),只能採用"非同步載入"(asynchronous)。這就是AMD規範誕生的背景。
25、函式的length是多少?
length 是函式物件的一個屬性值,指該函式有多少個必須要傳入的引數,即形參的個數。形參的數量不包括剩餘引數個數,僅包括第一個具有預設值之前的引數個數
26、深度遍歷廣度遍歷的區別?
對於演算法來說 無非就是時間換空間 空間換時間
1、深度優先不需要記住所有的節點, 所以佔用空間小, 而廣度優先需要先記錄所有的節點佔用空間大
2、深度優先有回溯的操作(沒有路走了需要回頭)所以相對而言時間會長一點
3、深度優先採用的是堆疊的形式, 即先進後出
4、廣度優先則採用的是佇列的形式, 即先進先出
27、JS中的設計模式有哪些?
建立模式:該模式抽象了物件例項化過程。
結構型模式:這些模式處理不同的類和物件以提供新功能。
行為模式:也稱釋出-訂閱模式,定義了一個被觀察者和多個觀察者的、一對多的物件關係。
並行設計模式:這些模式處理多執行緒程式設計範例。
架構設計模式:這些模式用於處理架構設計
28、JS中如何將頁面重定向到另一個頁面?
1、使用 location.href:window.location.href =“https://www.baidu.com/”)
2、使用 location.replace:window.location.replace(" https://www.baidu.com/;")
29、JS中滑鼠事件的各個座標?
屬性 | 說明 | 相容性 |
---|---|---|
offsetX | 以當前的目標元素左上角為原點,定位x軸座標 | 除Mozilla外都相容 |
offsetY | 以當前的目標元素左上角為原點,定位y軸座標 | 除Mozilla外都相容 |
clientX | 以瀏覽器可視視窗左上角為原點,定位x軸座標 | 都相容 |
clientY | 以瀏覽器可視視窗左上角為原點,定位y軸座標 | 都相容 |
pageX | 以doument物件左上角為原點,定位x軸座標 | 除IE外都相容 |
pageY | 以doument物件左上角為原點,定位y軸座標 | 除IE外都相容 |
screenX | 以計算機螢幕左上頂角為原點,定位x軸座標(多螢幕會影響) | 全相容 |
screenY | 以計算機螢幕左上頂角為原點,定位y軸座標 | 全相容 |
layerX | 最近的絕對定位的父元素(如果沒有,則為 document 物件)左上頂角為元素,定位 x 軸座標 | Mozilla 和 Safari |
layerY | 最近的絕對定位的父元素(如果沒有,則為 document 物件)左上頂角為元素,定位 y 軸座標 | Mozilla 和 Safari |
30、JS中元素檢視的各個尺寸?
屬性 | 說明 |
---|---|
offsetLeft | 獲取當前元素到定位父節點的left方向的距離 |
offsetTop | 獲取當前元素到定位父節點的top方向的距離 |
offsetWidth | 獲取當前元素 width + 左右padding + 左右border-width |
offsetHeight | 獲取當前元素 height + 上下padding + 上下border-width |
clientWidth | 獲取當前元素 width + 左右padding |
clientHeight | 獲取當前元素 height + 上下padding |
scrollWidth | 當前元素內容真實的寬度,內容不超出盒子寬度時為盒子的clientWidth |
scrollHeight | 當前元素內容真實的高度,內容不超出盒子高度時為盒子的clientHeight |
31、Window檢視的各個尺寸?
屬性 | 說明 |
---|---|
innerWidth | innerWidth 瀏覽器視窗可視區寬度(不包括瀏覽器控制檯、選單欄、工具欄) |
innerHeight | innerHeight 瀏覽器視窗可視區高度(不包括瀏覽器控制檯、選單欄、工具欄) |
32、Document文件檢視的各個尺寸?
屬性 | 說明 |
---|---|
document.documentElement.clientWidth | 瀏覽器視窗可視區寬度(不包括瀏覽器控制檯、選單欄、工具欄、滾動條) |
document.documentElement.clientHeight | 瀏覽器視窗可視區高度(不包括瀏覽器控制檯、選單欄、工具欄、滾動條) |
document.documentElement.offsetHeight | 獲取整個文件的高度(包含body的margin) |
document.body.offsetHeight | 獲取整個文件的高度(不包含body的margin) |
document.documentElement.scrollTop | 返回文件的滾動top方向的距離(當視窗發生滾動時值改變) |
document.documentElement.scrollLeft | 返回文件的滾動left方向的距離(當視窗發生滾動時值改變) |
33、監聽ajax上傳進度
//【上傳進度呼叫方法實現】
xhr.upload.onprogress = progressFunction