前端面試題及答案(一)

## 前端javascript

**一.對閉包的理解,以及哪些地方用過閉包,以及閉包的缺點**
php

```javascript
<button id="add">加1</button>
<span id="span">10</span>
(function(){
var a = 10;
add.onclick = function (){
a++;
span.innerHTML = a;
}
})()
```css

**二.對跨域瞭解嗎,jsonp 的限制**前端

Q:爲何要跨域
A:跨域,一般狀況下是說在兩個不經過的域名下面沒法進行正常的通訊,或者說是沒法獲取其餘域名下面的數據,這個主要的緣由是,瀏覽器出於安全問題的考慮,採用了同源策略,經過瀏覽器對JS的限制,防止惡意用戶獲取非法的數據。

Q:同源策略
A:限制從一個源加載的文檔或腳本如何與來自另外一個源的資源進行交互。這是一個用於隔離潛在惡意文件的關鍵的安全機制。java

Q:「同源」
A:協議相同、域名相同、端口相同jquery

Q:同源政策的目的
A:是爲了保證用戶信息的安全,防止惡意的網站竊取數據。css3

Q:同源的限制範圍
A:Cookie、LocalStorage 和 IndexDB 沒法讀取;DOM 沒法得到;AJAX 請求不能發送程序員

**解決辦法**
JSONP
1.只支持GET請求而不支持POST等其它類型的HTTP請求(雖然採用post+動態生成iframe是能夠達到post 跨域的目的,但這樣作是一個比較極端的方式,不建議採用)。明確說明:jquery使用POST請求jsonp能夠成功是因爲jquery自動把POST轉化成GET,實際仍是GET請求
2. 通常get請求能完成全部功能。如:若是須要給其餘域服務器傳送參數能夠在請求後掛參數(注意不要掛隱私數據),即 <script src="http://xxx/getPerson.php?name=Hello&age=18"></script>
3. JSONP易於實現,可是也會存在一些安全隱患,若是第三方的腳本隨意地執行,那麼它就能夠篡改頁面內容,截獲敏感數據。
4.在受信任的雙方傳遞數據,JSONP是很是合適的選擇。
5.能夠看出來JSONP跨域通常用於獲取其餘域的數據。
6.通常可以用JSONP實現跨域就用JSONP實現,這也是前端用的最多的跨域方法。

window.name
一、必須與iframe配合使用
二、window.name 傳輸技術,本來是 Thomas Frank 用於解決 cookie 的一些劣勢(每一個域名 4 x 20 Kb的限制、數據只能是字符串、設置和獲取 cookie 語法的複雜等等)而發明的。後來 Kris Zyp 在此方法的基礎上強化了 window.name 傳輸 ,用來解決跨域數據傳輸問題。
3.window.name 的美妙之處:name值在不一樣的頁面(甚至不一樣域名)加載後依舊存在,而且能夠支持很是長的 name 值(2MB)。
特徵:
1.瀏覽器窗口有 window.name 屬性。這個屬性的最大特色是,不管是否同源,只要在同一個窗口裏,前一個網頁設置了這個屬性,後一個網頁能夠讀取它。
2.即在一個窗口(window)的生命週期內,窗口載入的全部的頁面都是共享一個window.name的,每一個頁面對window.name都有讀寫的權限,window.name是持久存在一個窗口載入過的全部頁面中的,並不會因新頁面的載入而進行重置。web

基本原理:
1.當在瀏覽器中打開一個頁面,或者在頁面中添加一個iframe時,即會建立一個對應的window對象,當頁面加載另外一個新的頁面時,window的name屬性是不會變的。
2.這樣就能夠利用在頁面動態添加一個iframe而後src加載數據頁面,在數據頁面將須要的數據賦值給window.name。
3.然而此時承載iframe的index頁面(也就是請求數據的頁面)仍是不能直接訪問,不在同一域下iframe的name屬性,這時只須要將iframe再加載一個與承載頁面同域的空白頁面,便可對window.name進行數據讀取面試

