
# 題1
JS 中 8 種數據類型:
布爾(Boolean)、
字符串(String)、
數字(Number)、
對象(object)、
undefined、
null、
Symbol、
BigInt。
# 題2
輸出結果:555555(6個5)
原因:setTimeout 是異步的代碼,異步代碼最后執行,所以代碼的執行順序是1:先循環 2打印i 3 5次setTime。 第1步執行完之后 i 就已經是5了,所以后面六次打印都是 5。
# 題3
輸出:501234
原因:循環中的 setTimeout 是異步的,所以最后執行,所以先循環,然后打印i,先輸出5,然后每次循環中都調用一個匿名函數,并把 i 傳到函數中,i在傳值是是按值傳遞,依次傳入函數中的值是 01234,所以打印出來的也是 01234。
圖解:

擴展:類似的面試題,以下程序輸出結果是?

答:函數外打印i 報錯,剩下的輸出結果是01234。
let 可以定義塊級作用域,只能在循環中使用。
# 題4
typeof:查看一個變量的數據類型。返回值是:null、string、object、boolean 等數據類型
instanceof:查看一個對象是否是另一個對象的子對象(查看原型鏈),返回值是:boolean。

# 題5
實現思路:
1. 為 body 綁定一個 `mouseover` 事件
2. 通過事件對象獲取鼠標的信息(事件對象:回調函數上的參數,包含了事件的信息)
3. 設置圖片為絕對定位,并設置left、top屬性和鼠標位置相同
~~~
// 先初始化圖片
const img = document.createElement('IMG')
img.src = 'https://img14.360buyimg.com/babel/s1180x940_jfs/t1/115462/17/8922/86672/5ed4824dE79c7d70e/fa0f1f71baa04b5b.jpg.webp'
img.style.width = '100px'
img.style.height = '100px'
img.style.position = 'absolute'
img.style.left = 0
img.style.top = 0
document.body.appendChild(img)
// 寫法一、DOM0級事件(只能在冒泡階段觸發)
// e:事件對象
document.onmousemove = function(e) {
img.style.left = e.clientX + 'px'
img.style.top = e.clientY + 'px'
}
// 寫法二、DOM2級事件
// 第三個參數:是否在捕獲階段觸發,默認是 false(冒泡階段)
document.addEventListener('mousemove', function(e){
img.style.left = e.clientX + 'px'
img.style.top = e.clientY + 'px'
}, false)
~~~
# 題6
~~~
// 從數組中隨機抽取n個數
// 參數一、數組
// 參數二、n(隨機抽取幾個)
// 版本:有可能重復
function randomSelect(arr, n) {
// 保存最終的結果
let ret = []
// 循環 n 次
for(let i=0; i<n ; i++) {
// 生成一個 [0 ~ arr.length) 的隨機數
let index = Math.floor(Math.random() * arr.length)
// 根據隨機下標取出數
ret.push(arr[index])
}
return ret
}
// 版本不重復
function randomSelectUni(arr, n) {
// 保存最終的結果
let ret = []
// 生成一個 [0 ~ arr.length) 的隨機數
let index = Math.floor(Math.random() * arr.length)
// 循環 n 次
for(let i=0; i<n ; i++) {
// 如果隨機的這個數之前已經取過了,就重新計算隨機數
// indexOf 也可以使用 includes 來判斷數組中是否已經存在
while( ret.indexOf(arr[index]) !== -1 ) {
index = Math.floor(Math.random() * arr.length)
}
// 根據隨機下標取出數
ret.push(arr[index])
}
return ret
}
~~~
# 題7
這三個都是操作數組的函數。
- map:循環并處理數組中的每一個元素。
返回值:處理完之后的新數組。
不修改原數組。
~~~
let a = [1,2,3,4,5,6,7]
// 把 a 中的每個數擴大 10 倍,得到一個新數組
let b = a.map(v => v*10 )
~~~
- filter(過濾)
循環數組中的每一個元素,當滿一個條件時才返回,否則就過濾掉。
返回值:過濾完之后剩下滿足條件的元素的新組件。
不修改原數組。
~~~
let a = [
{
id: 12,
name: '手機'
},
{
id: 35,
name: '電腦'
}
]
// 過濾出商品ID大于20的商品
let b = a.filter(v=>v.id>20)
~~~
- reduce(累加)
循環數組中每一個元素,將每個元素中的值累加到一起。
返回值:累加之后的結果
不修改原數組。
~~~
let a = [
{
id: 12,
name: '手機',
price: 213
},
{
id: 35,
name: '電腦',
price: 435
}
]
// 計算出所有商品的總價格
// 參數一、total:每次累加的結果,也是最終的返回值
// 參數二、循環時數組中的每個元素
// 0:total 累加之前的初始值
let totalPrice = a.reduce( (total, v) => total+v.price, 0)
// 另一個例子
let a = [1,2,3,4,5,6,7]
// 對數組中所有的元素求和
// total 是累加之后的和,初始值為0
// 每循環一次把當前值加到 total 上,結果做為下次循環的 total
let sum = a.reduce( (total, v) => total+v , 0)
~~~
# 題8
異步加載:可以并發同時加載多個文件。
延遲加載:先不加載,當用到時才開始加載。
網頁中加載一個資源(CSS、JS、圖片等等)分為:
同步加載:加載完一個之后再加載下一個(一個一個的加載),這種加載有可能出現阻塞(某一個資源始終加載不出來就會等在這里)
異步加載:同時加載多個文件,這種不會出現阻塞。
延遲加載:先不加載,當使用到這個資源時再加載。比如:京東首面,默認只加載第一屏的商品數據,當向下滾動滾動條時才加載下一屏的商品,如果不滾動就不再加載后面的商品。
# 題9
問題一、async...await 是 ES8 中出的可以以同步的方式編寫異步代碼的一種技術。
問題二、它其實是 Generator(生成器) 的語法糖。
(ES6 文檔上寫的)
語法糖:這個語法是為了簡寫另一個語法而存在 的,它本身不能需要,需要先轉成另一種語法 才能運行。
比如:ES6中的 class(定義類,就是一種語法糖)
~~~
// es6 中定義一個類
class People {
hello() {
}
}
// 以上是語法糖,是以下代碼的語法糖(需要先轉成下面這樣才能運行)
function People(){
}
People.prototype.hello = function() {
}
~~~
# 題10
1. 原生JS 使用 AJAX 調用 接口

2. 渲染返回的數據(DOM操作)

擴展:將 AJAX 封裝成一個 Promise 對象的用法

擴展:如何使用 ES8 中的 async...await
