一痊剖、js面試題
- JavaScript 中的 this 究竟指向誰(shuí)肢专,箭頭函數(shù)的 this 有什么不同
- 普通函數(shù)
this 永遠(yuǎn)指向調(diào)用它的對(duì)象谚鄙,new的時(shí)候,指向new出來(lái)的對(duì)象形病。 - 箭頭函數(shù)
箭頭函數(shù)沒(méi)有自己的 this,當(dāng)在內(nèi)部使用了 this時(shí)霞幅,它會(huì)指向最近一層作用域內(nèi)的 this
- 深拷貝和淺拷貝的區(qū)別漠吻?如何實(shí)現(xiàn)?
兩者的區(qū)別:一個(gè)對(duì)象淺復(fù)制后,是深層次的對(duì)象地址的復(fù)制司恳,并沒(méi)有開(kāi)辟新的棧途乃,也就是復(fù)制的結(jié)果是兩個(gè)對(duì)象指向同一個(gè)地址,修改其中一個(gè)對(duì)象的屬性扔傅,則另一個(gè)對(duì)象的屬性也會(huì)發(fā)生改變耍共,而深復(fù)制的則是開(kāi)辟了一個(gè)新的棧,兩個(gè)對(duì)象對(duì)應(yīng)兩個(gè)不同的地址猎塞,修改一個(gè)對(duì)象的屬性试读,不會(huì)改變另一個(gè)對(duì)象的屬性。
JSON.stringify與JSON.parse可以實(shí)現(xiàn)深拷貝,還可以借用JQ的extend方法荠耽。
- 1.可以遞歸遞歸去復(fù)制所有層級(jí)屬性
// 原始對(duì)象
var obj = {
a:1,
arr: [2,3],
say:function(){
console.log('hello')
},
obj1:{
arr:[34,55,5],
hand:function(){
console.log('hand')
},
obj3:{
a:1,
take:function(){
console.log('take')
}
}
}
};
// 開(kāi)始淺復(fù)制
var shallowObj = shallowCopy(obj);
// 定義淺復(fù)制邏輯
function shallowCopy(src) {
var dst = {};
for (var prop in src) {
if (src.hasOwnProperty(prop)) {
dst[prop] = src[prop];
}
}
return dst;
}
// 改變復(fù)制后的新對(duì)象的屬性值(第二層以及更深層次)
shallowObj.obj1.obj3.take = function(){
console.log('shallowObj_take')
}
shallowObj.obj1.hand = function(){
console.log('shallowObj_hand')
}
// 打印新對(duì)象的方法調(diào)用
shallowObj.obj1.obj3.take(); // shallowObj_take
shallowObj.obj1.hand(); // shallowObj_hand
// 打印原對(duì)象的方法調(diào)用
obj.obj1.obj3.take(); // shallowObj_take
obj.obj1.hand(); // shallowObj_hand
問(wèn)題出現(xiàn)了:原對(duì)象的方法被新對(duì)象的修改钩骇,而產(chǎn)生變化。
原因是復(fù)制的是對(duì)象的地址指針铝量,兩個(gè)屬性共同指向一個(gè)對(duì)象倘屹,只要其一發(fā)生變化,另一個(gè)也隨之變化
- JSON.stringify與JSON.parse實(shí)現(xiàn)深拷貝
function deepClone(obj){
let _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone
}
let a=[0,1,[2,3],4],
b=deepClone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
- JQ的extend方法
let a=[0,1,[2,3],4],
b=$.extend(true,[],a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
- js的事件委托是什么慢叨,原理是什么纽匙?
事件委托就是利用事件冒泡,只指定一個(gè)事件處理程序拍谐,就可以管理某一類型的所有事件哄辣。用事件委托就可以只用一次dom操作就能完成所有的效果请梢。 - 如何判斷一個(gè)變量是否為數(shù)組(isArray)
1、instanceof
function isArray (obj) {
return obj instanceof Array;
}
2力穗、Array對(duì)象的 isArray方法
function isArray (obj) {
return Array.isArray(obj);
}
3毅弧、Object.prototype.toString
function isArray (obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
'DOM2級(jí)事件'規(guī)定的事件流包含3個(gè)階段:事件捕獲,處于目標(biāo)当窗,事件冒泡
阻止事件冒泡:event.stopPropagation()
阻止默認(rèn)行為:e.preventDefault()
回調(diào)地獄和回調(diào)函數(shù)
回調(diào)地獄(函數(shù)作為參數(shù)層層嵌套)
回調(diào)函數(shù)(一個(gè)函數(shù)作為參數(shù)需要依賴另一個(gè)函數(shù)執(zhí)行調(diào)用)數(shù)組的基本方法
push和unshift够坐,返回值是length
pop和shift,返回值是刪除的當(dāng)前項(xiàng)
slice:抽取當(dāng)前數(shù)組中的一段元素組合成一個(gè)新數(shù)組崖面。第一個(gè)參數(shù)從哪里開(kāi)始元咙,第二個(gè)參數(shù)是到哪結(jié)束
數(shù)組splice第一個(gè)參數(shù)是索引,第二個(gè)參數(shù)是想修改或者刪除幾個(gè)元素巫员,第三個(gè)是添加的內(nèi)容
split把字符串分割成數(shù)組
sort排序 reverse反轉(zhuǎn)數(shù)組 concat連接兩個(gè)數(shù)組
Array.prototype.includes()
:判斷數(shù)組中是否包含某指定的值數(shù)組去重的方法
- es6方法:[...new Set(arr)]或者Array.from(new Set(arr))
forEach + indexOf res.indexOf(val)=== -1庶香,該方法不足之處是NaN進(jìn)行過(guò)濾,改善的方法是使用includes方法 - filter+indexOf
- forEach + includes
- reduce + includes
- 嵌套循環(huán)+splice
- hash+hasOwnProperty+JSON.stringify
- 判斷一個(gè)變量是不是數(shù)組的可靠的方法:
Object.prototype.toString.call(list) //[object Array]
Array.isArray(list) //true
typeof和instanceof的區(qū)別
typeof返回的類型都是字符串形式
instanceof简识,后面一定要是對(duì)象類型赶掖,并且大小寫(xiě)不能錯(cuò),該方法適合一些條件選擇或分支七扰。call & apply & bind() 之間的區(qū)別:
call和apply都是改變this指向的方法奢赂,區(qū)別在于call可以寫(xiě)多個(gè)參數(shù),而apply只能寫(xiě)兩個(gè)參數(shù)颈走,第二個(gè)參數(shù)是一個(gè)數(shù)組膳灶,用于存放要傳的參數(shù)。
bind()返回的是一個(gè)新函數(shù)立由,必須調(diào)用它才會(huì)執(zhí)行基本數(shù)據(jù)類型
(ES6之前)其中5種為基本類型:string,number,boolean,null,undefined,
ES6出來(lái)的Symbol也是原始數(shù)據(jù)類型 轧钓,表示獨(dú)一無(wú)二的值
基本類型的存儲(chǔ)方式都是棧存儲(chǔ),引用類型的存儲(chǔ)方式都是堆存儲(chǔ)棧和隊(duì)列的區(qū)別?
棧的插入和刪除操作都是在一端進(jìn)行的锐膜,而隊(duì)列的操作卻是在兩端進(jìn)行的聋迎。
隊(duì)列先進(jìn)先出,棧先進(jìn)后出枣耀。
棧只允許在表尾一端進(jìn)行插入和刪除霉晕,而隊(duì)列只允許在表尾一端進(jìn)行插入,在表頭一端進(jìn)行刪除對(duì)閉包的理解
使用閉包主要是為了設(shè)計(jì)私有的方法和變量捞奕。閉包的優(yōu)點(diǎn)是可以避免全局變量的污染牺堰,缺點(diǎn)是閉包會(huì)常駐內(nèi)存,會(huì)增大內(nèi)存使用量颅围,使用不當(dāng)很容易造成內(nèi)存泄露伟葫。在js中,函數(shù)即閉包院促,只有函數(shù)才會(huì)產(chǎn)生作用域的概念
閉包有三個(gè)特性:
1.函數(shù)嵌套函數(shù)
2.函數(shù)內(nèi)部可以引用外部的參數(shù)和變量
3.參數(shù)和變量不會(huì)被垃圾回收機(jī)制回收跨域的解決方案
- jsonp 只能解決get跨域
原理:動(dòng)態(tài)創(chuàng)建一個(gè)script標(biāo)簽筏养。利用script標(biāo)簽的src屬性不受同源策略限制斧抱。因?yàn)樗械膕rc屬性和href屬性都不受同源策略限制〗ト埽可以請(qǐng)求第三方服務(wù)器數(shù)據(jù)內(nèi)容辉浦。
步驟:
去創(chuàng)建一個(gè)script標(biāo)簽
script的src屬性設(shè)置接口地址
接口參數(shù),必須要帶一個(gè)自定義函數(shù)名 要不然后臺(tái)無(wú)法返回?cái)?shù)據(jù)。
通過(guò)定義函數(shù)名去接收后臺(tái)返回?cái)?shù)據(jù)
//去創(chuàng)建一個(gè)script標(biāo)簽
var script = document.createElement("script");
//script的src屬性設(shè)置接口地址 并帶一個(gè)callback回調(diào)函數(shù)名稱
script.src = "http://127.0.0.1:8888/index.php?callback=jsonpCallback";
//插入到頁(yè)面
document.head.appendChild(script);
//通過(guò)定義函數(shù)名去接收后臺(tái)返回?cái)?shù)據(jù)
function jsonpCallback(data){
//注意 jsonp返回的數(shù)據(jù)是json對(duì)象可以直接使用
//ajax 取得數(shù)據(jù)是json字符串需要轉(zhuǎn)換成json對(duì)象才可以使用茎辐。
}
CORS:跨域資源共享
原理:服務(wù)器設(shè)置Access-Control-Allow-OriginHTTP
響應(yīng)頭之后宪郊,瀏覽器將會(huì)允許跨域請(qǐng)求
限制:瀏覽器需要支持HTML5,可以支持POST拖陆,PUT等方法兼容ie9以上
需要后臺(tái)設(shè)置
Access-Control-Allow-Origin: * //允許所有域名訪問(wèn)弛槐,或者 Access-Control-Allow-Origin: http://a.com //只允許所有域名訪問(wèn)
設(shè)置 document.domain
原理:相同主域名不同子域名下的頁(yè)面,可以設(shè)置document.domain
讓它們同域
限制:同域document提供的是頁(yè)面間的互操作依啰,需要載入iframe頁(yè)面
// URL http://a.com/foo
var ifr = document.createElement('iframe');
ifr.src = 'http://b.a.com/bar';
ifr.onload = function(){
var ifrdoc = ifr.contentDocument || ifr.contentWindow.document;
ifrdoc.getElementsById("foo").innerHTML);
};
ifr.style.display = 'none';
document.body.appendChild(ifr);
- 用Apache做轉(zhuǎn)發(fā)(逆向代理)乎串,讓跨域變成同域
16.原型鏈
每個(gè)構(gòu)造函數(shù)(constructor)都有一個(gè)原型對(duì)象(prototype)原型對(duì)象都包含一個(gè)指向構(gòu)造函數(shù)的指針,而實(shí)例(instance)都包含一個(gè)指向原型對(duì)象的內(nèi)部指針
如果試圖引用對(duì)象(實(shí)例instance)的某個(gè)屬性速警,會(huì)首先在對(duì)象內(nèi)部尋找該屬性叹誉,直至找不到然后在該對(duì)象的原型(instance.prototype)里去找這個(gè)屬性
二、vue面試題
-
router 的區(qū)別
- router為VueRouter的實(shí)例坏瞄,相當(dāng)于一個(gè)全局的路由器對(duì)象桂对,里面含有很多屬性和子對(duì)象甩卓,例如history對(duì)象鸠匀,經(jīng)常用的跳轉(zhuǎn)鏈接就可以用this.$router.push,和router-link跳轉(zhuǎn)一樣逾柿。
- route相當(dāng)于當(dāng)前正在跳轉(zhuǎn)的路由對(duì)象缀棍。可以從里面獲取name,path,params,query等机错。
- Vue的雙向數(shù)據(jù)綁定原理是什么爬范?
vue.js 是采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式,通過(guò)Object.defineProperty()
來(lái)劫持各個(gè)屬性的setter弱匪,getter青瀑,在數(shù)據(jù)變動(dòng)時(shí)發(fā)布消息給訂閱者,觸發(fā)相應(yīng)的監(jiān)聽(tīng)回調(diào)萧诫。 - <keep-alive></keep-alive>的作用是什么?
<keep-alive></keep-alive> 包裹動(dòng)態(tài)組件時(shí)斥难,會(huì)緩存不活動(dòng)的組件實(shí)例,主要用于保留組件狀態(tài)或避免重新渲染帘饶。