document.domain 跨域
這個的實現思路跟cookie跨域類似,都是在兩個關聯域名中設置document.domain值,而後讓這兩個值相等,這樣就能夠實現跨域操做

cookie跨域

postMessage跨域


**三..瀏覽器哪些地方用到了異步**

首先肯定JS是一門腳本語言,他的執行順序是從上到下逐行執行的,瀏覽器只有一個javascript引擎,因此瀏覽器同事只能執行一個任務,那麼異步操做的實現原理是什麼呢?
瀏覽器的javascript引擎確實是單線程的,可是瀏覽器自己是多線程的,瀏覽器包含
***javascript引擎線程、界面渲染線程、瀏覽器事件觸發線程、Http請求線程***
因此出發異步操做的時候,會有單獨的線程去作操做,javascript引擎線程不會受到阻塞,依然繼續解析js代碼。


**4、CSS 彈性佈局,哪些地方用到過**

flex佈局


**5、如何實現不定寬高水平和垂直居中**
1.最簡單的flex佈局
display: flex;
justify-content: center;
align-items: center;
2.利用table-cell
外層容器
display:table-cell;
text-align:center;
vertical-align:middle;
內部元素
vertical-align:middle;
display:inline-block;
3.使用CSS3 transform
外層容器
display:relative
內部元素
transform: translate(-50%,-50%);
position: absolute;
top: 50%;
left: 50%;

**6、const 和 let 區別,能夠改變 const 定義的某個對象的屬性嗎**

let與const都是隻在聲明所在的塊級做用域內有效。
let:無變量提高(未到let聲明時,是沒法訪問該變量的)
const:無變量提高,聲明一個基本類型的時候爲常量,不可修改;聲明對象能夠修改
const arr = {name:'小可愛', age:'21'}
arr.name = '萱萱'
console.log(arr)
由於對象是引用類型的,arr中保存的僅是對象的指針,這就意味着,const僅保證指針不發生改變,修改對象的屬性不會 改變
對象的指針,因此是被容許的。也就是說const定義的引用類型只要指針不發生改變,其餘的不論如何改變都是容許的。


**7、ES6 用到過嗎,新增了哪些東西,你用到過什麼**
定義變量加入了 let const
箭頭函數
Array.from() 將類數組對象與可遍歷對象轉換爲數組
類class

**8、箭頭函數,箭頭函數的特色, this 的指向**
箭頭函數是匿名函數,不綁定本身的this,arguments,super,new.target
箭頭函數會捕獲其所在上下文的this值,做爲本身的this值,在使用call/apply綁定時,至關於只是傳入了參 數,對this沒有影響

**9、數組去重**
ES6:Array.from(new Set(arr));
```javascript
<script type="text/javascript">
let arr = ['1',2,1,3,5,6,5]
let arrString = arr.toString()
console.log(arrString)
arrSplit = arr1.split(',') // 把一個字符串分割成字符串數組。
//join() 把數組中的全部元素放入一個字符串。
console.log(arrSplit)
let set = new Set(arrSplit)
console.log(set)
let newArr = Array.from(set)
console.log(newArr)
</script>
```

**10、哪些方法會改變原數組**

shift:將第一個元素刪除而且返回刪除元素,空即爲undefined
unshift:向數組開頭添加元素,並返回新的長度
pop:刪除最後一個並返回刪除的元素
push:向數組末尾添加元素,並返回新的長度
reverse:顛倒數組順序
sort:對數組排序
splice:splice(start,length,item)刪,增,替換數組元素,返回被刪除數組,無刪除則不返回


**11、深拷貝和淺拷貝**
淺拷貝: 將原對象或原數組的引用直接賦給新對象,新數組,新對象/數組只是原對象的一個引用
深拷貝: 建立一個新的對象和數組,將原對象的各項屬性的「值」(數組的全部元素)拷貝過來,是「值」而不是「引用」

