又快到了到金三四銀找工做的黃金時間,經過這些時間作面試題整理了一些經典必問的面試題,相信會對你們有幫助!javascript
1,獲取全部的DOM節點html
document.querySelectorAll('*')
此時獲得的是一個NodeList集合,咱們須要將其轉化成數組,而後對其篩選前端
2,轉化爲數組vue
[...document.querySelectorAll('*')]
一個拓展運算符就搞定java
3,獲取數組每一個元素的標籤名node
[...document.querySelectorAll('*')}.map(ele => ele.tagName)
使用一個map方法,將咱們須要的結果映射到一個新數組webpack
4,去重nginx
new Set([...document.querySelectorAll('*').map(ele=>ele.tagName)).size
咱們使用ES6中的set對象,把數組做爲構造函數的參數,就實現了去重,在使用Set對象的size方法就能夠獲得有多少種HTML元素了es6
async function async1() { console.log('async1 start'); await async2(); console.log('async1 end'); } async function async2() { console.log('async2'); } console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0) async1(); new Promise(function(resolve) { console.log('promise1'); resolve(); }).then(function() { console.log('promise2'); }); console.log('script end');
第一步,輸出script start
雖然有兩個函數聲明,有async關鍵字,可是沒有調用,就不看,直接打印同步代碼console.log(‘script start’)web
第二步,輸出async1 start
由於執行async1這個函數的時候,async表達式定義的函數也是當即執行
第三步,輸出async2
由於async2是async定義的函數,輸出async2並返回promise對象
第四步,輸出promise1
由於執行到new promise,promise是當即執行,就先打印promise1
第五步,輸出script end
由於上一步先打印了promise1,而後執行到resolve的時候,而後跳出promise繼續向下執行,輸出script end
第六步,輸出promise2
由於前面的nue promise放進resolve回調,因此resolve被放到調用棧執行
第七步,輸出async1 end
由於await定義的這個promise已經執行完,而且返回結果,因此繼續執行async1函數後的任務,就是console.log(‘async1 end’)
第八步,輸出setTimerout
setTimeout被放在最後被調用
列舉6種
<div class="parent"> <div class="child"> </div> </div> <style> .parent{ width: 550px; height: 550px; border: 1px solid #FF7F24; /* 方法一:定位 */ /* position: relative; */ /* 方法二:margin: auto */ /* position: relative; */ /* 方法三:利用display:table-cell */ /* display:table-cell 加上 vertical-align:middle和text-align:center 使高度不一樣的元素都水平垂直居中,其中display:inline-block使這兩個div在同一行顯示 */ /* display: table-cell; vertical-align: middle; text-align: center; */ /* 方法四:利用display:flex */ /* display: flex; justify-content: center; align-items: center; */ /* 方法五:計算父盒子與子盒子的空間距離(這跟方法一是一個道理) */ /* 方法六:利用transfrom */ /* position: relative */ /* 方法七:利用calc計算 */ /* position: relative; */ } .child{ width: 150px; height: 150px; border: 1px solid #FF3030; /* 方法一:定位 */ /* position: absolute; top: 50%; left: 50%; margin-top: -75px; margin-left: -75px; */ /* 方法二:margin: auto */ /* top: 0,left: 0,right: 0,bottom: 0就像四個方向有相同的力在拉這個盒子,而後margin:auto至關於平方剩餘空間居中 */ /* position: absolute; margin: auto; top: 0; left: 0; right: 0; bottom: 0; */ /* 方法三:利用display:table-cell */ /* display: inline-block */ /* 方法五:計算父盒子與子盒子的空間距離(這跟方法一是一個道理) */ /* (parent550-child150)÷2=200 */ /* margin-top: 200px; margin-left: 200px; */ /* 方法六:利用transfrom */ /* position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); */ /* 方法七:利用calc計算 */ /* top和left都是(父元素高-子元素高)÷2 */ /* position: absolute; top:calc(200px); left: calc(200px); */ } </style>
一、監聽數據變化的實現原理不一樣
二、數據流不一樣
三、組件通訊的區別
父組件經過props向子組件傳遞數據或回調
子組件經過事件event向父組件發送數據或回調
經過provide/inject實現父組件向子組件傳入數據,可跨層級
父組件經過props向子組件傳遞數據
React不支持子組件像父組件發送數據,而使用的是回調函數
經過 context實現父組件向子組件傳入數據, 可跨層級
四、模板渲染方式不一樣
React經過JSX渲染模板
Vue經過HTML進行渲染
React是經過原生JS實現模板中常見語法,如:插件,條件,循環
Vue是與組件JS分離的單獨模板,經過指令實現,如:v-if
五、模板中使用的數據
六、渲染過程不一樣
七、框架本質不一樣
八、Vuex和Redux的區別
九、組合不一樣功能方式不一樣
MVVM:MVVM是Model-View-ViewModel的簡寫
M指的是模型,V指的是視圖,VM指的是視圖模型
模型指的是後端傳遞的數據
視圖指的是所看到的頁面,試圖模型mvvm模式的核心,它是鏈接view和model的橋樑。
它有兩個方向:一是將模型轉化成試圖,即將後端傳遞的數據轉化成所看到的頁面。實現的方式是:數據綁定。二是將視圖轉化爲模型,即將所看到的頁面轉化成後端數據。
視圖模型指的是界面和對應的model,由於數據庫結構不能直接跟界面控件一一對應,因此,須要再定義一個數據對象專門對應view上的控件,而ViewModel的職責就是把model對象封裝成能夠顯示和接受輸入的界面數據對象
好比:
A複製了B,B被修改後
A要是隨着B的變化而變化,那就是淺拷貝
要是B改變了,A不變,那就是深拷貝
淺拷貝:
拷貝一層,對象級別的則拷貝引用
深拷貝:
拷貝多層,每一個層級的屬性都會拷貝
父向子傳遞數據經過props
子向父傳遞是經過$emit、event
子實例訪問父實例經過$parent
父實例訪問子實例經過$children
$attrs用父組件傳遞數據給子組件或孫組件
(包含了父做用域中不做爲 prop 被識別 (且獲取) 的特性綁定 (class 和 style 除外))
listeners用父組件傳遞數據給子組件或孫組件
包含了父做用域中的 (不含 .native 修飾器的) v-on 事件監聽器
祖先組件經過provider提供變量給子孫組件
子孫組件經過inject注入變量給祖先組件
ref用來訪問組件實例
emit用於父子、隔代、兄弟組件通訊
on用於父子、隔代、兄弟組件通訊
vuex用來做爲兄弟之間和跨級之間的通訊
相同點:
都是用來改變函數的this對象的指向的
第一個參數都是this要指向的對象
均可以利用後續參數傳參
區別:
call、apply的區別:接受參數的方式不同
bind:不當即執行。而apply、call 當即執行
若是事件處理函數調用的頻率無限制,會加劇瀏覽器的負擔,致使用戶體驗很是糟糕。此時咱們能夠採用debounce(防抖)和throttle(節流)的方式來減小調用頻率,同時又不影響實際效果
防抖:當持續觸發事件時,必定時間段內沒有再觸發事件,事件處理函數纔會執行一次,若是設定的時間到來以前,又一次觸發了事件,就從新開始延時
節流:當持續觸發事件時,保證必定時間段內只調用一次事件處理函數,原理是經過判斷是否到達必定時間來觸發函數。
節流無論事件觸發有多頻繁,都會保證在規定時間內必定會執行一次真正的事件處理函數,而函數防抖只是在最後一次事件後才觸發一次函數。 好比在頁面的無限加載場景下,咱們須要用戶在滾動頁面時,每隔一段時間發一次 Ajax 請求,而不是在用戶停下滾動頁面操做時纔去請求數據。這樣的場景,就適合用節流技術來實現
## 給數字增長「逗號」分隔?
<font color=#CD2626>例如輸入: '"123456789.888"' 輸出:123,456,789.888</font>
var rmb = 123456789.888; var retRmb = rmb.toFixed(3).replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,'); console.log(retRmb);
Vue響應式底層實現方法是Object.defineProperty()方法,該方法中存在一個getter和setter的可選項,能夠對屬性值的獲取和設置形成影響
Vue中編寫了一個wather來處理數據
在使用getter方法時,總會通知wather實例對view層渲染頁面
一樣的,在使用setter方法時,總會在變動值的同時,通知wather實例對view層進行更新
js的基本數據類型:
number、string、boolean、null、undefined、symbol(es6新增)
js的引用數據類型:
object、function
一、經過typeof判斷
經過typeof沒法判斷出數組、對象、null的具體類型
console.log(typeof 10); //number console.log(typeof NaN); //number console.log(typeof "10"); //string console.log(typeof false); //boolean console.log(typeof Symbol()); //symbol console.log(typeof function () {}); //function console.log(typeof []); //object console.log(typeof {}); //object console.log(typeof null); //object console.log(typeof undefined); //undefined
二、經過constructor判斷
經過constructor判斷數組和對象,但沒法判斷null,由於null不是對象 沒有construtor
console.log("".constructor == String); //true console.log(false.constructor == Boolean); //true console.log(new Number(10).constructor == Number); //true 這裏要使用對象的方式 console.log([].constructor == Array); //true console.log({}.constructor == Object); //true
三、經過instanceof判斷
instanceof是用於判斷A是否爲B的實例,由於instanceof是基於原型鏈進行檢測的,因此能夠經過instanceof檢測數組,可是要檢測對象就不是那麼準確了,由於數組對象也是Object
console.log([] instanceof Array); //true console.log([] instanceof Object); //true console.log({} instanceof Array); //false console.log({} instanceof Object); //true
四、經過Object.prototype.toString.call判斷
都能判斷出來,包括unll undefined
let getType = Object.prototype.toString; console.log(getType.call(undefined)); //[object Undefined] console.log(getType.call(null)); //[object Null] console.log(getType.call([])); //[object Array] console.log(getType.call({})); //[object Object]
## js中事件傳遞有哪幾個階段?
捕獲階段:先由文檔的根節點document往事件觸發對象,從外向內捕獲事件對象
目標階段:到達目標事件位置(事發地),觸發事件
冒泡階段:再從目標事件位置往文檔的根節點方向回溯,從內向外冒泡事件對象
this表示當前對象,this的指向是根據調用的上下文來決定的,默認指向window對象,指向window對象時能夠省略不寫
調用的上下文環境包括全局和局部
全局環境:
全局環境就是在<script></script>裏面,這裏的this始終指向的是window對象
局部環境:
在全局做用域下直接調用函數,this指向window
對象函數調用,哪一個對象調用就指向哪一個對象
使用new實例化對象,在構造函數中的this指向實例化對象
使用call或apply改變this的指向
其它:
用於區分全局變量和局部變量,須要使用this
返回函數當前的對象
前端緩存主要分爲HTTP緩存和瀏覽器緩存,
其中HTTP緩存是在HTTP請求傳輸時用到的緩存,
主要在服務器代碼上設置,而瀏覽器緩存則主要由前端js上進行設置
閉包就是可以讀取其餘函數內部變量的函數,也就是個函數,只不過是處於其餘函數內部而已
因爲在javascript中,只有函數內部的子函數才能讀取局部變量,因此說,閉包能夠簡單理解成「定義在一個函數內部的函數「
因此,在本質上,閉包是將函數內部和函數外部鏈接起來的橋樑
閉包能夠讀取函數內部的變量,和讓這些變量的值始終保持在內存中
適用場景:
採用函數引用方式的setTimeout調用
將函數關聯到對象的實例方法
封裝相關的功能集
每一個構造函數都有一個原型對象,
原型對象都包含一個指向構造函數想指針(constructor),而實例對象都包含一個指向原型對象的內部指針(__proto__)。
若是讓原型對象等於另外一個類型的實例,此時的原型對象將包含一個指向另外一個原型的指針(__proto__),另外一個原型也包含着一個指向另外一個構造函數的指針(constructor)。
假如另外一個原型又是另外一個類型的實例……這就構成了實例與原型的鏈條
原型鏈是實現繼承的主要方法
跨域是指一個域下的文檔或腳本試圖去請求另外一個域下的資源
跨域的解決方案:
Proxy的優勢:
能夠直接監聽對象而非屬性,並返回一個新對象
能夠直接監聽數值的變化
攔截方法較多
能夠劫持整個對象,並返回一個新對象
Proxy做爲新標準將受到瀏覽器廠商重點持續的性能優化
Proxy的缺點:
Proxy是es6提供的新特性,兼容性很差
Object.defineProperty的優勢:
兼容性好,支持IE9
IE9如下的版本不兼容
Object.defineProperty的缺點:
沒法監控到數組下標的變化,致使直接經過數組的下標給數組設置值,不能實時響應
只能劫持對象的屬性,咱們須要對每一個對象的每一個屬性進行遍歷
在vue2.0中,是經過遞歸+遍歷data對象來實現對數據的監控的,
若是屬性值也是對象,那麼須要深度遍歷,顯然若是能劫持一個完整的對象纔是最好的選擇,
因此在vue2.0中選Object.defineProperty,
當時雖然es6的新屬性出現了Proxy,可是兼容性很差,最主要的是這個屬性沒法用polyfill來兼容,
可是在vue3.0的版本中會有效的提供兼容解決方案
在vue3.0中,Proxy不用像Object.defineProperty給屬性都設置set,get的方法,因此Proxy不會觸發循環調用
key的做用是爲了在diff算法執行時更快的找到對應的節點,提升diff速度
vue組件高度複用增長key能夠標識組件的惟一性,爲了更高效更新虛擬DOM
Vue響應式底層實現方法是Object.defineProperty()方法,該方法中存在一個getter和setter的可選項,能夠對屬性值的獲取和設置形成影響
Vue中編寫了一個wather來處理數據
在使用getter方法時,總會通知wather實例對view層渲染頁面
一樣的,在使用setter方法時,總會在變動值得同時,通知wather實例對view層進行更新
若是data是一個函數的話,這樣沒複用一次組件,就會返回一份新的data,相似於給每一個組件實例建立一個私有的數據空間,讓各個組件實例維護各自的數據。而單純的寫成對象形式,就使得全部組件實例共用一份data,就會形成一個變了全都會變得結果
因此說vue組件的data必須是函數。這都是由於js的特性帶來的,跟vue自己設計無關。
js自己的面向對象編程也是基於原型鏈和構造函數,應該會注意原型鏈上添加通常都是一個函數方法而不會去添加一個對象了
一、把模板編譯爲render函數
二、實例進行掛載, 根據根節點render函數的調用,遞歸的生成虛擬dom
三、對比虛擬dom,渲染到真實dom
四、組件內部data發生變化,組件和子組件引用data做爲props從新調用render函數,生成虛擬dom, 返回到步驟3
webpack是一個打包模塊化JavaScript的工具,在webpack裏一切文件皆模塊,經過Loader轉換文件,經過Plugin注入鉤子,最後輸出由多個模塊組合成得文件,webpack專一於構建模塊化項目
一、利用babel完成代碼轉換及解析,並生成單個文件的依賴模塊Map
二、從入口開始遞歸分析,並生成整個項目的依賴圖譜
三、將各個引用模塊打包爲一個當即執行函數
四、將最終的bundle文件寫入bundle.js中
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> </head> <body> <div id="app"></div> </body> </html> <style> #app{ width: 0; height: 0; border: 93px solid; border-color: red green yellow transparent; } </style>
這裏主要用到了CSS3的一個transparent屬性
transparent是透明的意思,在CSS3之後,支持全部的coloe屬性
畫的三角形其實border的寬度加上顏色來控制的,其實三角形的造成不過是,其它的邊框顏色設置成了透明瞭而已
E:last-child匹配父元素的最後一個子元素E
E:nth-child(n)匹配父元素的第n個子元素E
E:nth-last-child(n)匹配父元素的倒數第n個子元素E
static:默認值 沒有定位,元素出如今正常的流中
absolute:絕對定位 相對於static定位之外的第一個父元素進行定位
relative:相對定位 生成相對定位的元素,相對於其正常位置進行定位
fixed:固定定位 生成絕對定位的元素,相對於瀏覽器窗口進行定位
緩存是創建一個函數的過程,這個函數可以記住以前計算的結果或值。使用緩存函數是爲了不在最後一次使用相同參數的計算中已經執行的函數的計算。這節省了時間,但也有不利的一面,即咱們將消耗更多的內存來保存之前的結果
原型鏈繼承:父類的實例做爲子類的原型
借用構造函數繼承:複製父類的實例屬性給子類
組合繼承:調用父類構造函數,繼承父類的屬性,經過將父類實例做爲子類原型,實現函數複用
原型式繼承:不自定義類型的狀況下,臨時建立一個構造函數,藉助已有的對象做爲臨時構造函數的原型,而後在此基礎實例化對象,並返回
寄生式繼承:其實就是在原型式繼承獲得對象的基礎上,在內部再以某種方式來加強對象,而後返回
寄生組合繼承:經過寄生的方式來修復組合式繼承的不足,完美的實現繼承
但願看到文章的同窗都有收穫!
文章要是有不對的地方還望指正!
最後祝你們都愈來愈優秀!
歡迎你們加入,一塊兒學習前端,共同進步!