詳解clientWidth,scrollWidth评雌,offsetWidth,innerWidth的區(qū)別
1.innerWidth
對于IE9+氯质、Chrome、Firefox、Opera 以及 Safari:
window.innerHeight=瀏覽器窗口的內(nèi)部高度
window.innerWidth=瀏覽器窗口的內(nèi)部寬度
1.clientWidth
一盹兢、對于 Internet Explorer 8邻梆、7、6绎秒、5:
document.documentElement.clientHeight表示HTML文檔所在窗口的當(dāng)前高度
document.documentElement.clientWidth表示HTML文檔所在窗口的當(dāng)前寬度
在不同瀏覽器都實用的 JavaScript 方案:
var w=document.documentElement.clientWidth||document.body.clientWidth;
var h=document.documentElement.clientHeight||document.body.clientHeight;
clientWidth也可以用來獲取元素的寬高浦妄,不包含元素的border.
clientWidth=元素的width+padding
3.scrollWidth
scrollHeight和scrollWidth,獲取網(wǎng)頁內(nèi)容和寬度.
一见芹、針對IE剂娄、Opera:(針對整個網(wǎng)頁來說)
scrollHeight是網(wǎng)頁內(nèi)容的實際高度,可以小于clientHeight.
二辆童、針對NS宜咒、FF:(針對整個網(wǎng)頁來說)
scrollHeight也是網(wǎng)頁內(nèi)容的實際高度,但是最小值是clientHeight.
也就是說就算網(wǎng)頁內(nèi)容比瀏覽器窗口小把鉴,但是返回值還是cliengHeight.
瀏覽器兼容:
var w=document.documentElement.scrollWidth
|| document.body.scrollWidth;
var h=document.documentElement.scrollHeight
|| document.body.scrollHeight;
scrollHeight和scrollWidth還可以獲取Dom元素中內(nèi)容實際占用的高度和寬度.
scrollWidth=元素的width+padding
4.網(wǎng)頁尺寸offsetHeight
offsetHeight和offsetWidth故黑,獲取網(wǎng)頁內(nèi)容高度和寬度(包括滾動條等邊線,會隨窗口的顯示大小改變)庭砍。
offsetHeight=clientHeight+滾動條+邊框.(整個網(wǎng)頁來說)
瀏覽器兼容性
var w= document.documentElement.offsetWidth
|| document.body.offsetWidth;
var h= document.documentElement.offsetHeight
offset用來獲取DOM元素中內(nèi)容高度和寬度時包括元素的border.
offsetWidth=元素的width+padding+border
6.23
回調(diào)函數(shù)
(作為實參傳入另一函數(shù)场晶,并在該外部函數(shù)內(nèi)被調(diào)用,用以來完成某些任務(wù)的函數(shù))
如果一個函數(shù)A 作為另一個B的參數(shù)那么函數(shù)A就被稱為回調(diào)函數(shù)怠缸。
解構(gòu)賦值
ES6新增加的賦值方法诗轻,一般分為對象解構(gòu)和數(shù)組結(jié)構(gòu)兩種方式。
通過解構(gòu)賦值可以將屬性/值從對象/數(shù)組中取出揭北,賦值給其他變量扳炬。
作用
交換變量的值
從函數(shù)返回多個值
函數(shù)參數(shù)的定義
提取JSON的值
函數(shù)參數(shù)的默認值
遍歷Map結(jié)構(gòu)
輸入模塊的指定方法
數(shù)組按照順序解構(gòu)賦值
// 變量先聲明后賦值時的結(jié)構(gòu)
? var a, b, rest;
? [a, b] = [10, 20]; // a 10; b 20
? // 變量聲明并賦值時的結(jié)構(gòu)
? var [a, b] = [10, 20, 30, 40, 50]; // a 10; b 20
? // 默認值
? var [a = 12,b] = [,3]; // a 12; b 3
? // 將剩余數(shù)組賦值給一個變量
? var [a, b, ...rest] = [10, 20, 30, 40, 50]; // a 10; b 20; rest [30, 40, 50]
? // 注意:如果剩余元素右側(cè)有逗號,會拋出 SyntaxError搔体,因為剩余元素必須是數(shù)組的最后一個元素恨樟。
? var[a,...b,]=[12,23,34,45];
? // Uncaught SyntaxError: Rest element must be last element
? // 忽略某些返回值
? var[a,,b]=[12,23,34,45]; // a 12;b 34
對象按照屬性解構(gòu)賦值
// 變量先聲明后賦值時的結(jié)構(gòu)
var a, b, rest;
({a, b} = {a:10, b: 20}); // a 10; b 20
/** 備注:賦值語句周圍的圓括號 ( ... ) 在使用對象字面量無聲明解構(gòu)賦值時是必須的。
? ? ? {a, b} = {a: 1, b: 2} 不是有效的獨立語法疚俱,因為左邊的 {a, b} 被認為是一個塊而不是對象字面量劝术。
? ? ? 然而,({a, b} = {a: 1, b: 2}) 是有效的呆奕,正如 var {a, b} = {a: 1, b: 2}
? ? ? 你的 ( ... ) 表達式之前需要有一個分號养晋,否則它可能會被當(dāng)成上一行中的函數(shù)執(zhí)行。
*/
// 變量聲明并賦值時的結(jié)構(gòu)
var {a, b} = {a:10, b: 20}; // a 10; b 20
// 給新的變量名賦值
var {a:q, b} = {a:10, b: 20}; // q 10; b 20; a is not defined
// 默認值
var {a = 12, b} = {a:undefined, b: 20}; // a 12; b 3
// 將剩余數(shù)組賦值給一個變量
var {a = 10, b, ...rest} = {a:undefined, b: 20, c: 30, d: 40}; // a 10; b 20; rest {c: 30, d: 40}
// 注意:如果剩余元素右側(cè)有逗號梁钾,會拋出 SyntaxError绳泉,因為剩余元素必須是數(shù)組的最后一個元素。
var{a = 10, b, ...rest,} = {a:undefined, b: 20, c: 30, d: 40};
// Uncaught SyntaxError: Rest element must be last element
// 對象屬性計算名和解構(gòu)
let key = "z";
let { [key]: foo } = { z: "bar" }; // foo 'bar';z is not defined
// 解構(gòu)對象時會查找原型鏈(如果屬性不在對象自身姆泻,將從原型鏈中查找)
字符串結(jié)構(gòu)
// 當(dāng)作數(shù)組結(jié)構(gòu)
var [q,w] = '12'; // q 1; w 2
// 當(dāng)作對象結(jié)構(gòu)
var { length}= '12';// length 2
ES6閉包
簡單來說:一個作用域可以訪問另外一個函數(shù)內(nèi)部的局部變量圈纺。閉包指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù) 簡單理解:一個作用域可以訪問另外一個函數(shù)內(nèi)部的局部變量
function fn(){
? ? ? ? let num = 10
? ? ? ? function fun(){
? ? ? ? ? ? console.log(num)
? ? ? ? }
? ? ? ? fun()
? ? }
? ? fn() //10
閉包的主要作用:延伸了變量的作用范圍秦忿。
// fn 外面的作用域可以訪問fn 內(nèi)部的局部變量
? ? function fn(){
? ? ? ? let num = 10
? ? ? ? // 方法一: 先定義再返回函數(shù)
? ? ? ? function fun(){
? ? ? ? ? ? console.log(num)
? ? ? ? }
? ? ? ? return fun //返回 fun函數(shù)
? ? }
? ? let f = fn()
? ? f() //10
閉包就是函數(shù)內(nèi)部的子函數(shù)—— 等于沒說
當(dāng)函數(shù)可以記住并訪問所在的詞法作用域時,就產(chǎn)生了閉包蛾娶,即使函數(shù)是在當(dāng)前詞法作用域之外執(zhí)行灯谣。——靠譜
閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)蛔琅,在本質(zhì)上是函數(shù)內(nèi)部和函數(shù)外部鏈接的橋梁——靠譜
函數(shù)和對其周圍狀態(tài)(詞法環(huán)境)的引用捆綁在一起構(gòu)成閉包(closure)——很靠譜
JS 執(zhí)行棧
當(dāng) js 執(zhí)行全局代碼的時候胎许,會編譯全局代碼并創(chuàng)建全局上下文,全局執(zhí)行上下文是只有一個的罗售。
當(dāng)執(zhí)行函數(shù)的時候辜窑,會編譯函數(shù)中的代碼,然后創(chuàng)建函數(shù)上下文寨躁,函數(shù)執(zhí)行完成之后穆碎,上下文就會被銷毀。
執(zhí)行 eval 函數(shù)的時候职恳,eval會被編譯所禀,并創(chuàng)建 eval 上下文。
一.什么是執(zhí)行棧放钦?
在JavaScript當(dāng)中函數(shù)一旦過多色徘,就有多個函數(shù)執(zhí)行上下文,每次調(diào)用函數(shù)創(chuàng)建一個新的執(zhí)行上下文操禀,那如何管理創(chuàng)建的那么多執(zhí)行上下文呢褂策?
JavaScript 引擎創(chuàng)建了執(zhí)行上下文棧來管理執(zhí)行上下文⊥切迹可以把執(zhí)行上下文棧認為是一個存儲函數(shù)調(diào)用的棧結(jié)構(gòu)斤寂,遵循先進后出的原則。
執(zhí)行棧: call stack 一種結(jié)構(gòu)揪惦,放的是函數(shù)的執(zhí)行環(huán)境扬蕊,每一次函數(shù)執(zhí)行之前,他的所有內(nèi)容全部會放到執(zhí)行棧中丹擎,函數(shù)調(diào)用之前,會創(chuàng)建執(zhí)行環(huán)境歇父,放到執(zhí)行棧當(dāng)中蒂培,函數(shù)調(diào)用完成,銷毀執(zhí)行環(huán)境榜苫。
如上圖所述:在執(zhí)行棧中必須遵守先進后出护戳,后進先出,自上而下的順序垂睬。
JavaScript 執(zhí)行在單線程上媳荒,所有的代碼都是排隊執(zhí)行抗悍。
一開始瀏覽器執(zhí)行全局的代碼時,首先創(chuàng)建全局的執(zhí)行上下文钳枕,壓入執(zhí)行棧的頂部缴渊。
每當(dāng)進入一個函數(shù)的執(zhí)行就會創(chuàng)建函數(shù)的執(zhí)行上下文,并且把它壓入執(zhí)行棧的頂部鱼炒。當(dāng)前函數(shù)執(zhí)行完成后衔沼,當(dāng)前函數(shù)的執(zhí)行上下文出棧,并等待垃圾回收昔瞧。
瀏覽器的 JS 執(zhí)行引擎總是訪問棧頂?shù)膱?zhí)行上下文指蚁。
執(zhí)行機制?
單線程
JavaScript 語言的一大特點就是單線程,也就是說自晰,同一個時間只能做一件事凝化。這是因為 Javascript 這門腳本語言誕生的使命所致——JavaScript 是為處理以及操作 DOM 而誕生的。比如我們對某個 DOM 元素進行添加和刪除操作酬荞,不能同時進行搓劫。 應(yīng)該先進行添加,之后再刪除袜蚕。
單線程就意味著糟把,所有任務(wù)需要排隊,前一個任務(wù)結(jié)束牲剃,才會執(zhí)行后一個任務(wù)遣疯。這樣所導(dǎo)致的問題是: 如果 JS 執(zhí)行的時間過長,這樣就會造成頁面的渲染不連貫凿傅,導(dǎo)致頁面渲染加載阻塞的感覺缠犀。
同步和異步
為了解決這個問題,利用多核 CPU 的計算能力聪舒,HTML5 提出 Web Worker 標(biāo)準(zhǔn)辨液,允許 JavaScript 腳本創(chuàng)建多個線程
于是,JS 中出現(xiàn)了同步和異步箱残。
同步:
前一個任務(wù)結(jié)束后再執(zhí)行后一個任務(wù)
異步:
在做這件事的同時滔迈,你還可以去處理其他事情
同步任務(wù)
同步任務(wù)都在主線程上執(zhí)行,形成一個 執(zhí)行棧
異步任務(wù)
JS中的異步是通過回調(diào)函數(shù)實現(xiàn)的
異步任務(wù)有以下三種類型
普通事件被辑,如click,resize等
資源加載燎悍,如load,error等
定時器,包括setInterval,setTimeout等
異步任務(wù)相關(guān)回調(diào)函數(shù)添加到任務(wù)隊列中(任務(wù)隊列也稱為消息隊列)
塊級作用域和局部作用域的區(qū)別
1.在塊級作用域中,通過var定義的變量是全局變量;
2.在局部作用域中,通過var定義的變量是局部變量;
3.無論是在塊級作用域還是局部作用域,只要省略了變量前面的let或者var,變量就會變成全局作用域里面的變量盼理。
JS中三種創(chuàng)建對象的方式
利用字面量創(chuàng)建對象
利用new Object創(chuàng)建對象
利用構(gòu)造函數(shù)創(chuàng)建對象