深拷貝的要求程度
*咱們在使用深拷貝的時候,必定要弄清楚咱們對深拷貝的要求程度:是僅「深」拷貝第一層級的對象屬性或數組元素,仍是遞歸拷貝全部層級的對象屬性和數組元素?*

***深拷貝數組(只拷貝第一級數組元素)***
1.直接遍歷
2. slice()
slice() 方法返回一個從已有的數組中截取一部分元素片斷組成的新數組(不改變原來的數組!)
用法:array.slice(start,end) start表示是起始元素的下標, end表示的是終止元素的下標
當slice()不帶任何參數的時候,默認返回一個長度和原數組相同的新數組

```javascript
var array = [1, 2, 3, 4];
var copyArray = array.slice();
copyArray[0] = 100;
console.log(array); // [1, 2, 3, 4]
console.log(copyArray); // [100, 2, 3, 4]
```
3. concat()
```javascript
var array = [1, 2, 3, 4];
var copyArray = array.concat();
copyArray[0] = 100;
console.log(array); // [1, 2, 3, 4]
console.log(copyArray); // [100, 2, 3, 4]
```
***深拷貝對象***
1.直接遍歷
2.ES6的Object.assign

```javascript
var obj = {
name: '醉霜林',
job: '前端開發'
}
var copyObj = Object.assign({}, obj);
copyObj.name = '醉霜林2號';
console.log(obj); // {name: "醉霜林", job: "前端開發"}
console.log(copyObj); // {name: "醉霜林2號", job: "前端開發"}
```
Object.assign:用於對象的合併,將源對象(source)的全部可枚舉屬性,複製到目標對象(target),並返回合併後的target
用法: Object.assign(target, source1, source2); 因此 copyObj = Object.assign({}, obj); 這段代碼將會把obj中的一級屬性都拷貝到 {}中,而後將其返回賦給copyObj
3.ES6擴展運算符:
擴展運算符(...)用於取出參數對象的全部可遍歷屬性,拷貝到當前對象之中
**對多層嵌套對象,很遺憾,上面三種方法,都會失敗:**

```javascript
var obj = {
name: {
firstName: '醉',
lastName: '霜林'
},
job: '前端開發'
}

var copyObj = Object.assign({}, obj)
copyObj.name.lastName = '霜林醉';
console.log(obj.name.lastName); // 霜林醉
console.log(copyObj.name.lastName); // 霜林醉
```
***拷貝全部層級***

1.不只拷貝第一層級,還可以拷貝數組或對象全部層級的各項值
2. 不是單獨針對數組或對象,而是可以通用於數組,對象和其餘複雜的JSON形式的對象
下面這一招可謂是「一招鮮,吃遍天」

(1).JSON.parse(JSON.stringify(XXXX))
```javascript
var array = [
{ number: 1 },
{ number: 2 },
{ number: 3 }
];
var copyArray = JSON.parse(JSON.stringify(array))
copyArray[0].number = 100;
console.log(array); // [{number: 1}, { number: 2 }, { number: 3 }]
console.log(copyArray); // [{number: 100}, { number: 2 }, { number: 3 }]
```
2.手動寫遞歸

```javascript
var array = [
{ number: 1 },
{ number: 2 },
{ number: 3 }
];
function copy (obj) {
var newobj = obj.constructor === Array ? [] : {};
if(typeof obj !== 'object'){
return;
}
for(var i in obj){
newobj[i] = typeof obj[i] === 'object' ?
copy(obj[i]) : obj[i];
}
return newobj
}
var copyArray = copy(array)
copyArray[0].number = 100;
console.log(array); // [{number: 1}, { number: 2 }, { number: 3 }]
console.log(copyArray); // [{number: 100}, { number: 2 }, { number: 3 }]

```
***存在大量深拷貝需求的代碼——immutable提供的解決方案***

實際上,即便咱們知道了如何在各類狀況下進行深拷貝,咱們也仍然面臨一些問題: 深拷貝其實是很消耗性能的。(咱們可能只是但願改變新數組裏的其中一個元素的時候不影響原數組,但卻被迫要把整個原數組都拷貝一遍,這不是一種浪費嗎?)因此,當你的項目裏有大量深拷貝需求的時候,性能就可能造成了一個制約的瓶頸了。

