
在學(xué)js的過(guò)程中,記錄一些零碎的小知識(shí),以便以后翻看。持續(xù)更新……
學(xué)習(xí)資料:JavaScript教程 以及 《你不知道的JavaScript》系列叢書
- localstorage:保存用戶更改,可用于覆蓋當(dāng)前頁(yè)面已修改的hash,避免瀏覽器刷新后更改信息丟失。(以后補(bǔ)充和cookie的區(qū)別)
- example.com/favicon.ico,favicon.ico用于獲取當(dāng)前網(wǎng)站的title圖標(biāo)
- 變量提升:JavaScript 引擎的工作方式是,先解析代碼,獲取所有被聲明的變量,然后再一行一行地運(yùn)行。這造成的結(jié)果,就是所有的變量的聲明語(yǔ)句,都會(huì)被提升到代碼的頭部,這就叫做變量提升(hoisting)。
console.log(a) // undefined
var a = 1
- JavaScript 使用大括號(hào),將多個(gè)相關(guān)的語(yǔ)句組合在一起,稱為“區(qū)塊”(block),對(duì)于var命令來(lái)說(shuō),JavaScript 的區(qū)塊不構(gòu)成單獨(dú)的作用域(scope)。
{
var a = 1;
}
a // 1
在區(qū)塊外部,變量a依然有效,ES6為了改變這種現(xiàn)狀,引入了let:
{
let a = 1;
}
a // undefined
- 關(guān)于是否添加分號(hào):尤雨溪的回答
總結(jié)下來(lái)就是一句話:一行開(kāi)頭是括號(hào)或者方括號(hào)的時(shí)候加上分號(hào)就可以了,其他時(shí)候全部不需要。 - 如果存在多重循環(huán),不帶參數(shù)的break語(yǔ)句和continue語(yǔ)句都只針對(duì)最內(nèi)層循環(huán)。
- 語(yǔ)句的前面有標(biāo)簽(label),用于跳轉(zhuǎn)到程序的任意位置,通常與break語(yǔ)句和continue語(yǔ)句配合使用,跳出特定的循環(huán)或者代碼塊。
- 七大數(shù)據(jù)類型:
- number
- string
- boolean
- undefined
- null
- symbol
- object
object細(xì)分為:object(狹義),array,function
- 三種類型準(zhǔn)換的方法:typeof,instanceof,Object.prototype.toString
var obj = { }, arr = [ ]
typeof obj // object
typeof arr // object
arr instanceof Array // true
obj instanceof Array // false
typeof NaN // number
typeof Ifinity // number
typeof null // object
function f(){}
typeof f // function
數(shù)組或?qū)ο髸?huì)先調(diào)用valueOf()獲取原始值,然后調(diào)用toString()轉(zhuǎn)化成字符串,然后調(diào)用Number()轉(zhuǎn)成數(shù)字,Boolean類型也是調(diào)用Number()轉(zhuǎn)化成數(shù)字。
參考:js面試題大坑——隱式類型轉(zhuǎn)換
Number(null) // 0
5 + null // 5
Number(undefined) // NaN
5 + undefined // NaN
神代碼:
(!(~+[])+{})[--[~+""][+[]]*[~+[]]+~~!+[]]+({}+[])[[~!+[]*~+[]]] = sb
- 如果 JavaScript 預(yù)期某個(gè)位置應(yīng)該是布爾值,會(huì)將該位置上現(xiàn)有的值自動(dòng)轉(zhuǎn)為布爾值。轉(zhuǎn)換規(guī)則是除了下面六個(gè)值被轉(zhuǎn)為false,其他值都視為true。
- undefined
- null
- false
- 0
- NaN
- " " 或 ' '
event.target 和 event.currentTaget的區(qū)別,以后整理為博客,先參考這篇
typeof valueOf instanceof的用法,區(qū)別,輸出結(jié)果博客總結(jié)
js現(xiàn)階段主要掌握用法:改變?cè)氐腸lass,比如添加和取消"active",具體的樣式交給CSS
盡量不要用瀏覽器提供的API,容易出bug
nextSibling找兄弟的時(shí)候:記住nodeType的1,3狀態(tài)。1是元素,3是文字以及各種空格回車制表符。不過(guò)更常用nextElementSibling
記住常用DOM操作的API,出博客
setInterval() clearInterval() setTimeout()
如果忘了使用new命令,直接調(diào)用構(gòu)造函數(shù)會(huì)發(fā)生什么事?
這種情況下,構(gòu)造函數(shù)就變成了普通函數(shù),并不會(huì)生成實(shí)例對(duì)象。而且由于后面會(huì)說(shuō)到的原因,this這時(shí)代表全局對(duì)象,將造成一些意想不到的結(jié)果。
運(yùn)算符:見(jiàn)博客
當(dāng)需要迅速先hide()再show()的時(shí)候,瀏覽器會(huì)自動(dòng)合并這個(gè)操作,也就是忽略掉hide(),此時(shí)可以在hide()之后調(diào)用offset()來(lái)打斷瀏覽器這一行為。因?yàn)閛ffset()會(huì)計(jì)算當(dāng)前CSS中涉及變量的偏移。
寫輪播圖時(shí),寬高在HTML寫死的原因:作為圖片站位符,防止圖片加載不均勻發(fā)生重排(re-layout),重排時(shí)圖片倒退,會(huì)降低效率,很耗內(nèi)存。
這個(gè)手段常用于頁(yè)面性能優(yōu)化。
狀態(tài)機(jī)的編程思想:
指導(dǎo)思想:HTML、CSS和JS:內(nèi)容、樣式和行為分離:
即
- 不要用HTML控制樣式(<center>...</center>)
- 不要用CSS控制行為(IE下的expression,效率低下)
- 不要用js控制樣式(
div.show(),會(huì)改變display;最好只用js更改class:$div.classList.add('disable'))
.one():為元素添加一個(gè)事件處理,只執(zhí)行一次。
transitionend事件會(huì)在CSS transition結(jié)束后觸發(fā),無(wú)縫輪播中有用到。
“點(diǎn)擊別處消失”的實(shí)現(xiàn)方法:(遮蔽罩?)
(1)點(diǎn)擊元素自身處理
(2)用jq封裝好的
dispatchEvent & fireEvent
如果是被點(diǎn)擊的節(jié)點(diǎn)同時(shí)擁有捕獲和冒泡,那么執(zhí)行順序和添加順序一致;其他情況都是優(yōu)先捕獲。
mouseenter:鼠標(biāo)進(jìn)入一個(gè)節(jié)點(diǎn)時(shí)觸發(fā),進(jìn)入子節(jié)點(diǎn)不會(huì)觸發(fā)這個(gè)事件
mouseover:鼠標(biāo)進(jìn)入一個(gè)節(jié)點(diǎn)時(shí)觸發(fā),進(jìn)入子節(jié)點(diǎn)會(huì)再一次觸發(fā)這個(gè)事件
mouseout:鼠標(biāo)離開(kāi)一個(gè)節(jié)點(diǎn)時(shí)觸發(fā),離開(kāi)父節(jié)點(diǎn)也會(huì)觸發(fā)這個(gè)事件
mouseleave:鼠標(biāo)離開(kāi)一個(gè)節(jié)點(diǎn)時(shí)觸發(fā),離開(kāi)父節(jié)點(diǎn)不會(huì)觸發(fā)這個(gè)事件
- click事件指的是,用戶在同一個(gè)位置先完成mousedown動(dòng)作,再完成mouseup動(dòng)作。因此,觸發(fā)順序是,mousedown首先觸發(fā),mouseup接著觸發(fā),click最后觸發(fā)。
dblclick事件則會(huì)在mousedown、mouseup、click之后觸發(fā)。
(1)clientX、clientY
點(diǎn)擊位置距離當(dāng)前body可視區(qū)域的x,y坐標(biāo)
(2)pageX、pageY
對(duì)于整個(gè)頁(yè)面來(lái)說(shuō),包括了被卷去的body部分的長(zhǎng)度
(3)screenX、screenY
點(diǎn)擊位置距離當(dāng)前電腦屏幕的x,y坐標(biāo)
(4)offsetX、offsetY
相對(duì)于帶有定位的父盒子的x,y坐標(biāo)
MouseEvent.offsetX屬性返回鼠標(biāo)位置與目標(biāo)節(jié)點(diǎn)左側(cè)的padding邊緣的水平距離(單位像素)
(5)x、y
和screenX、screenY一樣
- 鍵盤事件由用戶擊打鍵盤觸發(fā),主要有keydown、keypress、keyup三個(gè)事件,它們都繼承了KeyboardEvent接口。
- keydown:按下鍵盤時(shí)觸發(fā)。
- keypress:按下有值的鍵時(shí)觸發(fā),即按下 Ctrl、Alt、Shift、Meta 這樣無(wú)值的鍵,這個(gè)事件不會(huì)觸發(fā)。對(duì)于有值的鍵,按下時(shí)先觸發(fā)keydown事件,再觸發(fā)這個(gè)事件。
- keyup:松開(kāi)鍵盤時(shí)觸發(fā)該事件。
鼠標(biāo)的事件屬性。
onclick
ondblclick
onmousedown
onmouseenter
onmouseleave
onmousemove
onmouseout
onmouseover
onmouseup
onwheel
鍵盤的事件屬性。
onkeydown
onkeypress
onkeyup
焦點(diǎn)的事件屬性。
onblur
onfocus
表單的事件屬性。
oninput
onchange
onsubmit
onreset
oninvalid
onselect
觸摸的事件屬性。
ontouchcancel
ontouchend
ontouchmove
ontouchstart
拖動(dòng)的事件屬性分成兩類:一類與被拖動(dòng)元素相關(guān),另一類與接收被拖動(dòng)元素的容器元素相關(guān)。
被拖動(dòng)元素的事件屬性。
ondragstart:拖動(dòng)開(kāi)始
ondrag:拖動(dòng)過(guò)程中,每隔幾百毫秒觸發(fā)一次
ondragend:拖動(dòng)結(jié)束
接收被拖動(dòng)元素的容器元素的事件屬性。
ondragenter:被拖動(dòng)元素進(jìn)入容器元素。
ondragleave:被拖動(dòng)元素離開(kāi)容器元素。
ondragover:被拖動(dòng)元素在容器元素上方,每隔幾百毫秒觸發(fā)一次。
ondrop:松開(kāi)鼠標(biāo)后,被拖動(dòng)元素放入容器元素。
<dialog>對(duì)話框元素的事件屬性。
oncancel
onclose
- 當(dāng)需要響應(yīng)式布局時(shí),不要用img標(biāo)簽,用 div 的 background 來(lái)設(shè)置圖片,而且還可以加個(gè)懶加載什么的
background: transparent url(...) no-repeat center;
background-size: cover;
display: flow-root; // 只有一個(gè)作用,觸發(fā)BFC
為什么 let 和 const 不存在變量提升呢?
這是因?yàn)樵诰幾g階段, 當(dāng)遇到變量聲明時(shí), 編譯器要么將它提升至作用域頂部(var 聲明), 要么將它放到 臨時(shí)死區(qū)(temporal dead zone, TDZ), 也就是用 let 或 const 聲明的變量. 訪問(wèn) TDZ 中的變量會(huì)觸發(fā)運(yùn)行時(shí)的錯(cuò)誤, 只有執(zhí)行過(guò)變量聲明語(yǔ)句后, 變量才會(huì)從 TDZ 中移出, 這時(shí)才可訪問(wèn).
下面這個(gè)例子你能不能全部答對(duì).
typeof null; // 'object'
typeof []; // 'object'
typeof someStr; // 'undefined'
typeof str; // Uncaught ReferenceError: str is not defined
const str = 'Yancey';
第一個(gè), 因?yàn)?null 根本上是一個(gè)指針, 所以會(huì)返回 'object'. 深層次一點(diǎn), 不同的對(duì)象在底層都表示為二進(jìn)制, 在 Javascript 中二進(jìn)制前三位都為 0 的會(huì)被判斷為 Object 類型, null 的二進(jìn)制全為 0, 自然前三位也是 0, 所以執(zhí)行 typeof 時(shí)會(huì)返回 'object'.
第二個(gè)想強(qiáng)調(diào)的是, typeof 判斷一個(gè)引用類型的變量, 拿到的都是 'object', 因此該操作符無(wú)法正確辨別具體的類型, 如 Array 還是 RegExp.
第三個(gè), 當(dāng) typeof 一個(gè) 未聲明 的變量, 不會(huì)報(bào)錯(cuò), 而是返回 'undefined'
第四個(gè), str 先是存在于 TDZ, 上面說(shuō)到訪問(wèn) TDZ 中的變量會(huì)觸發(fā)運(yùn)行時(shí)的錯(cuò)誤, 所以這段代碼直接報(bào)錯(cuò).
javascript:void($={}) 使不能復(fù)制的頁(yè)面可以復(fù)制(原理??)
瀏覽器渲染機(jī)制(reflow && repaint)
flex布局中,對(duì)需要右對(duì)齊的元素設(shè)置margin-left: auto即可
圖片居中HTML5:

Object.assign 方法可以很方便地一次向類添加多個(gè)方法。
類的內(nèi)部所有定義的方法,都是不可枚舉的(non-enumerable)。
class Point {
constructor(x, y) {
// ...
}
toString() {
// ...
}
}
Object.keys(Point.prototype)
// []
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]
上面代碼中,toString 方法是 Point 類內(nèi)部定義的方法,它是不可枚舉的。這一點(diǎn)與 ES5 的行為不一致。
ES6 規(guī)定,在子類普通方法中通過(guò)super調(diào)用父類的方法時(shí),方法內(nèi)部的this指向當(dāng)前的子類實(shí)例。
class A {
constructor() {
this.x = 1;
}
print() {
console.log(this.x);
}
}
class B extends A {
constructor() {
super();
this.x = 2;
}
m() {
super.print();
}
}
let b = new B();
b.m() // 2
上面代碼中,super.print()雖然調(diào)用的是A.prototype.print(),但是A.prototype.print()內(nèi)部的this指向子類B的實(shí)例,導(dǎo)致輸出的是2,而不是1。也就是說(shuō),實(shí)際上執(zhí)行的是super.print.call(this)。
