## 前端
**一.對閉包的理解,以及哪些地方用過閉包,以及閉包的缺點**
```javascript
<button id="add">加1</button>
<span id="span">10</span>
(function(){
var a = 10;
add.onclick = function (){
a++;
span.innerHTML = a;
}
})()
```
**二.對跨域了解嗎,jsonp 的限制**
Q:為什么要跨域
A:跨域,通常情況下是說在兩個不通過的域名下面無法進行正常的通信,或者說是無法獲取其他域名下面的資料,這個主要的原因是,瀏覽器出于安全問題的考慮,采用了同源策略,通過瀏覽器對JS的限制,防止惡意用戶獲取非法的資料,
Q:同源策略
A:限制從一個源加載的檔案或腳本如何與來自另一個源的資源進行互動,這是一個用于隔離潛在惡意檔案的關鍵的安全機制,
Q:“同源”
A:協議相同、域名相同、埠相同
Q:同源政策的目的
A:是為了保證用戶資訊的安全,防止惡意的網站竊取資料,
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
1、必須與iframe配合使用
2、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是持久存在一個視窗載入過的所有頁面中的,并不會因新頁面的載入而進行重置,
基本原理:
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代碼,
**四、CSS 彈性布局,哪些地方用到過**
flex布局
**五、如何實作不定寬高水平和垂直居中**
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%;
**六、const 和 let 區別,可以改變 const 定義的某個物件的屬性嗎**
let與const都是只在宣告所在的塊級作用域內有效,
let:無變數提升(未到let宣告時,是無法訪問該變數的)
const:無變數提升,宣告一個基本型別的時候為常量,不可修改;宣告物件可以修改
const arr = {name:'小可愛', age:'21'}
arr.name = '萱萱'
console.log(arr)
因為物件是參考型別的,arr中保存的僅是物件的指標,這就意味著,const僅保證指標不發生改變,修改物件的屬性不會 改變
物件的指標,所以是被允許的,也就是說const定義的參考型別只要指標不發生改變,其他的不論如何改變都是允許的,
**七、ES6 用到過嗎,新增了哪些東西,你用到過什么**
定義變數加入了 let const
箭頭函式
Array.from() 將類陣列物件與可遍歷物件轉換為陣列
類class
**八、箭頭函式,箭頭函式的特點, this 的指向**
箭頭函式是匿名函式,不系結自己的this,arguments,super,new.target
箭頭函式會捕獲其所在背景關系的this值,作為自己的this值,在使用call/apply系結時,相當于只是傳入了參 數,對this沒有影響
**九、陣列去重**
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>
```
**十、哪些方法會改變原陣列**
shift:將第一個元素洗掉并且回傳洗掉元素,空即為undefined
unshift:向陣列開頭添加元素,并回傳新的長度
pop:洗掉最后一個并回傳洗掉的元素
push:向陣列末尾添加元素,并回傳新的長度
reverse:顛倒陣列順序
sort:對陣列排序
splice:splice(start,length,item)刪,增,替換陣列元素,回傳被洗掉陣列,無洗掉則不回傳
**十一、深拷貝和淺拷貝**
淺拷貝: 將原物件或原陣列的參考直接賦給新物件,新陣列,新物件/陣列只是原物件的一個參考
深拷貝: 創建一個新的物件和陣列,將原物件的各項屬性的“值”(陣列的所有元素)拷貝過來,是“值”而不是“參考”
深拷貝的要求程度
*我們在使用深拷貝的時候,一定要弄清楚我們對深拷貝的要求程度:是僅“深”拷貝第一層級的物件屬性或陣列元素,還是遞回拷貝所有層級的物件屬性和陣列元素?*
***深拷貝陣列(只拷貝第一級陣列元素)***
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
```
十二、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,
十三、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="https://www.cnblogs.com/daizhong/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大小超過限制都被忽略,且永遠不會被設定,
**十三、事件機制**(太多 百度)
**十四、setTimeout機制(推薦:https://www.jianshu.com/p/3e482748369d?from=groupmessage)**
**十五、遇到過兼容性問題嗎,怎么處理的**
1、內外邊距(初始化樣式或normalize css)
2、圖片默認有間距(display:block/float)
3、標簽最低高度設定min-height不兼容(min-height:200px; height:auto !important; height:200px; overflow:visible;)
4、chrome中文界面下默認會將小于12px的文本強制按照12px顯示 (添加css屬性-webkit-text-size-adjust:none;)
5、一些移動端設備不支持vedio和audio的自動播放(
document.addEventListener('touchstart',function() {
document.getElementsByTagName('audio')[0].play();
document.getElementsByTagName('audio')[0].pause();
});)
6、IE5-IE8不支持opacity(
Opacity:0.8;
Filter:alpha(opacity=80);
-ms-filter:”progid:DXImageTransform.Microsoft.Alpha(opacity=80)”;)
7、Firefox點擊鏈接出現的虛線框(a{outline:none;} a:focus{outline:none;})
8、css3種hack
參考部分面試題目或答案,如有遺漏,請私信補充,
https://blog.csdn.net/zhang6223284/article/details/81273180
https://blog.csdn.net/weixin_34116110/article/details/88624479
https://blog.csdn.net/qq_39207948/article/details/81067482
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/6701.html
標籤:其他
上一篇:TCP協議如何保證可靠傳輸?