immutable的做用:

經過immutable引入的一套API,實現:

1.在改變新的數組(對象)的時候,不改變原數組(對象)

2.在大量深拷貝操做中顯著地減小性能消耗

```javascript
const { Map } = require('immutable')
const map1 = Map({ a: 1, b: 2, c: 3 })
const map2 = map1.set('b', 50)
map1.get('b') // 2
map2.get('b') // 50
```

12、call() 和 apply() 的區別和做用?

區別:apply()與call()做用沒有區別,用法與call()方法稍有區別,就是call()的第二個參數(調用函數使用的參數),是一個一個傳入的;而apply()的第二個參數的值是使用數組的形式傳入的
做用:在Javascript中,每一個函數都包含兩個非繼承而來的方法,call和apply。這兩個方法的用途都是在特定的做用域中調用函數,實際上等於設置函數體內的this對象的值。

apply方法接收兩個參數,第一個參數是在其中運行函數的做用域,第二個是一個參數數組或者arguments對象。
call方法與apply方法做用相同,第一個參數也相同,區別在於,其他的參數須要逐個列出。

apply(thisArg, argArray);
call(thisArg[,arg1,arg2…]);

是使用call仍是apply要看具體的狀況。若是你知道全部參數或者參數的數量很少,可使用call;
若是參數的數量不肯定,或者數量很大,或者你收到的是一個數組或者是個arguments對象,則須要使用apply。
十3、localStorage sessionStorage Cookie
共同點:都是保存在瀏覽器端,且同源的。
不一樣點:
webstorage是本地存儲,存儲在客戶端,包括localStorage和sessionStorage。

**localStorage**:localStorage生命週期是永久,這意味着除非用戶顯示在瀏覽器提供的UI上清除 localStorage信息,不然這些信息將永遠存在。存放數據大小爲通常爲5MB,並且它僅在客戶端(即瀏覽器)中保存,不參與和服務器的通訊。

**sessionStorage**:sessionStorage僅在當前會話下有效,關閉頁面或瀏覽器後被清除。存放數據大小爲通常爲5MB,並且它僅在客戶端(即瀏覽器)中保存,不參與和服務器的通訊。源生接口能夠接受,亦可再次封裝來對Object和Array有更好的支持。

***localStorage和sessionStorage使用時使用相同的API:***

localStorage.setItem("key","value");//以「key」爲名稱存儲一個值「value」
localStorage.getItem("key");//獲取名稱爲「key」的值
localStorage.removeItem("key");//刪除名稱爲「key」的信息。
localStorage.clear();​//清空localStorage中全部信息

做用域不一樣:
不一樣瀏覽器沒法共享localStorage或sessionStorage中的信息。相同瀏覽器的不一樣頁面間能夠共享相同的 localStorage(頁面屬於相同域名和端口),可是不一樣頁面或標籤頁間沒法共享sessionStorage的信息。這裏須要注意的是,頁面及標 籤頁僅指頂級窗口,若是一個標籤頁包含多個iframe標籤且他們屬於同源頁面,那麼他們之間是能夠共享sessionStorage的。

**Cookie**
生命期爲只在設置的cookie過時時間以前一直有效,即便窗口或瀏覽器關閉。 存放數據大小爲4K左右 。有個數限制(各瀏覽器不一樣)。與服務器端通訊:每次都會攜帶在HTTP頭中,若是使用cookie保存過多數據會帶來性能問題。但Cookie須要程序員本身封裝,源生的Cookie接口不友好。


