HTML&CSS:
一.瀏覽器內(nèi)核:
1.渲染引擎:渲染引擎負責取得網(wǎng)頁的內(nèi)容(HTML、XML、圖像等等)、整理訊息(例如加入 CSS 等),以及計算網(wǎng)頁的顯示方式,然后會輸出至顯示器或打印機。
2.js引擎:JS 引擎則是解析 Javascript 語言,執(zhí)行 javascript 語言來實現(xiàn)網(wǎng)頁的動態(tài)效果。
二.盒模型(標準盒模型和怪異盒模型的區(qū)別):
1.標準盒模型:標準盒模型中width指的是內(nèi)容區(qū)域content的寬度;height指的是內(nèi)容區(qū)域content的高度。標準盒模型下盒子的大小 = content + border + padding + margin
2.怪異盒模型:怪異盒模型中的width指的是內(nèi)容、邊框、內(nèi)邊距總的寬度(content + border + padding);height指的是內(nèi)容、邊框、內(nèi)邊距總的高度。怪異盒模型下盒子的大小=width(content + border + padding) + margin
最后可以通過box-sizing:border-box
三.flex布局:
display:flex(常用)
flex-direction:決定項目的排列方向。(常用)
flex-wrap:即一條軸線排不下時如何換行。(常用)
flex-flow:是flex-direction屬性和flex-wrap屬性的簡寫形式,默認值為row nowrap。
justify-content:定義了項目在主軸上的對齊方式。(justify)(常用)
align-items:定義項目在交叉軸上如何對齊。(常用)
align-content:定義了多根軸線的對齊方式。如果項目只有一根軸線,該屬性不起作用。(換行會產(chǎn)生多軸)
四.兩/三欄布局、水平/垂直居中:
1.兩欄布局:浮動 、定位、 flex
2.三欄布局:絕對定位、 浮動+負外邊距(雙飛翼布局)、浮動定位法、flex、圣杯布局(設置左右邊距加+positive定位)
3.水平/垂直居中:text-align:center 、margin:0 auto; 、使用定位屬性、flexbox布局(display: flex; justify-content: center;)、多行的行內(nèi)元素(使用給父元素設置display:table-cell;和vertical-align: middle;屬即可;)
五.什么是BFC:
BFC是一塊獨立的布局環(huán)境,保護其中內(nèi)部元素不收外部影響,也不影響外部。本身BFC是一種css的布局方式,只是我們可以利用它來解決外邊距折疊的問題,BFC并不是專門用來解決這個問題而創(chuàng)的;
五.清除浮動:
1.額外標簽法(在最后一個浮動標簽后,新加一個標簽,給其設置clear:both;)(不推薦)
2.父級添加overflow屬性(父元素添加overflow:hidden)(不推薦)
3.使用after偽元素清除浮動(推薦使用)
.clearfix:after{/偽元素是行內(nèi)元素 正常瀏覽器清除浮動方法/
content: "";
display: block;
height: 0;
clear:both;
visibility: hidden;
}
.clearfix{
zoom: 1;/ie6清除浮動的方式 號只有IE6-IE7執(zhí)行,其他瀏覽器不執(zhí)行/
}
<body>
<div class="fahter clearfix">
<div class="big">big</div>
<div class="small">small</div>
</div>
<div class="footer"></div>
4.使用before和after雙偽元素清除浮動
.clearfix:after,.clearfix:before{
content: "";
display: table;
}
.clearfix:after{
clear: both;
}
.clearfix{
*zoom: 1;
}
<div class="fahter clearfix">
<div class="big">big</div>
<div class="small">small</div>
</div>
<div class="footer"></div>
六.css3動畫:
第一種是:transition實現(xiàn)漸變動畫,第二種是:transform轉(zhuǎn)變動畫,第三種是:animation實現(xiàn)自定義動畫,具體使用步驟看文檔。
七.H5新特性:
語義標簽、增強型表單、視頻和音頻、Canvas繪圖、SVG繪圖、地理定位、拖放API、WebWorker、WebStorage、WebSocket,具體用法看文檔。
八.行內(nèi)元素有哪些?塊級元素有哪些?空元素有哪些?
首先:css規(guī)范規(guī)定,每個元素都有display屬性,確定該元素的類型,每個元素都有默認的display值,如div 的display默認值為“block” ,則為“塊級”元素;span 默認display 屬性值為“inline”,是“行內(nèi)”元素。
常用的塊狀元素有:div p h1..h6 ol ul dl table address blockquote form
常見的內(nèi)聯(lián)元素有:a span br i em strong label q var cite code
常用的內(nèi)聯(lián)塊狀元素有:img input
知名的空元素:br hr img input link meta br
九瀏覽器是怎么對 HTML5 的離線儲存資源進行管理和加載的呢?
在線的情況下,瀏覽器發(fā)現(xiàn) html 頭部有 manifest 屬性,它會請求 manifest 文件,如果是第
一次訪問 app,那么瀏覽器就會根據(jù) manifest 文件的內(nèi)容下載相應的資源并且進行離線存儲。
如果已經(jīng)訪問過 app 并且資源已經(jīng)離線存儲了,那么瀏覽器就會使用離線的資源加載頁面,
然后瀏覽器會對比新的 manifest 文件與舊的 manifest 文件,如果文件沒有發(fā)生改變,就不做
任何操作,如果文件改變了,那么就會重新下載文件中的資源并進行離線存儲。
離線的情況下,瀏覽器就直接使用離線存儲的資源
十.頁面渲染時,dom 元素所采用的 布局模型,可通過box-sizing 進行設置。根據(jù)計算寬高的區(qū)域可分為:
content-box (W3C 標準 盒模型 )
border-box (IE 盒模 型)
padding-box (FireFox 曾經(jīng) 支持 )
margin-box (瀏覽器未實現(xiàn))
Tips: 理論上是有上面 4 種盒子,但現(xiàn)在 w3c 與 mdn 規(guī)范中均只支持 content-box 與border-box
十一.ie 盒模型算上 border、padding 及自身(不算 margin),標準的只算上自身窗體的大小 css
標準模型 :box-sizing:content-box;
IE 模型:box-sizing:border-box;
十二.幾種獲得寬高的方式 :
1.dom.style.width/height
這種方式只能取到 dom 元素內(nèi)聯(lián)樣式所設置的寬高,也就是說如果該節(jié)點的樣式是在 style
標簽中或外聯(lián)的 CSS 文件中設置的話,通過這種方法是獲取不到 dom 的寬高的。21
2.dom.currentStyle.width/height
這種方式獲取的是在頁面渲染完成后的結(jié)果,就是說不管是哪種方式設置的樣式,都能獲取
到。但這種方式只有 IE 瀏覽器支持。
3.window.getComputedStyle(dom).width/height
這種方式的原理和 2 是一樣的,這個可以兼容更多的瀏覽器,通用性好一些。
4.dom.getBoundingClientRect().width/height
這種方式是根據(jù)元素在視窗中的絕對位置來獲取寬高的
5.dom.offsetWidth/offsetHeight
這個就沒什么好說的了,最常用的,也是兼容最好的。
十三.居中方法:
答: 1. 水平方向上
//針對 inline, 內(nèi)聯(lián)塊 inline-block, 內(nèi)聯(lián)表 inline-table, inline-flex 元素及 img,span,button 等元素
.text_div{
text-align:center;
}
//不定寬塊狀元素居中
.text_div{
margin:0 auto;//且需要設置父級寬度
}
//通過給父元素設置 float,然后給父元素設置 position:relative 和 left:50%,子元素設置 position:relative 和 left: -50% 來實現(xiàn)水平居中。
.wrap{
float:left;
position:relative;
left:50%;
clear:both;
}
.wrap-center{
left:-50%;
}
- 垂直居中
//單行內(nèi)聯(lián)(inline-)元素垂直居中
//通過設置內(nèi)聯(lián)元素的高度(height)和行高(line-height)相等,從而使元素垂直居中。
.text_div{
height: 120px;
line-height: 120px;
}
//利用表布局
.father { display: table; }
.children {
display: table-cell;
vertical-align: middle;
text-align: center;
}
//flex 布局
.center-flex {
display: flex;
flex-direction: column;//上下排列
justify-content: center;
}
//絕對布局方式
//已知高度
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
height: 100px;
margin-top: -50px;
}
//未知高度
.parent { position: relative; }
.child {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
- 垂直水平居中根據(jù)上方結(jié)合
///flex 方 式
.parent {
display: flex;
justify-content: center;
align-items: center;
}
//grid 方 式
.parent{
height: 140px;
display: grid;
}
.child { margin: auto};
十四.css 優(yōu)先確定級:
每個選擇器都有權(quán)值,權(quán)值越大越優(yōu)先
繼承的樣式優(yōu)先級低于自身指定樣式
!important 優(yōu)先級最高 js 也無法修改
權(quán)值相同時,靠近元素的樣式優(yōu)先級高 順序為內(nèi)聯(lián)樣式表(標簽內(nèi)部)> 內(nèi)部樣式表(當
前文件中)> 外部樣式表(外部文件中)
十五.如何清除浮動:
不清楚浮動會發(fā)生高度塌陷:浮動元素父元素高度自適應(父元素不寫高度時,子元素寫了
浮動后,父元素會發(fā)生高度塌陷)clear 清除浮動(添加空 div 法)在浮動元素下方添加空 div,并給該元素寫 css 樣式:
{clear:both;height:0;
overflow:hidden;}
給浮動元素父級設置高度,父級同時浮動(需要給父級同級元素添加浮動),父級設置成 inline-block,其 margin: 0 auto 居中方式失效給父級添加 overflow:hidden 清除浮動方法
萬能清除法 after 偽類 清浮動(現(xiàn)在主流方法,推薦使用)
float_div:after{ content:"."; clear:both; display:block; height:0; overflow:hidden;
visibility:hidden; }.float_div{ zoom:1
}
.clearfix:after {
/生成內(nèi)容作為最后一個元素/
content: "";
/使生成的元素以塊級元素顯示,占滿剩余空間/
display: block;
/避免生成內(nèi)容破壞原有布局的高度/
height: 0;
/使生成的內(nèi)容不可見,并允許可能被生成內(nèi)容蓋住的內(nèi)容可以進行點擊和交互/
visibility: hidden;
/清除浮動元素對當前元素的影響/24
clear: both; }
.clearfix {
/用于兼容 IE, 觸發(fā) IE hasLayout/ *zoom:1;}
十六.display 相關:
block:div 等容器類型 inline:img span 等行內(nèi)類型
table 系列:將樣式變成 table 類型 flex:重點把握,非常強大
grid:同上
inline-block:可設置寬度,兩者間有一點間隙 inherit:繼承父級
十七.介紹一下 CSS 的盒子模型:
有兩種, IE 盒子模型、標準 W3C 盒子模型;
IE 的 content 部分包含了 border 和 pading;
盒模型: 內(nèi)容(content)、填充(padding)、邊界(margin)、 邊框(border)
十八.優(yōu)先級算法如何計算?
優(yōu)先級就近原則,同權(quán)重情況下樣式定義最近者為準
載入樣式以最后載入的定位為準;優(yōu)先級為:
!important > id > class > tag
important 比 內(nèi)聯(lián)優(yōu)先級高,但內(nèi)聯(lián)比 id 要高
十九.列出 display 的值,說明他們的作用?
block 象塊類型元素一樣顯示。
inline 缺省值。象行內(nèi)元素類型一樣顯示。
inline-block 象行內(nèi)元素一樣顯示,但其內(nèi)容象塊類型元素一樣顯示。list-item 象塊類型元素
一樣顯示,并添加樣式列表標記
二十.position 的值,relative 和 absolute 分別是相對于誰進行定位的?
absolute生成絕對定位的元素,相對于 static 定位以外的第一個祖先元素進行定位。
fixed (老 IE 不支持)生成絕對定位的元素,相對于瀏覽器窗口進行定位。
relative 生成相對定位的元素,相對于其在普通流中的位置進行定位。
static 默認值。沒有定位,元素出現(xiàn)在正常的流中*(忽略 top, bottom, left, right z-index 聲
明)。inherit 規(guī)定從父元素繼承 position 屬性的值
二十一.Less/Sass/Scss 的區(qū)別?
Scss 其實是 Sass 的改進版本 Scss 是 Sass 的縮排語法,對于寫慣 css 前端的 web 開發(fā)者來說
很不直觀,也不能將 css 代碼加入到 Sass 里面,因此 Sass 語法進行了改良,Sass 3 就變成了
Scss(sassy css)。與原來的語法兼容,只是用{}取代了原來的縮進。
Less 環(huán)境較 Sass 簡單 Sass 的安裝需要安裝 Ruby 環(huán)境,Less 基于 JavaScript,需要引入 Less.js
來處理代碼輸出 css 變量符不一樣,Less 是@,而 Sass 是$,而且變量的作用域也不一樣。
Sass 沒有局部變量,滿足就近原則。Less 中{}內(nèi)定義的變量為局部變量。
Less 沒有輸出設置,Sass 提供 4 中輸出選項:
輸出樣式的風格可以有四種選擇,默認為 nested nested:嵌套縮進的 css 代碼 expanded:
展開的多行 css 代碼 compact:簡潔格式的 css 代碼 compressed:壓縮后的 css 代碼
Sass 支持條件語句,可以使用 if{}else{},for{}循環(huán)等等。而 Less 不支持。
Less 與 Sass 處理機制不一樣 Less 是通過客戶端處理的,Sass 是通過服務端處理,相比較之
下 Less 解析會比 Sass 慢一點30
Sass 和 Less 的工具庫不同 Sass 有工具庫 Compass, 簡單說,Sass 和 Compass 的關系有點像
Javascript 和 jQuery 的關系,Compass 是 Sass 的工具庫。在 它的基礎上,封裝了一系列有用
的模塊和模板,補充強化了 Sass 的功
能。
Less 有 UI 組件庫 Bootstrap, Bootstrap 是 web 前端開發(fā)中一個比較有名的前端 UI 組件庫,
Bootstrap 的樣式文件部分源碼就是采用 Less 語法編寫,不過 Bootstrap4 也開始用 Sass 編寫
了。
二十二. css 與 js 動畫差異?
css 性能好
css 代碼邏輯相對簡單 js 動畫控制好
js 兼容性好
js 可實現(xiàn)的動畫多 js 可以添加事件
二十三 .如何居中 div?如何居中一個浮動元素?如何讓絕對定位的 div 居中?
div:
border: 1px solid red;34
margin: 0 auto;
height: 50px;
width: 80px;
浮動元素的上下左右居中:
border: 1px solid red;
float: left;
position: absolute;
width: 200px;
height: 100px;
left: 50%;
top: 50%;
margin: -50px 0 0 -100px;
絕對定位的左右居中:
border: 1px solid black;
position: absolute;
width: 200px;
height: 100px;
margin: 0 auto;
left: 0;
right: 0
二十四.請解釋一下 CSS3 的 flexbox(彈性盒布局模型),以及適用場景?
該布局模型的目的是提供一種更加高效的方式來對容器中的條目進行布局、對齊和分配空
間。在傳統(tǒng)的布局方式中,block 布局是把塊在垂直方向從上到下依次排列的;而 inline 布
局則是在水平方向來排列。彈性盒布局并沒有這樣內(nèi)在的方向限制,可以由開發(fā)人員自由操
作。 使用場景:彈性布局適合于移動前端開發(fā),在 Android 和 ios 上也完美支持。
JavaScript:
一.介紹一下js的數(shù)據(jù)類型有哪些,值是如何存儲的:
一共8種數(shù)據(jù)類型 分為基本數(shù)據(jù)類型和引用數(shù)據(jù)類型
基本數(shù)據(jù)類型:undefined 、Null 、boolean、 Number、 String、 Symbol、 Biglnt
引用數(shù)據(jù)類型:Object 里面包含 function、Array、Date等
1.原始數(shù)據(jù)類型:直接存儲在棧(stack)中,占據(jù)空間小、大小固定,屬于被頻繁使用數(shù)據(jù),所以放入棧中存儲。
2.引用數(shù)據(jù)類型:同時存儲在棧(stack)和堆(heap)中,占據(jù)空間大、大小不固定。引用數(shù)據(jù)類型在棧中存儲了指針,該指針指向堆中該實體的起始地址。當解釋器尋找引用值時,會首先檢索其在棧中的地址,取得地址后從堆中獲得實體。
二. && 、 ||和!! 運算符分別能做什么:
? && 叫邏輯與,在其操作數(shù)中找到第一個虛值表達式并返回它,如果沒有找到任何虛值表達式,則返回最后一個真值表達式。它采用短路來防止不必要的工作。
? || 叫邏輯或,在其操作數(shù)中找到第一個真值表達式并返回它。這也使用了短路來防止不必要的工作。在支持 ES6 默認函數(shù)參數(shù)之前,它用于初始化函數(shù)中的默認參數(shù)值。
? !! 運算符可以將右側(cè)的值強制轉(zhuǎn)換為布爾值,這也是將值轉(zhuǎn)換為布爾值的一種簡單方法。
三. js的數(shù)據(jù)類型的轉(zhuǎn)換:
? 轉(zhuǎn)換為布爾值(調(diào)用Boolean()方法)
? 轉(zhuǎn)換為數(shù)字(調(diào)用Number()、parseInt()和parseFloat()方法)
? 轉(zhuǎn)換為字符串(調(diào)用.toString()或者String()方法)
? null和underfined沒有.toString方法
四. js的數(shù)據(jù)類型的判斷:
1.typeof 對于原始類型來說,除了 null 都可以顯示正確的類型。
2.instanceof 可以正確的判斷對象的類型,因為內(nèi)部機制是通過判斷對象的原型鏈中是不是能找到類型的 prototype。可以看出直接的字面量值判斷數(shù)據(jù)類型,instanceof可以精準判斷引用數(shù)據(jù)類型(Array,F(xiàn)unction,Object),而基本數(shù)據(jù)類型不能被instanceof精準判斷。
3.constructor這里有一個坑,如果我創(chuàng)建一個對象,更改它的原型,constructor就會變得不可靠了。
4.Object.prototype.toString.call() 使用 Object 對象的原型方法 toString ,使用 call 進行貍貓換太子,借用Object的 toString 方法。
五. js的內(nèi)置對象有那些:
(1)值屬性,這些全局屬性返回一個簡單值,這些值沒有自己的屬性和方法。例如 Infinity、NaN、undefined、null 字面量
(2)函數(shù)屬性,全局函數(shù)可以直接調(diào)用,不需要在調(diào)用時指定所屬對象,執(zhí)行結(jié)束后會將結(jié)果直接返回給調(diào)用者。例如 eval()、parseFloat()、parseInt() 等
(3)基本對象,基本對象是定義或使用其他對象的基礎?;緦ο蟀ㄒ话銓ο蟆⒑瘮?shù)對象和錯誤對象。例如 Object、Function、Boolean、Symbol、Error 等
(4)數(shù)字和日期對象,用來表示數(shù)字、日期和執(zhí)行數(shù)學計算的對象。例如 Number、Math、Date
(5)字符串,用來表示和操作字符串的對象。例如 String、RegExp
(6)可索引的集合對象,這些對象表示按照索引值來排序的數(shù)據(jù)集合,包括數(shù)組和類型數(shù)組,以及類數(shù)組結(jié)構(gòu)的對象。例如 Array
(7)使用鍵的集合對象,這些集合對象在存儲數(shù)據(jù)時會使用到鍵,支持按照插入順序來迭代元素。例如 Map、Set、WeakMap、WeakSet
(8)矢量集合,SIMD 矢量集合中的數(shù)據(jù)會被組織為一個數(shù)據(jù)序列。例如 SIMD 等
(9)結(jié)構(gòu)化數(shù)據(jù),這些對象用來表示和操作結(jié)構(gòu)化的緩沖區(qū)數(shù)據(jù),或使用 JSON 編碼的數(shù)據(jù)。例如 JSON 等
(10)控制抽象對象例如 Promise、Generator 等
(11)反射 例如 Reflect、Proxy
(12)國際化,為了支持多語言處理而加入 ECMAScript 的對象。例如 Intl、Intl.Collator 等
(13)WebAssembly
(14)其他 例如 arguments
六. undefined 與 undeclared 的區(qū)別?
已在作用域中聲明但還沒有賦值的變量,是 undefined。相反,還沒有在作用域中聲明過的變量,是 undeclared 的。
七. null 和 undefined 的區(qū)別?
首先 Undefined 和 Null 都是基本數(shù)據(jù)類型,這兩個基本數(shù)據(jù)類型分別都只有一個值,就是 undefined 和 null。
undefined 代表的含義是未定義
null 代表的含義是空對象
八. {}和[]的valueOf和toString的結(jié)果是什么?
{} 的 valueOf 結(jié)果為 {} ,toString 的結(jié)果為 "[object Object]"
[] 的 valueOf 結(jié)果為 [] ,toString 的結(jié)果為 ""
九. Javascript 的作用域和作用域鏈?
作用域: 作用域是定義變量的區(qū)域,它有一套訪問變量的規(guī)則,這套規(guī)則來管理瀏覽器引擎如何在當前作用域以及嵌套的作用域中根據(jù)變量(標識符)進行變量查找。
作用域鏈: 作用域鏈的作用是保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問,通過作用域鏈,我們可以訪問到外層環(huán)境的變量和 函數(shù)。
作用域鏈的本質(zhì)上是一個指向變量對象的指針列表。變量對象是一個包含了執(zhí)行環(huán)境中所有變量和函數(shù)的對象。作用域鏈的前 端始終都是當前執(zhí)行上下文的變量對象。全局執(zhí)行上下文的變量對象(也就是全局對象)始終是作用域鏈的最后一個對象。
十. javascript 創(chuàng)建對象的幾種方式?
(1)第一種是工廠模式,工廠模式的主要工作原理是用函數(shù)來封裝創(chuàng)建對象的細節(jié),從而通過調(diào)用函數(shù)來達到復用的目的。但是它有一個很大的問題就是創(chuàng)建出來的對象無法和某個類型聯(lián)系起來,它只是簡單的封裝了復用代碼,而沒有建立起對象和類型間的關系。
(2)第二種是構(gòu)造函數(shù)模式。js 中每一個函數(shù)都可以作為構(gòu)造函數(shù),只要一個函數(shù)是通過 new 來調(diào)用的,那么我們就可以把它稱為構(gòu)造函數(shù)。執(zhí)行構(gòu)造函數(shù)首先會創(chuàng)建一個對象,然后將對象的原型指向構(gòu)造函數(shù)的 prototype 屬性,然后將執(zhí)行上下文中的 this 指向這個對象,最后再執(zhí)行整個函數(shù),如果返回值不是對象,則返回新建的對象。因為 this 的值指向了新建的對象,因此我們可以使用 this 給對象賦值。構(gòu)造函數(shù)模式相對于工廠模式的優(yōu)點是,所創(chuàng)建的對象和構(gòu)造函數(shù)建立起了聯(lián)系,因此我們可以通過原型來識別對象的類型。但是構(gòu)造函數(shù)存在一個缺點就是,造成了不必要的函數(shù)對象的創(chuàng)建,因為在 js 中函數(shù)也是一個對象,因此如果對象屬性中如果包含函數(shù)的話,那么每次我們都會新建一個函數(shù)對象,浪費了不必要的內(nèi)存空間,因為函數(shù)是所有的實例都可以通用的。
(3)第三種模式是原型模式,因為每一個函數(shù)都有一個 prototype 屬性,這個屬性是一個對象,它包含了通過構(gòu)造函數(shù)創(chuàng)建的所有實例都能共享的屬性和方法。因此我們可以使用原型對象來添加公用屬性和方法,從而實現(xiàn)代碼的復用。這種方式相對于構(gòu)造函數(shù)模式來說,解決了函數(shù)對象的復用問題。但是這種模式也存在一些問題,一個是沒有辦法通過傳入?yún)?shù)來初始化值,另一個是如果存在一個引用類型如 Array 這樣的值,那么所有的實例將共享一個對象,一個實例對引用類型值的改變會影響所有的實例。
(4)第四種模式是組合使用構(gòu)造函數(shù)模式和原型模式,這是創(chuàng)建自定義類型的最常見方式。因為構(gòu)造函數(shù)模式和原型模式分開使用都存在一些問題,因此我們可以組合使用這兩種模式,通過構(gòu)造函數(shù)來初始化對象的屬性,通過原型對象來實現(xiàn)函數(shù)方法的復用。這種方法很好的解決了兩種模式單獨使用時的缺點,但是有一點不足的就是,因為使用了兩種不同的模式,所以對于代碼的封裝性不夠好。
(5)第五種模式是動態(tài)原型模式,這一種模式將原型方法賦值的創(chuàng)建過程移動到了構(gòu)造函數(shù)的內(nèi)部,通過對屬性是否存在的判斷,可以實現(xiàn)僅在第一次調(diào)用函數(shù)時對原型對象賦值一次的效果。這一種方式很好地對上面的混合模式進行了封裝。
(6)第六種模式是寄生構(gòu)造函數(shù)模式,這一種模式和工廠模式的實現(xiàn)基本相同,我對這個模式的理解是,它主要是基于一個已有的類型,在實例化時對實例化的對象進行擴展。這樣既不用修改原來的構(gòu)造函數(shù),也達到了擴展對象的目的。它的一個缺點和工廠模式一樣,無法實現(xiàn)對象的識別。
十一.JavaScript 繼承的幾種實現(xiàn)方式?
(1)第一種是以原型鏈的方式來實現(xiàn)繼承,但是這種實現(xiàn)方式存在的缺點是,在包含有引用類型的數(shù)據(jù)時,會被所有的實例對象所共享,容易造成修改的混亂。還有就是在創(chuàng)建子類型的時候不能向超類型傳遞參數(shù)。
(2)第二種方式是使用借用構(gòu)造函數(shù)的方式,這種方式是通過在子類型的函數(shù)中調(diào)用超類型的構(gòu)造函數(shù)來實現(xiàn)的,這一種方法解決了不能向超類型傳遞參數(shù)的缺點,但是它存在的一個問題就是無法實現(xiàn)函數(shù)方法的復用,并且超類型原型定義的方法子類型也沒有辦法訪問到。
(3)第三種方式是組合繼承,組合繼承是將原型鏈和借用構(gòu)造函數(shù)組合起來使用的一種方式。通過借用構(gòu)造函數(shù)的方式來實現(xiàn)類型的屬性的繼承,通過將子類型的原型設置為超類型的實例來實現(xiàn)方法的繼承。這種方式解決了上面的兩種模式單獨使用時的問題,但是由于我們是以超類型的實例來作為子類型的原型,所以調(diào)用了兩次超類的構(gòu)造函數(shù),造成了子類型的原型中多了很多不必要的屬性。
(4)第四種方式是原型式繼承,原型式繼承的主要思路就是基于已有的對象來創(chuàng)建新的對象,實現(xiàn)的原理是,向函數(shù)中傳入一個對象,然后返回一個以這個對象為原型的對象。這種繼承的思路主要不是為了實現(xiàn)創(chuàng)造一種新的類型,只是對某個對象實現(xiàn)一種簡單繼承,ES5 中定義的 Object.create() 方法就是原型式繼承的實現(xiàn)。缺點與原型鏈方式相同。
(5)第五種方式是寄生式繼承,寄生式繼承的思路是創(chuàng)建一個用于封裝繼承過程的函數(shù),通過傳入一個對象,然后復制一個對象的副本,然后對象進行擴展,最后返回這個對象。這個擴展的過程就可以理解是一種繼承。這種繼承的優(yōu)點就是對一個簡單對象實現(xiàn)繼承,如果這個對象不是我們的自定義類型時。缺點是沒有辦法實現(xiàn)函數(shù)的復用。
(6)第六種方式是寄生式組合繼承,組合繼承的缺點就是使用超類型的實例做為子類型的原型,導致添加了不必要的原型屬性。寄生式組合繼承的方式是使用超類型的原型的副本來作為子類型的原型,這樣就避免了創(chuàng)建不必要的屬性。
十二.談談你對this、call、apply和bind的理解?
- 在瀏覽器里,在全局范圍內(nèi)this 指向window對象;
- 在函數(shù)中,this永遠指向最后調(diào)用他的那個對象;
- 構(gòu)造函數(shù)中,this指向new出來的那個新的對象;
- call、apply、bind中的this被強綁定在指定的那個對象上;
- 箭頭函數(shù)中this比較特殊,箭頭函數(shù)this為父作用域的this,不是調(diào)用時的this.要知道前四種 方式,都是調(diào)用時確定,也就是動態(tài)的,而箭頭函數(shù)的this指向是靜態(tài)的,聲明的時候就確定了下 來;
- apply、call、bind都是js給函數(shù)內(nèi)置的一些API,調(diào)用他們可以為函數(shù)指定this的執(zhí)行,同時 也可以傳參。
十三.js 獲取原型的方法?
? p.proto
? p.constructor.prototype
? Object.getPrototypeOf(p)
十四.什么是閉包?
閉包是指有權(quán)訪問另一個函數(shù)作用域內(nèi)變量的函數(shù),創(chuàng)建閉包的最常見的方式就是在一個函數(shù)內(nèi)創(chuàng)建另一個函數(shù),創(chuàng)建的函數(shù)可以 訪問到當前函數(shù)的局部變量。
十五.什么是 DOM 和 BOM?
DOM 指的是文檔對象模型,它指的是把文檔當做一個對象來對待,這個對象主要定義了處理網(wǎng)頁內(nèi)容的方法和接口。
BOM 指的是瀏覽器對象模型,它指的是把瀏覽器當做一個對象來對待,這個對象主要定義了與瀏覽器進行交互的法和接口。BOM 的核心是 window,而 window 對象具有雙重角色,它既是通過 js 訪問瀏覽器窗口的一個接口,又是一個 Global(全局) 對象。這意味著在網(wǎng)頁中定義的任何對象,變量和函數(shù),都作為全局對象的一個屬性或者方法存在。window 對象含有 locati on 對象、navigator 對象、screen 對象等子對象,并且 DOM 的最根本的對象 document 對象也是 BOM 的 window 對 象的子對象。
十六.三種事件模型是什么?
事件 是用戶操作網(wǎng)頁時發(fā)生的交互動作或者網(wǎng)頁本身的一些操作,現(xiàn)代瀏覽器一共有三種事件模型。
- DOM0級模型: ,這種模型不會傳播,所以沒有事件流的概念,但是現(xiàn)在有的瀏覽器支持以冒泡的方式實現(xiàn),它可以在網(wǎng)頁中直接定義監(jiān)聽函數(shù),也可以通過 js屬性來指定監(jiān)聽函數(shù)。這種方式是所有瀏覽器都兼容的。
- IE 事件模型: 在該事件模型中,一次事件共有兩個過程,事件處理階段,和事件冒泡階段。事件處理階段會首先執(zhí)行目標元素綁定的監(jiān)聽事件。然后是事件冒泡階段,冒泡指的是事件從目標元素冒泡到 document,依次檢查經(jīng)過的節(jié)點是否綁定了事件監(jiān)聽函數(shù),如果有則執(zhí)行。這種模型通過 attachEvent 來添加監(jiān)聽函數(shù),可以添加多個監(jiān)聽函數(shù),會按順序依次執(zhí)行。
- DOM2 級事件模型: 在該事件模型中,一次事件共有三個過程,第一個過程是事件捕獲階段。捕獲指的是事件從 document 一直向下傳播到目標元素,依次檢查經(jīng)過的節(jié)點是否綁定了事件監(jiān)聽函數(shù),如果有則執(zhí)行。后面兩個階段和 IE 事件模型的兩個階段相同。這種事件模型,事件綁定的函數(shù)是 addEventListener,其中第三個參數(shù)可以指定事件是否在捕獲階段執(zhí)行。
十七.事件委托是什么?
事件委托 本質(zhì)上是利用了瀏覽器事件冒泡的機制。因為事件在冒泡過程中會上傳到父節(jié)點,并且父節(jié)點可以通過事件對象獲取到 目標節(jié)點,因此可以把子節(jié)點的監(jiān)聽函數(shù)定義在父節(jié)點上,由父節(jié)點的監(jiān)聽函數(shù)統(tǒng)一處理多個子元素的事件,這種方式稱為事件代理。
使用事件代理我們可以不必要為每一個子元素都綁定一個監(jiān)聽事件,這樣減少了內(nèi)存上的消耗。并且使用事件代理我們還可以實現(xiàn)事件的動態(tài)綁定,比如說新增了一個子節(jié)點,我們并不需要單獨地為它添加一個監(jiān)聽事件,它所發(fā)生的事件會交給父元素中的監(jiān)聽函數(shù)來處理。
十八.什么是事件傳播?
當事件發(fā)生在DOM元素上時,該事件并不完全發(fā)生在那個元素上。在“當事件發(fā)生在DOM元素上時,該事件并不完全發(fā)生在那個元素上。
事件傳播有三個階段:
- 捕獲階段–事件從 window 開始,然后向下到每個元素,直到到達目標元素事件或event.target。
- 目標階段–事件已達到目標元素。
- 冒泡階段–事件從目標元素冒泡,然后上升到每個元素,直到到達 window。
十九.什么是事件捕獲?
百度
十九.什么是事件冒泡?
百度
二十.DOM 操作——怎樣添加、移除、移動、復制、創(chuàng)建和查找節(jié)點?
(1)創(chuàng)建新節(jié)點
createDocumentFragment() //創(chuàng)建一個DOM片段
createElement() //創(chuàng)建一個具體的元素
createTextNode() //創(chuàng)建一個文本節(jié)點
(2)添加、移除、替換、插入
appendChild(node)
removeChild(node)
replaceChild(new,old)
insertBefore(new,old)
(3)查找
getElementById();
getElementsByName();
getElementsByTagName();
getElementsByClassName();
querySelector();
querySelectorAll();
(4)屬性操作
getAttribute(key);
setAttribute(key, value);
hasAttribute(key);
removeAttribute(key);
二十一.數(shù)組和對象有哪些原生方法,列舉一下?
Array.concat( ) 連接數(shù)組
Array.join( ) 將數(shù)組元素連接起來以構(gòu)建一個字符串
Array.length 數(shù)組的大小
Array.pop( ) 刪除并返回數(shù)組的最后一個元素
Array.push( ) 給數(shù)組添加元素
Array.reverse( ) 顛倒數(shù)組中元素的順序
Array.shift( ) 將元素移出數(shù)組
Array.slice( ) 返回數(shù)組的一部分
Array.sort( ) 對數(shù)組元素進行排序
Array.splice( ) 插入、刪除或替換數(shù)組的元素
Array.toLocaleString( ) 把數(shù)組轉(zhuǎn)換成局部字符串
Array.toString( ) 將數(shù)組轉(zhuǎn)換成一個字符串
Array.unshift( ) 在數(shù)組頭部插入一個元素
Object.hasOwnProperty( ) 檢查屬性是否被繼承
Object.isPrototypeOf( ) 一個對象是否是另一個對象的原型
Object.propertyIsEnumerable( ) 是否可以通過for/in循環(huán)看到屬性
Object.toLocaleString( ) 返回對象的本地字符串表示
Object.toString( ) 定義一個對象的字符串表示
Object.valueOf( ) 指定對象的原始值
二十二.Ajax 是什么? 如何創(chuàng)建一個 Ajax?
它是一種異步通信的方法,通過直接由 js 腳本向服務器發(fā)起 http 通信,然后根據(jù)服務器返回的數(shù)據(jù),更新網(wǎng)頁的相應部分,而不用刷新整個頁面的一種方法。
創(chuàng)建步驟:
面試手寫(原生):
//1:創(chuàng)建Ajax對象
var xhr = window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');// 兼容IE6及以下版本
//2:配置 Ajax請求地址
xhr.open('get','index.xml',true);
//3:發(fā)送請求
xhr.send(null); // 嚴謹寫法
//4:監(jiān)聽請求,接受響應
xhr.onreadysatechange=function(){
if(xhr.readySate==4&&xhr.status==200 || xhr.status==304 )
console.log(xhr.responsetXML)
}
jQuery寫法
$.ajax({
type:'post',
url:'',
async:ture,//async 異步 sync 同步
data:data,//針對post請求
dataType:'jsonp',
success:function (msg) {
},
error:function (error) {
}
})
promise 封裝實現(xiàn):
// promise 封裝實現(xiàn):
function getJSON(url) {
// 創(chuàng)建一個 promise 對象
let promise = new Promise(function(resolve, reject) {
let xhr = new XMLHttpRequest();
// 新建一個 http 請求
xhr.open("GET", url, true);
// 設置狀態(tài)的監(jiān)聽函數(shù)
xhr.onreadystatechange = function() {
if (this.readyState !== 4) return;
// 當請求成功或失敗時,改變 promise 的狀態(tài)
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
// 設置錯誤監(jiān)聽函數(shù)
xhr.onerror = function() {
reject(new Error(this.statusText));
};
// 設置響應的數(shù)據(jù)類型
xhr.responseType = "json";
// 設置請求頭信息
xhr.setRequestHeader("Accept", "application/json");
// 發(fā)送 http 請求
xhr.send(null);
});
return promise;
}
二十三. js 延遲加載的方式有哪些?
js 的加載、解析和執(zhí)行會阻塞頁面的渲染過程,因此我們希望 js 腳本能夠盡可能的延遲加載,提高頁面的渲染速度。
我了解到的幾種方式是:
- 將 js 腳本放在文檔的底部,來使 js 腳本盡可能的在最后來加載執(zhí)行。
- 給 js 腳本添加 defer屬性,這個屬性會讓腳本的加載與文檔的解析同步解析,然后在文檔解析完成后再執(zhí)行這個腳本文件,這樣的話就能使頁面的渲染不被阻塞。多個設置了 defer 屬性的腳本按規(guī)范來說最后是順序執(zhí)行的,但是在一些瀏覽器中可能不是這樣。
- 給 js 腳本添加 async屬性,這個屬性會使腳本異步加載,不會阻塞頁面的解析過程,但是當腳本加載完成后立即執(zhí)行 js腳本,這個時候如果文檔沒有解析完成的話同樣會阻塞。多個 async 屬性的腳本的執(zhí)行順序是不可預測的,一般不會按照代碼的順序依次執(zhí)行。
- 動態(tài)創(chuàng)建 DOM 標簽的方式,我們可以對文檔的加載事件進行監(jiān)聽,當文檔加載完成后再動態(tài)的創(chuàng)建 script 標簽來引入 js 腳本。
二十四.談談你對模塊化開發(fā)的理解?
一個模塊是實現(xiàn)一個特定功能的一組方法。在最開始的時候,js 只實現(xiàn)一些簡單的功能,所以并沒有模塊的概念 ,但隨著程序越來越復雜,代碼的模塊化開發(fā)變得越來越重要。
由于函數(shù)具有獨立作用域的特點,最原始的寫法是使用函數(shù)來作為模塊,幾個函數(shù)作為一個模塊,但是這種方式容易造成全局變量的污 染,并且模塊間沒有聯(lián)系。
后面提出了對象寫法,通過將函數(shù)作為一個對象的方法來實現(xiàn),這樣解決了直接使用函數(shù)作為模塊的一些缺點,但是這種辦法會暴露所 有的所有的模塊成員,外部代碼可以修改內(nèi)部屬性的值。
現(xiàn)在最常用的是立即執(zhí)行函數(shù)的寫法,通過利用閉包來實現(xiàn)模塊私有作用域的建立,同時不會對全局作用域造成污染。
二十五.js 的幾種模塊規(guī)范?
? 第一種是 CommonJS 方案,它通過 require 來引入模塊,通過 module.exports 定義模塊的輸出接口。這種模塊加載方案是服務器端的解決方案,它是以同步的方式來引入模塊的,因為在服務端文件都存儲在本地磁盤,所以讀取非???,所以以同步的方式加載沒有問題。但如果是在瀏覽器端,由于模塊的加載是使用網(wǎng)絡請求,因此使用異步加載的方式更加合適。
? 第二種是 AMD 方案,這種方案采用異步加載的方式來加載模塊,模塊的加載不影響后面語句的執(zhí)行,所有依賴這個模塊的語句都定義在一個回調(diào)函數(shù)里,等到加載完成后再執(zhí)行回調(diào)函數(shù)。require.js 實現(xiàn)了 AMD 規(guī)范。
? 第三種是 CMD 方案,這種方案和 AMD 方案都是為了解決異步模塊加載的問題,sea.js 實現(xiàn)了 CMD 規(guī)范。它和require.js的區(qū)別在于模塊定義時對依賴的處理不同和對依賴模塊的執(zhí)行時機的處理不同。
? 第四種方案是 ES6 提出的方案,使用 import 和 export 的形式來導入導出模塊。
二十六.ECMAScript 2015(ES6)有哪些新特性?
? 塊作用域
? 類
? 箭頭函數(shù)
? 模板字符串
? 加強的對象字面
? 對象解構(gòu)
? Promise
? 模塊
? Symbol
? 代理(proxy)Set
? 函數(shù)默認參數(shù)
? rest 和展開
二十七. var,let和const的區(qū)別是什么?
var聲明的變量會掛載在window上,而let和const聲明的變量不會:
var聲明變量存在變量提升,let和const不存在變量提升:
let和const聲明形成塊作用域,同一作用域下let和const不能聲明同名變量,而var可以
二十八.什么是高階函數(shù)?
高階函數(shù)只是將函數(shù)作為參數(shù)或返回值的函數(shù)。
function higherOrderFunction(param,callback){
return callback(param);
}
二十九.深淺拷貝

三十.對象的拷貝?
淺拷貝: 以賦值的形式拷貝引用對象,仍指向同一個地址,修改時原對象也會受到影響
Object.assign
展開運算符(...)
深拷貝: 完全拷貝一個新對象,修改時原對象不再受到任何影響
JSON.parse(JSON.stringify(obj)): 性能最快
具有循環(huán)引用的對象時,報錯 當值為函數(shù)、undefined、或 symbol 時,無法拷貝 遞歸進行逐一賦值
三十一.new 運算符的執(zhí)行過程?
新生成一個對象
鏈接到原型: obj.proto = Con.prototype
綁定 this: apply
返回新對象(如果構(gòu)造函數(shù)有自己 retrun 時,則返回該值)
三十二.類型轉(zhuǎn)換?
大家都知道 JS 中在使用運算符號或者對比符時,會自帶隱式轉(zhuǎn)換,規(guī)則如下:
-、*、/、% :一律轉(zhuǎn)換成數(shù)值后計算
+:
數(shù)字 + 字符串 = 字符串, 運算順序是從左到右
數(shù)字 + 對象, 優(yōu)先調(diào)用對象的 valueOf -> toString
數(shù)字 + boolean/null -> 數(shù)字
數(shù)字 + undefined -> NaN
[1].toString() === '1'
{}.toString() === '[object object]'
NaN !== NaN 、+undefined 為 NaN
三十三.類型判斷?
判斷 Target 的類型,單單用 typeof 并無法完全滿足,這其實并不是 bug,本
質(zhì)原因是 JS 的萬物皆對象的理論。因此要真正完美判斷時,我們需要區(qū)分對待:
基本類型(null): 使用 String(null)
基本類型(string / number / boolean / undefined) + function: 直接使用
typeof 即可
其余引用類型(Array / Date / RegExp Error): 調(diào)用 toString 后根據(jù)[object54
XXX]進行判斷
很穩(wěn)的判斷封裝:
let class2type = {}'Array Date RegExp Object Error'.split(' ').forEach(e
=> class2type[ '[object ' + e + ']' ] = e.toLowerCase())
function type(obj) {
if (obj == null) return String(obj)
return typeof obj === 'object' ?
class2type[ Object.prototype.toString.call(obj) ] || 'object' : typeof
obj
}
三十四.防抖與節(jié)流?
防抖與節(jié)流函數(shù)是一種最常用的 高頻觸發(fā)優(yōu)化方式,能對性能有較大的幫助。防抖 (debounce): 將多次高頻操作優(yōu)化為只在最后一次執(zhí)行,通常使用的場景是:用戶輸入,只需再輸入完成后做一次輸入校驗即可。
function debounce(fn, wait, immediate) {
let timer = null
return function() {
let args = arguments
let context = this
if (immediate && !timer) {55
fn.apply(context, args)
}
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(context, args)
}, wait)
}
}
節(jié)流(throttle): 每隔一段時間后執(zhí)行一次,也就是降低頻率,將高頻操作優(yōu)化成低頻操作,通常使用場景: 滾動條事件 或者 resize 事件,通常每隔 100~500ms 執(zhí)行一次即可。
function throttle(fn, wait, immediate) {
let timer = null
let callNow = immediate
return function() {
let context = this,
args = arguments
if (callNow) {
fn.apply(context, args)
callNow = false
}
if (!timer) {
timer = setTimeout(() => {
fn.apply(context, args)
timer = null
}, wait)
}
}
}
三十五.說一下閉包
一句話可以概括:閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù),或者子函數(shù)在外
調(diào)用,子函數(shù)所在的父函數(shù)的作用域不會被釋放
7.如何解決異步回調(diào)地獄
promise、generator、async/await
三十六.說一下圖片的懶加載和預加載
預加載:提前加載圖片,當用戶需要查看時可直接從本地緩存中渲染。
懶加載:懶加載的主要目的是作為服務器前端的優(yōu)化,減少請求數(shù)或延遲請求數(shù)。
兩種技術的本質(zhì):兩者的行為是相反的,一個是提前加載,一個是遲緩甚至不加
載。
懶加載對服務器前端有一定的緩解壓力作用,預加載則會增加服務器前端壓力。
三十七.mouseover 和 mouseenter 的區(qū)別
mouseover:當鼠標移入元素或其子元素都會觸發(fā)事件,所以有一個重復觸發(fā),
冒泡的過程。對應的移除事件是 mouseout
mouseenter:當鼠標移除元素本身(不包含元素的子元素)會觸發(fā)事件,也就是
不會冒泡,對應的移除事件是 mouseleave
三十八.JS 中的垃圾回收機制
必要性:由于字符串、對象和數(shù)組沒有固定大小,所有當他們的大小已知時,才
能對他們進行動態(tài)的存儲分配。JavaScript 程序每次創(chuàng)建字符串、數(shù)組或?qū)ο?br> 時,解釋器都必須分配內(nèi)存來存儲那個實體。只要像這樣動態(tài)地分配了內(nèi)存,最
終都要釋放這些內(nèi)存以便他們能夠被再用,否則,JavaScript 的解釋器將會消
耗完系統(tǒng)中所有可用的內(nèi)存,造成系統(tǒng)崩潰。
這段話解釋了為什么需要系統(tǒng)需要垃圾回收,JS 不像 C/C++,他有自己的一套垃
圾回收機制(Garbage Collection)。JavaScript 的解釋器可以檢測到何時程序
不再使用一個對象了,當他確定了一個對象是無用的時候,他就知道不再需要這
個對象,可以把它所占用的內(nèi)存釋放掉了。例如:68
var a="hello world";
var b="world";
var a=b;
//這時,會釋放掉"hello world",釋放內(nèi)存以便再引用
垃圾回收的方法:標記清除、計數(shù)引用。
標記清除
這是最常見的垃圾回收方式,當變量進入環(huán)境時,就標記這個變量為”進入環(huán)境
“,從邏輯上講,永遠不能釋放進入環(huán)境的變量所占的內(nèi)存,永遠不能釋放進入
環(huán)境變量所占用的內(nèi)存,只要執(zhí)行流程進入相應的環(huán)境,就可能用到他們。當離
開環(huán)境時,就標記為離開環(huán)境。
垃圾回收器在運行的時候會給存儲在內(nèi)存中的變量都加上標記(所有都加),然
后去掉環(huán)境變量中的變量,以及被環(huán)境變量中的變量所引用的變量(條件性去除
標記),刪除所有被標記的變量,刪除的變量無法在環(huán)境變量中被訪問所以會被
刪除,最后垃圾回收器,完成了內(nèi)存的清除工作,并回收他們所占用的內(nèi)存。
引用計數(shù)法
另一種不太常見的方法就是引用計數(shù)法,引用計數(shù)法的意思就是每個值沒引用的
次數(shù),當聲明了一個變量,并用一個引用類型的值賦值給改變量,則這個值的引
用次數(shù)為 1,;相反的,如果包含了對這個值引用的變量又取得了另外一個值,
則原先的引用值引用次數(shù)就減 1,當這個值的引用次數(shù)為 0 的時候,說明沒有辦
法再訪問這個值了,因此就把所占的內(nèi)存給回收進來,這樣垃圾收集器再次運行
的時候,就會釋放引用次數(shù)為 0 的這些值。
用引用計數(shù)法會存在內(nèi)存泄露,下面來看原因:
function problem() {
var objA = new Object();
var objB = new Object();
objA.someOtherObject = objB;
objB.anotherObject = objA;
}
在這個例子里面,objA 和 objB 通過各自的屬性相互引用,這樣的話,兩個對象
的引用次數(shù)都為 2,在采用引用計數(shù)的策略中,由于函數(shù)執(zhí)行之后,這兩個對象
都離開了作用域,函數(shù)執(zhí)行完成之后,因為計數(shù)不為 0,這樣的相互引用如果大
量存在就會導致內(nèi)存泄露。
特別是在 DOM 對象中,也容易存在這種問題:
var element=document.getElementById(’‘);
var myObj=new Object();
myObj.element=element;
element.someObject=myObj;
這樣就不會有垃圾回收的過程。
11.setTimeout、setInterval 和 requestAnimationFrame
之間的區(qū)別
與 setTimeout 和 setInterval 不同,requestAnimationFrame 不需要設置時間
間隔,
大多數(shù)電腦顯示器的刷新頻率是 60Hz,大概相當于每秒鐘重繪 60 次。大多數(shù)瀏
覽器都會對重繪操作加以限制,不超過顯示器的重繪頻率,因為即使超過那個頻
率用戶體驗也不會有提升。因此,最平滑動畫的最佳循環(huán)間隔是 1000ms/60,約
等于 16.6ms。
RAF 采用的是系統(tǒng)時間間隔,不會因為前面的任務,不會影響 RAF,但是如果前
面的任務多的話,73
會響應 setTimeout 和 setInterval 真正運行時的時間間隔。
特點:
(1)requestAnimationFrame 會把每一幀中的所有 DOM 操作集中起來,在一次
重繪或回流中就完成,并且重繪或回流的時間間隔緊緊跟隨瀏覽器的刷新頻率。
(2)在隱藏或不可見的元素中,requestAnimationFrame 將不會進行重繪或回
流,這當然就意味著更少的 CPU、GPU 和內(nèi)存使用量
(3)requestAnimationFrame 是由瀏覽器專門為動畫提供的 API,在運行時瀏覽
器會自動優(yōu)化方法的調(diào)用,并且如果頁面不是激活狀態(tài)下的話,動畫會自動暫停,
有效節(jié)省了 CPU 開銷
三十九.數(shù)據(jù)去重
法一:indexOf 循環(huán)去重
法二:ES6 Set 去重;Array.from(new Set(array))
法三:Object 鍵值對去重;把數(shù)組的值存成 Object 的 key 值,比如
Object[value1] = true,在判斷另一個值的時候,如果 Object[value2]存在的
話,就說明該值是重復的
四十.數(shù)組常用方法
push(),pop(),shift(),unshift(),splice(),sort(),reverse(),map()等
四十一. js 判斷類型
判斷方法:typeof(),instanceof,Object.prototype.toString.call()等
四十二. 事件代理在捕獲階段的實際應用
可以在父元素層面阻止事件向子元素傳播,也可代替子元素執(zhí)行某些操作。
四十三. 性能優(yōu)化
減少 HTTP 請求
使用內(nèi)容發(fā)布網(wǎng)絡(CDN)
添加本地緩存
壓縮資源文件
將 CSS 樣式表放在頂部,把 javascript 放在底部(瀏覽器的運行機制決定)
避免使用 CSS 表達式
減少 DNS 查詢
使用外部 javascript 和 CSS
避免重定向
圖片 lazyLoa
四十四.跨域的原理
跨域,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的,
是瀏覽器對 JavaScript 實施的安全限制,那么只要協(xié)議、域名、端口有任何一
個不同,都被當作是不同的域??缬蛟?,即是通過各種方式,避開瀏覽器的安
全限制
四十五.this 的指向 哪幾種
默認綁定:全局環(huán)境中,this 默認綁定到 window。
隱式綁定:一般地,被直接對象所包含的函數(shù)調(diào)用時,也稱為方法調(diào)用,this
隱式綁定到該直接對象。
隱式丟失:隱式丟失是指被隱式綁定的函數(shù)丟失綁定對象,從而默認綁定到
window。顯式綁定:通過 call()、apply()、bind()方法把對象綁定到 this 上,
叫做顯式綁定。
new 綁定:如果函數(shù)或者方法調(diào)用之前帶有關鍵字 new,它就構(gòu)成構(gòu)造函數(shù)調(diào)用。
對于 this 綁定來說,稱為 new 綁定。87
【1】構(gòu)造函數(shù)通常不使用 return 關鍵字,它們通常初始化新對象,當構(gòu)造函數(shù)
的函數(shù)體執(zhí)行完畢時,它會顯式返回。在這種情況下,構(gòu)造函數(shù)調(diào)用表達式的計
算結(jié)果就是這個新對象的值。
【2】如果構(gòu)造函數(shù)使用 return 語句但沒有指定返回值,或者返回一個原始值,
那么這時將忽略返回值,同時使用這個新對象作為調(diào)用結(jié)果。
【3】如果構(gòu)造函數(shù)顯式地使用 return 語句返回一個對象,那么調(diào)用表達式的值
就是這個對象
四十六.ES6 箭頭函數(shù)的特性
ES6 增加了箭頭函數(shù),基本語法為
let func = value => value;
相當于
let func = function (value) {
return value;
};
箭頭函數(shù)與普通函數(shù)的區(qū)別在于:
1、箭頭函數(shù)沒有 this,所以需要通過查找作用域鏈來確定 this 的值,這就意
味著如果箭頭函數(shù)被非箭頭函數(shù)包含,this 綁定的就是最近一層非箭頭函數(shù)的
this,
2、箭頭函數(shù)沒有自己的 arguments 對象,但是可以訪問外圍函數(shù)的 arguments
對象
3、不能通過 new 關鍵字調(diào)用,同樣也沒有 new.target 值和原型
四十七.async 和 await 具體該怎么用
(async () = > {
await new promise();
})()