題目三
- 說(shuō)一下對(duì)變量提升的理解
- 變量定義(提升)
- 函數(shù)聲明(提升)
- 說(shuō)明
this幾種不同的使用場(chǎng)景 - 創(chuàng)建 10 個(gè)
<a>標(biāo)簽, 點(diǎn)擊的時(shí)候彈出不同的序號(hào)for(var i = 0; i < 10; i++) { (function(i){ var a = document.createElement('a') a.innerHTML =i + '<br>' a.addEventListener('click', function(e){ console.log(i) }) document.body.appendChild(a) })(i) } - 如何理解作用域
- 自由變量
- 作用域鏈,查找自由變量
- 閉包的兩個(gè)場(chǎng)景
- 實(shí)際開發(fā)中閉包的應(yīng)用
// 封裝變量, 收斂權(quán)限 function isFirstLoad() { var _list = [] return function (id) { if (_list.indexOf(id) >=0 ) { return false } else { _list.push(id) return true } } } var firstLoad = isFirstLoad() console.log(firstLoad(10)) // true console.log(firstLoad(10)) // false console.log(firstLoad(20)) // true
知識(shí)點(diǎn)
- 執(zhí)行上下文
- 范圍: 一段
<script>或者一個(gè)函數(shù) - 全局: 變量定義, 函數(shù)聲明, 一段
<script> - 函數(shù): 變量定義, 函數(shù)聲明,
this arguments函數(shù)
<script>
console.log(a) // undefined 變量提升
var a = 100
fn('yym') // 'yym' 20
function fn(name) { // 函數(shù)聲明 提升
age = 20
console.log(name,age)
var age
}
</script>
this
-
this要在執(zhí)行時(shí)才能確認(rèn)值, 定義時(shí)無(wú)法確認(rèn)- 作為構(gòu)造函數(shù)執(zhí)行
- 作為對(duì)象屬性執(zhí)行
- 作為普通函數(shù)執(zhí)行
call apply bind
var a = {
name: 'yym',
fn: function () {
console.log(this.name)
}
}
// 不看下面, 上面不能確定this指啥
a.fn() // this === a
a.fn.call({name: 'B'}) // this === {name: B}
var fn1 = a.fn
fn1() // this === window
代碼演示
function Foo(name) {
// this = {}
this.name = name
// return this
}
var f = new Foo('yym') // 構(gòu)造函數(shù)的 this
var obj = {
name: 'A',
printName: function () {
console.log(this.name)
}
}
obj.printName() // 作為對(duì)象屬性執(zhí)行 this === Obj
function fn () {
console.log(this)
}
fn() // 作為普通函數(shù)執(zhí)行 this === window
function fn1 (name) {
console.log(this)
}
fn1.call({x: 100}, 'yym') // call this === {x: 100} apply 第二個(gè)參數(shù)是數(shù)組
var fn2 = function (name) {
console.log(this)
}.bind({y: 150}) // .bind 是一個(gè)函數(shù)表達(dá)式
fn2('yym') // this === {y:150}
- 作用域
- JS沒有塊級(jí)作用域
- 只有函數(shù)和全局作用域
// 無(wú)塊級(jí)作用域
if (true) {
var name = 'yym'
}
console.log(name) // 可以訪問到 var name = 'yym'
// 函數(shù)和全局作用域
var a = 100
function fn() {
var a = 200
console.log('fn', a) // fn 200
}
console.log('global', a) // global 100
fn()
- 作用域鏈
var a = 100
function fn () {
var b = 200
// 當(dāng)前作用域沒有定義的變量, 即'自由變量'
console.log(a) // 在當(dāng)前作用域找不到變量 a, 去父級(jí)作用域去找
console.log(b)
}
var a = 100
function F1 () {
var b = 200
function F2() {
// 當(dāng)前作用域沒有定義的變量, 即'自由變量'
console.log(a)
console.log(b)
console.log(c)
}
F2()
}
F1()
有 3個(gè)作用域: F2作用域, F1作用域, 全局作用域
a 在 F2 中沒有, 去F1 作用域找, 沒有, 繼續(xù)去全局作用域找
b 在 F2 中沒有, 在F1 作用域找到了
- 閉包
function F1() {
var a = 100
// 返回一個(gè)函數(shù), (函數(shù)作為返回值)
return function () {
console.log(a) // 自由變量, 到父級(jí)作用域去找
}
}
var f1 = F1()
var a = 200
f1() // 100
- 閉包的使用場(chǎng)景
- 函數(shù)作為返回值
- 函數(shù)作為參數(shù)傳遞
// 函數(shù)作為參數(shù)傳遞
function F1() {
var a = 100
return function () {
console.log(a) // 自由變量, 到父級(jí)作用域去找
}
}
var f1 = F1()
function F2(fn) {
var a = 200
fn()
}
F2(f1) // 把f1 作為參數(shù)傳進(jìn)去 100
題目四
- 同步和異步的區(qū)別是什么? 分別舉一個(gè)同步和異步的例子
- 同步會(huì)阻塞代碼執(zhí)行, 而異步不會(huì)
- alert是同步, setTimeout是異步
- 一個(gè)關(guān)于setTimeout的筆試題
console.log(1) setTimeout(() => { console.log(2) }, 0) console.log(3) setTimeout(() => { console.log(4) }, 1000) console.log(5) // 1 3 5 2 1s后打印 4 - 前端使用異步的場(chǎng)景有哪些
ajax 動(dòng)態(tài)<img>加載setTImeout setInterval- 事件綁定
知識(shí)點(diǎn)
- 什么是異步 (對(duì)比同步)
console.log(100)
setTimeout(() => {
console.log(200)
}, 1000)
console.log(300)
如果是同步: 先打印100, 停頓1s后打印200, 然后打印300, 這肯定不是我們希望的,我們不希望它停頓
異步: 打印100, 打印300, 1s后打印200,不阻礙后面程序的加載
console.log(100)
alert(200) // 你什么時(shí)候點(diǎn)掉,什么時(shí)候執(zhí)行后面的,會(huì)卡在那兒
console.log(300)
- 前端使用異步的場(chǎng)景
在可能發(fā)生等待的情況
等待過程中不能像alert一樣阻塞程序進(jìn)行
-
"等待的情況" 都需要異步
- 定時(shí)任務(wù):
setTimeout setInterval - 網(wǎng)絡(luò)請(qǐng)求:
ajax請(qǐng)求, 動(dòng)態(tài)<img>加載 - 事件綁定
// ajax請(qǐng)求, 異步 console.log('start') // 1.start $.get('url',function(data1) { // 異步 3.data1 console.log('data1') }) console.log('end') // 2.end // 事件綁定 異步 console.log('start') // 1.start $('#app').addEventListener('click', function () { alert('clicked') }) console.log('end') // 2.end - 定時(shí)任務(wù):
- 異步和單線程
- JavaScript是單線程語(yǔ)言,因此,在一個(gè)進(jìn)程上,只能運(yùn)行一個(gè)線程,而不能多個(gè)線程同時(shí)運(yùn)行。也就是說(shuō)JavaScript不允許多個(gè)線程共享內(nèi)存空間。因此,如果有多個(gè)線程想同時(shí)運(yùn)行,則需采取排隊(duì)的方式,即只有當(dāng)前一個(gè)線程執(zhí)行完畢,后一個(gè)線程才開始執(zhí)行。
- 任務(wù)隊(duì)列
- 單線程就意味著,所有任務(wù)(線程)需要排隊(duì),前一個(gè)任務(wù)結(jié)束,才會(huì)執(zhí)行后一個(gè)任務(wù)。如果前一個(gè)任務(wù)耗時(shí)很長(zhǎng),后一個(gè)任務(wù)不得不一直等待。
- 同步任務(wù)指的是,在主線程上排隊(duì)執(zhí)行的任務(wù),只有前一個(gè)任務(wù)執(zhí)行完畢,后一個(gè)任務(wù)才會(huì)執(zhí)行;異步任務(wù)指的是不進(jìn)入主線程、而進(jìn)入任務(wù)隊(duì)列的任務(wù),只有當(dāng)主線程上的所有同步任務(wù)執(zhí)行完畢之后,主線程才會(huì)讀取任務(wù)隊(duì)列,開始執(zhí)行異步任務(wù)。
console.log(100)
setTimeout(() => {
console.log(200)
})
console.log(300)
執(zhí)行過程: 先打印100 , 遇到setTImeout異步會(huì)把里面的東西放到任務(wù)隊(duì)列, 在打印 300,打印完成, 然后執(zhí)行任務(wù)隊(duì)列的工作
函數(shù) setTimeout 接受兩個(gè)參數(shù):待加入隊(duì)列的消息和一個(gè)延遲(可選,默認(rèn)為0)。這個(gè)延遲代表了消息被實(shí)際加入到隊(duì)列的最
小延遲時(shí)間。如果隊(duì)列中沒有其它消息,在這段延遲時(shí)間過去之后,消息會(huì)被馬上處理。但是,如果有其它消息,
setTimeout 消息必須等待其它消息處理完。因此第二個(gè)參數(shù)僅僅表示最少延遲時(shí)間,而非確切的等待時(shí)間。
題目五
- 獲取2019-02-10格式的日期
function formatDate(dt) { if (!dt) { dt = new Date() } var year = dt.getFullYear() var month = dt.getMonth() + 1 var date = dt.getDate() if (month < 10) { // 強(qiáng)制類型轉(zhuǎn)換 month = '0' + month } if (date < 10) { // 強(qiáng)制類型轉(zhuǎn)換 date = '0' + date } // 強(qiáng)制類型轉(zhuǎn)換 return year + '-' + month + '-' + date } console.log(formatDate()) - 獲取隨機(jī)數(shù),要求長(zhǎng)度一致的字符串格式
var random =Math.random(); random = random+'0000000000' random = random.slice(0,10) console.log(random) - 寫一個(gè)能遍歷對(duì)象和數(shù)組的通用
forEach函數(shù)function forEach(obj,fn) { var key if (obj instanceof Array) { //判斷是不是數(shù)組 obj.forEach(function (item, index) { fn(index, item) }) } else { // 不是數(shù)組就是對(duì)象 for (key in obj) { fn(key, obj[key]) } } } var arr = [1, 2, 3] forEach(arr, function (index, item) { console.log(index, item) }) var obj = {x: 100, y: 200} forEach(obj, function(key, value) { console.log(key, value) })
知識(shí)點(diǎn)
- 日期
Date.now() // 獲取當(dāng)前時(shí)間的毫秒數(shù) 1549788153194
var dt = new Date()
dt.getTime() // 獲取毫秒數(shù)
dt.getFullYear() // 得到年
dt.getMonth() // 獲取的是 0-11, 所以要 + 1
dt.getDate() // 獲取日 0-31
dt.getHours() // 獲取小時(shí) 0-23
dt.getMinutes() // 獲取分鐘 0-59
dt.getSeconds() // 獲取秒 0-59
- Math
- 獲取隨機(jī)數(shù)
Math.random()
- 數(shù)組
API
-
forEach遍歷所有元素 -
every判斷所有元素是否都符合條件 -
some判斷是否至少一個(gè)元素符合條件 -
sort排序 -
map對(duì)元素重新組裝,生成新數(shù)組 -
filter過濾符合條件的元素
var arr = [1,2,3]
arr.forEach(function (item,index) {
// 遍歷數(shù)組所有元素
console.log(index,item)
})
var result = arr.every(function (item, index) {
// 用來(lái)判斷所有的數(shù)組元素,都滿足一個(gè)條件
if( item < 4) {
return true
}
})
console.log(result) // true
var result = arr.some(function (item, index) {
// 用來(lái)判斷所有的數(shù)組元素, 只要有一個(gè)滿足條件即可
if( item < 2) {
return true
}
})
console.log(result) // true
var arr = [1,4,3,5,2]
var arr2 = arr.sort(function (a, b) {
// 從小到大排序
return a - b
})
console.log(arr2)
var arr = [1,2,3,4]
var arr2 = arr.map(function(item,index) {
// 將元素重新組裝, 并返回
return item * 2
})
console.log(arr2)
var arr = [1,2,3]
var arr2 = arr.filter(function(item,index) {
// 通過某一條件過濾
if (item >= 2) {
return true
}
})
console.log(arr2) // [2, 3]
- 對(duì)象API
for in
var obj = {
x: 100,
y: 200,
z: 300
}
var key
for (key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key, obj[key])
}
}