```javascript
//Cookie方法
<script src="../js/cookie.js"></script>//Cookie函數本身封裝引入
function haxi(){
if(getCookie("isClose")){
$(".header").hide();
}else{
$(".header").show();
}

$(".close").click(function(){
$(".header").fadeOut(1000);

setCookie("isClose", "1","s10");
})
}
haxi();
```
cookie的優勢:具備極高的擴展性和可用性
1.經過良好的編程,控制保存在cookie中的session對象的大小。
2.經過加密和安全傳輸技術,減小cookie被破解的可能性。
3.只有在cookie中存放不敏感的數據,即便被盜取也不會有很大的損失。
4.控制cookie的生命期,使之不會永遠有效。這樣的話偷盜者極可能拿到的就 是一個過時的cookie。

cookie的缺點:
1.cookie的長度和數量的限制。每一個domain最多隻能有20條cookie,每一個cookie長度不能超過4KB。不然會被截掉。
2.安全性問題。若是cookie被人攔掉了,那我的就能夠獲取到全部session信息。加密的話也不起什麼做用。
3.有些狀態不可能保存在客戶端。例如,爲了防止重複提交表單,咱們須要在服務端保存一個計數器。若吧計數器保存在客戶端,則起不到什麼做用。

**瀏覽器容許每一個域名所包含的cookie數**:
*Microsoft指出InternetExplorer8增長cookie限制爲每一個域名50個,但IE7彷佛也容許每一個域名50個cookie。
Firefox每一個域名cookie限制爲50個。
Opera每一個域名cookie限制爲30個。
Safari/WebKit貌似沒有cookie限制。可是若是cookie不少,則會使header大小超過服務器的處理的限制,會致使錯誤發生。
注:「每一個域名cookie限制爲20個」將再也不正確!*

**當不少的cookie被設置,瀏覽器如何去響應。**
除Safari(能夠設置所有cookie,無論數量多少),有兩個方法:
  最少最近使用(leastrecentlyused(LRU))的方法:當Cookie已達到限額,自動踢除最老的Cookie,以使給最新的Cookie一些空間。Internet Explorer和Opera使用此方法。

  Firefox很獨特:雖然最後的設置的Cookie始終保留,但彷佛隨機決定哪些cookie被保留。彷佛沒有任何計劃(建議:在Firefox中不要超過Cookie限制)。


**不一樣瀏覽器間cookie總大小也不一樣:**
 Firefox和Safari容許cookie多達4097個字節,包括名(name)、值(value)和等號。
 Opera容許cookie多達4096個字節,包括:名(name)、值(value)和等號。
 Internet Explorer容許cookie多達4095個字節,包括:名(name)、值(value)和等號。
注:多字節字符計算爲兩個字節。在全部瀏覽器中,任何cookie大小超過限制都被忽略,且永遠不會被設置。

**十3、事件機制**(太多 百度)

**十4、setTimeout機制(推薦:https://www.jianshu.com/p/3e482748369d?from=groupmessage)**

**十5、遇到過兼容性問題嗎,怎麼處理的**
一、內外邊距(初始化樣式或normalize css)
二、圖片默認有間距(display:block/float)
三、標籤最低高度設置min-height不兼容(min-height:200px; height:auto !important; height:200px; overflow:visible;)
四、chrome中文界面下默認會將小於12px的文本強制按照12px顯示 (添加css屬性-webkit-text-size-adjust:none;)
五、一些移動端設備不支持vedio和audio的自動播放(
document.addEventListener('touchstart',function() {
document.getElementsByTagName('audio')[0].play();
document.getElementsByTagName('audio')[0].pause();
});)
六、IE5-IE8不支持opacity(
Opacity:0.8;
Filter:alpha(opacity=80);
-ms-filter:」progid:DXImageTransform.Microsoft.Alpha(opacity=80)」;)

七、Firefox點擊連接出現的虛線框(a{outline:none;} a:focus{outline:none;})

八、css3種hack

 

 

 

 

 

 

 

 

參考部分面試題目或答案,若有遺漏,請私信補充。https://blog.csdn.net/zhang6223284/article/details/81273180https://blog.csdn.net/weixin_34116110/article/details/88624479https://blog.csdn.net/qq_39207948/article/details/81067482

相關文章
相關標籤/搜索