題目來源來自:https://xiedaimala.com/tasks/e67878e4-ef45-4545-9cad-a1946c6e21f1
HTML
1.如何理解 HTML 語義化的?
1.讓頁面內(nèi)容結(jié)構(gòu)化,易于理解
2.利于搜索引擎的爬蟲和SEO
3.在沒有css的情況下也一樣方便閱讀和理解
4.便于維護(hù)
比如,
標(biāo)題可以用 <h1> ~ <h6>;
邊欄用 <aside>;
頭部用 <header>;
主體內(nèi)容用 <main>;
頁腳用 <footer>;
2.meta viewport 是做什么用的,怎么寫?
meta viewport主要是用來適配移動端的,寫法如下:
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0/>
3.你用過哪些 HTML 5 標(biāo)簽?
<header>定義一個頁面或是區(qū)域的頭部</header>
<div>
<section>定義一個區(qū)域</section>
<aside>定義頁面內(nèi)容的側(cè)邊框部分</aside>
</div>
<footer>定義一個頁面或是區(qū)域的底部</footer>
4.H5 是什么?
因為H5不僅指HTML5,一般客戶所說的H5涉及到的技術(shù)范圍太廣了,所以
可以理解為通過前端開發(fā)實現(xiàn)一種市面上可以有比較炫酷動效或者功能的手機(jī)端網(wǎng)頁
CSS
1.說一下兩種盒模型
W3C標(biāo)準(zhǔn)盒子模型
W3C標(biāo)準(zhǔn)盒子模式包括內(nèi)容(content)、填充(padding)、邊框(border)、邊界(margin)
IE盒子模型
width和height把padding和border包括進(jìn)去了。
2.如何垂直居中?
有好幾種方式,這里我主要記三種
- flex實現(xiàn)
<div class="parent">
<div class="child"></div>
</div>
.parent{
width:300px;
height:300px;
display:flex;
align-items:center;
}
.child{
width:100px;
height:100px;
}
- 利用絕對定位實現(xiàn)
.parent{
width:300px;
height:300px;
position:relative;
}
.child{
width:100px;
height:100px;
position:absolute;
top: 50%;
margin-top: -50px;/*如果不確定元素的高度,可以使用transform:translateY(-50%)*/
}
-
利用display:table-cell實現(xiàn)
給父元素display:table,子元素display:table-cell的方式實現(xiàn)CSS垂直居中。
.parent{
width:300px;
height:300px;
display:table;
}
.child{
width:100px;
height:100px;
display:table-cell;
vertical-align:venter;
}
原生JS
1.必考:ES 6 語法知道哪些,分別怎么用?
let關(guān)鍵字,可以聲明一個塊級作用域的變量
let與var的區(qū)別,let聲明一個塊級作用域的變量,而var聲明一個函數(shù)作用域的變量。簡單來說,let聲明的變量只作用在它所在的花括號內(nèi)const關(guān)鍵字:聲明一些不允許改變的量
模板字符串:
在ES6之前,我們往往這么處理模板字符串:
通過“\”和“+”來構(gòu)建模板
而對ES6來說
基本的字符串格式化。將表達(dá)式嵌入字符串中進(jìn)行拼接。用${}來界定;
ES6反引號(``)直接搞定;箭頭函數(shù)(Arrow Function):
箭頭函數(shù)有幾個使用注意點。
(1)函數(shù)體內(nèi)的 this 對象,就是定義時所在的對象,而不是使用時所在的對象。
(2)不可以當(dāng)作構(gòu)造函數(shù),也就是說,不可以使用 new 命令,否則會拋出一個錯誤。
(3)不可以使用 arguments 對象,該對象在函數(shù)體內(nèi)不存在。如果要用,可以用 rest 參數(shù)代替。
(4)不可以使用 yield 命令,因此箭頭函數(shù)不能用作 Generator 函數(shù)。函數(shù)的參數(shù)默認(rèn)值
在ES6之前,我們往往這樣定義參數(shù)的默認(rèn)值:
// ES6之前,當(dāng)未傳入?yún)?shù)時,text = 'default';
function printText(text) {
text = text || 'default';
console.log(text);
}
// ES6;
function printText(text = 'default') {
console.log(text);
}
printText('hello'); // hello
printText();// default
-
類
我們知道,javascript和其他語言不同,它不是傳統(tǒng)的面向?qū)ο蟮恼Z言,我們通常使用function來模仿對象,以下是最常用的方法:
function people(身高, 體重) {
//people對象的屬性
this.身高 = 身高;
this.體重 = 體重;
}
//people對象的方法
people.prototype.說話 = function () {
alert("我很帥")
};
代碼看著不是很直觀,剛接觸js的程序員很難想到這是一個對象,而且方法和屬性沒有寫在一起,代碼整潔性很差。
在ES6我們引入CLASS,這樣寫:
class people {
//屬性寫這里
constructor(身高, 體重) {
this.身高 = 身高;
this.體重 = 體重;
}
//方法寫這里
speak() {
alert("我很帥")
}
}
類的繼承
既然ES6中我們的類用class寫,那么類的繼承又該怎么實現(xiàn)呢?還是之前的例子,在ES5中,我們要寫一個繼承是很麻煩的。我們用對象冒充/call/apply方法繼承對象屬性,用原型鏈繼承對象的方法。就好像這樣:
function man(身高, 體重){
people.call(this,身高,體重) //call()繼承屬性
}
man.prototype = new people()//原型鏈繼承方法
ES6中我們實現(xiàn)類的繼承更為方便,先看下面例子:
class man extends people{
constructor(身高,體重){
super(身高,體重)
}
}
我們使用extends people()來實現(xiàn)原型鏈繼承,繼承了父類原型中的方法;super()參數(shù)填寫需要繼承的父類屬性;constructor()中填寫子類的所有屬性。
在作用上,class繼承與傳統(tǒng)的“function繼承”沒有任何區(qū)別。實際上,class就是語法糖,它大大簡化了繼承所需要的代碼。
2.必考 Promise、Promise.all、Promise.race 分別怎么用?
3.必考:手寫函數(shù)防抖和函數(shù)節(jié)流
//外賣配送接單,js防抖舉例子
function debounce(fn,wait) {
var timerId = null;
return function(){
if(timer !== null){
clearTimeout(timer);
}
timer = setTimeout(()=>{
fn()
},wait)
}
};
//js節(jié)流,例如游戲技能cd
//節(jié)流throttle代碼:
function throttle(fn, delay) {
let canRun = true; // 通過閉包保存一個標(biāo)記
return function() {
// 在函數(shù)開頭判斷標(biāo)記是否為true,不為true則return
if (!canRun) return;
// 立即設(shè)置為false
canRun = false;
// 將外部傳入的函數(shù)的執(zhí)行放在setTimeout中
setTimeout(() => {
// 最后在setTimeout執(zhí)行完畢后再把標(biāo)記設(shè)置為true(關(guān)鍵)表示可以執(zhí)行下一次循環(huán)了。
// 當(dāng)定時器沒有執(zhí)行的時候標(biāo)記永遠(yuǎn)是false,在開頭被return掉
fn.apply(this, arguments);
canRun = true;
}, delay);
};
}
4.必考:手寫AJAX
function ajax(type, url, success) {
var req = new XMLHttpRequest();
req.open(type, url, true);
req.send();
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
var result = req.responseText;
success(result);
}
};
}
ajax("GET", "http://xxxx", function(result) {
console.log(result);
});
5.必考:這段代碼里的 this 是什么?
this的指向:
- fn()
this=> window/global - obj.fn()
this=>obj - fn.call(xx)
this=>xx - fn.bind(xx)
this=>xx - fn.apply(xx)
this=>xx - new Fn()
this=>新對象 - fn=()=>{}
this=>外面的this
6.必考:閉包/立即執(zhí)行函數(shù)是什么?
閉包:由于在JS中,變量的作用域?qū)儆诤瘮?shù)作用域,在函數(shù)執(zhí)行后作用域就會被清理、內(nèi)存也隨之回收,但是由于閉包是建立在一個函數(shù)內(nèi)部的子函數(shù),由于其可訪問上級作用域的原因,即使上級函數(shù)執(zhí)行完,作用域也不會隨之銷毀,這時的子函數(shù)——也就是閉包,便擁有了訪問上級作用域中的變量的權(quán)限,即使上級函數(shù)執(zhí)行完后作用域內(nèi)的值也不會被銷毀。
7.必考:什么是 JSONP,什么是 CORS,什么是跨域?
什么是跨域?
跨域,指的是瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器施加的安全限制。
同源又是什么呢?
所謂同源是指,域名,協(xié)議,端口均相同。
如:
http://www.abc.com/index.html 調(diào)用 http://www.abc.com/server.php (非跨域)
http://www.abc.com/index.html 調(diào)用 http://www.bcd.com/server.php (主域名不同:abc/bcd,跨域)
http://abc.123.com/index.html 調(diào)用 http://bcd.123.com/server.php (子域名不同:abc/bcd,跨域)
http://www.abc.com:8080/index.html 調(diào)用 http://www.abc.com:8081/server.php (端口不同:8080/8081,跨域)
http://www.abc.com/index.html 調(diào)用 https://www.abc.com/server.php (協(xié)議不同:http/https,跨域)
什么是CORS?
查閱mdn關(guān)于CORS可知,跨域資源共享(CORS) 是一種機(jī)制,它使用額外的 HTTP 頭來告訴瀏覽器 讓運行在一個 origin (domain) 上的Web應(yīng)用被準(zhǔn)許訪問來自不同源服務(wù)器上的指定的資源。當(dāng)一個資源從與該資源本身所在的服務(wù)器不同的域、協(xié)議或端口請求一個資源時,資源會發(fā)起一個跨域 HTTP 請求。
什么是JSONP?
JSONP就可以解決跨域問題。JSONP是網(wǎng)頁通過動態(tài)創(chuàng)建<script>元素向服務(wù)器發(fā)起請求,當(dāng)服務(wù)器接收到請求后,將數(shù)據(jù)放在一個指定名字的回調(diào)函數(shù)里傳回來。而正因此<script>只能GET不能POST,JSONP也只能GET不能POST。
解決跨域問題
JSONP
代理
例如www.abc.com/index.html需要調(diào)用www.bcd.com/server.php,可以寫一個接口www.abc.com/server.php,由這個接口在后端去調(diào)用www.bcd.com/server.php并拿到返回值,然后再返回給index.html,這就是一個代理的模式。相當(dāng)于繞過了瀏覽器端,自然就不存在跨域問題。
PHP端修改header(XHR2方式)
在php接口腳本中加入以下兩句即可:
header('Access-Control-Allow-Origin:*');//允許所有來源訪問
header('Access-Control-Allow-Method:POST,GET');//允許訪問的方式
8.實現(xiàn)一個new操作:
- 新生成了一個對象
- 新對象隱式原型鏈接到函數(shù)原型
- 調(diào)用函數(shù)綁定this
- 返回新對象
new Person("John") = {
var obj = {};
obj.__proto__ = Person.prototype; // 此時便建立了obj對象的原型鏈: obj->Person.prototype->Object.prototype->null
var result = Person.call(obj,"John"); // 相當(dāng)于obj.Person("John")
return typeof result === 'object' ? result : obj; // 如果無返回值或者返回一個非對象值,則將obj返回作為新對象
}
常考:async/await 怎么用,如何捕獲異常?
常考:如何實現(xiàn)深拷貝?
常考:如何用正則實現(xiàn) trim()?
常考:不用 class 如何實現(xiàn)繼承?用 class 又如何實現(xiàn)?
常考:如何實現(xiàn)數(shù)組去重?
放棄:== 相關(guān)題目(反著答)
送命題:手寫一個 Promise
HTTP
1.cookie,sessionStorage,localStorage的區(qū)別?
相同點:
cookie,localStorage,sessionStorage都是在客戶端保存數(shù)據(jù)的,存儲數(shù)據(jù)的類型:都是字符串。
不同點:
1、生命周期:
1)cookie如果不設(shè)置有效期,那么就是臨時存儲(存儲在內(nèi)存中),是會話級別的,會話結(jié)束后,cookie也就失效了,如果設(shè)置了有效期,那么cookie存儲在硬盤里,有效期到了,就自動消失了。
2)localStorage的生命周期是永久的,關(guān)閉頁面或瀏覽器之后localStorage中的數(shù)據(jù)也不會消失。localStorage除非主動刪除數(shù)據(jù),否則數(shù)據(jù)永遠(yuǎn)不會消失。
3)sessionStorage僅在當(dāng)前會話下有效。sessionStorage引入了一個“瀏覽器窗口”的概念,sessionStorage是在同源的窗口中始終存在的數(shù)據(jù)。只要這個瀏覽器窗口沒有關(guān)閉,即使刷新頁面或者進(jìn)入同源另一個頁面,數(shù)據(jù)依然存在。但是sessionStorage在關(guān)閉了瀏覽器窗口后就會被銷毀。同時獨立的打開同一個窗口同一個頁面,sessionStorage也是不一樣的。
2、網(wǎng)絡(luò)流量:cookie的數(shù)據(jù)每次都會發(fā)給服務(wù)器端,而localstorage和sessionStorage不會與服務(wù)器端通信,純粹為了保存數(shù)據(jù),所以,webstorage更加節(jié)約網(wǎng)絡(luò)流量。
3、大小限制:cookie大小限制在4KB,非常小;localstorage和sessionStorage在5M
4、安全性:WebStorage不會隨著HTTP header發(fā)送到服務(wù)器端,所以安全性相對于cookie來說比較高一些,不會擔(dān)心截獲。
5、使用方便性上:WebStorage提供了一些方法,數(shù)據(jù)操作比cookie方便;
setItem (key, value) —— 保存數(shù)據(jù),以鍵值對的方式儲存信息。
getItem (key) —— 獲取數(shù)據(jù),將鍵值傳入,即可獲取到對應(yīng)的value值。
removeItem (key) —— 刪除單個數(shù)據(jù),根據(jù)鍵值移除對應(yīng)的信息。
clear () —— 刪除所有的數(shù)據(jù)
key (index) —— 獲取某個索引的key
2.HTTP緩存圖解
3.Http 請求的整個過程
1.域名解析 --> 2.發(fā)起 TCP 的 3 次握手 --> 3.建立 TCP 連接后發(fā)起 http 請求 --> 4.服務(wù)器響應(yīng) http 請求,瀏覽器得到 html 代碼 --> 5.瀏覽器解析 html 代碼,并請求 html 代碼中的資源(如 js、css、圖片等) --> 6.瀏覽器對頁面進(jìn)行渲染呈現(xiàn)給用戶