HTML相關(guān)
1、XHTML和HTML有什么區(qū)別
HTML是一種基本的WEB網(wǎng)頁實(shí)際語言,XHTML是一種基于XML的置標(biāo)語言
最主要的不同:
- XHTML 元素必須被正確的嵌套;
- XHTML 元素必須被關(guān)閉;
- XHTML 標(biāo)簽名必須用小寫字母;
- XHTML 文檔必須擁有根元素。
2、什么是語義化的HTML?
- 直觀的認(rèn)識(shí)標(biāo)簽,對(duì)于搜索引擎的抓取有好處,用正確的標(biāo)簽做正確的事。HTML語義化就是讓頁面的內(nèi)容結(jié)構(gòu)化,便于對(duì)瀏覽器、搜索引擎解析;
- 在沒有css樣式加持的情況下也以一種文檔格式顯示,并且是容易閱讀的。搜索引擎的爬蟲依賴于標(biāo)記來確定上下文和各個(gè)關(guān)鍵字的權(quán)重,利于SEO。
- 使閱讀源代碼的人對(duì)網(wǎng)站更容易將網(wǎng)站分塊,便于閱讀維護(hù)理解。
3、常見的瀏覽器內(nèi)核有哪些?
- Trident內(nèi)核 IE、360、搜狗等
- Gecko內(nèi)核 Netscape6及以上版本、Firefox
- Presto內(nèi)核 Opera7及以上
- Webkit Safari、Chrome等
4、H5有哪些新特性?移除了哪些元素?如何處理HTML5新標(biāo)簽的瀏覽器兼容問題?
新特性
- canvas繪圖;
- 本地離線存儲(chǔ)localStorage長期存儲(chǔ)數(shù)據(jù),瀏覽器關(guān)閉后數(shù)據(jù)不丟失;
- sessionStorage數(shù)據(jù)在瀏覽器關(guān)閉后會(huì)自動(dòng)刪除;
- 用于媒體回放的video和audio;
- 語義化更好的內(nèi)容標(biāo)簽如article、footer、header、nav、setion;
- 表單控件 calendar、date、time、email、url、search;
- 新的技術(shù) web worker、web socket、geolocation。
移除元素
- 純表現(xiàn)元素 font、big、center、u、tt、s;
- 對(duì)可用性產(chǎn)生負(fù)面影響的元素:frame、frameset、noframes
兼容
IE8/IE7/IE6支持通過document.createElement方法產(chǎn)生的標(biāo)簽,可以利用這一特性讓這些瀏覽器支持HTML5新標(biāo)簽。
5、如何實(shí)現(xiàn)瀏覽器內(nèi)多個(gè)標(biāo)簽頁之間的通信?
調(diào)用 localStroage、cookie 等本地存儲(chǔ)方式
6、HTML5為什么只需要寫!DOCTYPE HTML?
HTML5 不基于 SGML,因此不需要對(duì)DTD進(jìn)行引用,但是需要doctype來規(guī)范瀏覽器的行為(讓瀏覽器按照他們應(yīng)該的方式來運(yùn)行);而HTML4.0基于SGML,所以需要對(duì)DTD進(jìn)行引用,才能告知瀏覽器文檔所使用的文檔類型。
7、Doctype作用?標(biāo)準(zhǔn)模式與兼容模式各有什么區(qū)別?
!DOCTYPE聲明位于HTML文檔中的第一行,處于html標(biāo)簽之前。告知瀏覽器的解析器用什么文檔標(biāo)準(zhǔn)解析這個(gè)文檔。DOCTYPE不存在或格式不正確會(huì)導(dǎo)致文檔以兼容模式呈現(xiàn)。
標(biāo)準(zhǔn)模式的排版和JS運(yùn)作模式都是以該瀏覽器支持的最高標(biāo)準(zhǔn)運(yùn)行。在兼容模式中,頁面以寬松的向后兼容的方式顯示,模擬老式瀏覽器的行為以防止站點(diǎn)無法工作。
8、label的作用是什么?怎么用?
label標(biāo)簽是用來定義表單控制間的關(guān)系,當(dāng)用戶選擇該標(biāo)簽時(shí),瀏覽器會(huì)自動(dòng)將焦點(diǎn)轉(zhuǎn)到和標(biāo)簽相關(guān)的表單控件上。
用法:
<label for = "Name">Number:</label>
<input type="text" name="Name" id="Name" />
or
<label>Data:<input type="text" name="B" /><label>
CSS相關(guān)
1、如何居中div?如何居中一個(gè)浮動(dòng)元素?
//居中div
margin: 0 auto
//居中浮動(dòng)元素
float:left;
position:relative;
left:50%;
//居中絕對(duì)定位div
position:absolute;
top: 50%;
left: 50%;
margin:-100px 0px 0px -100
2、經(jīng)常遇到的瀏覽器兼容性有哪些?簡述原因和解決辦法?
1)不同瀏覽器的標(biāo)簽,默認(rèn)的margin和padding不同
解決方案:加一個(gè)全局的*{margin:0;padding:0;}來統(tǒng)一。
2)IE6雙邊距bug:塊屬性標(biāo)簽float后,又有橫行的margin情況下,在ie6顯示margin比設(shè)置的大。
解決方案:在float的標(biāo)簽樣式控制中加入 display:inline;將其轉(zhuǎn)化為行內(nèi)屬性。
3)在IE6,IE7中元素高度超出自己設(shè)置高度。
原因:IE8以前的瀏覽器中會(huì)給元素設(shè)置默認(rèn)的行高的高度導(dǎo)致的。
解決方案:加上overflow:hidden或設(shè)置line-height為更小的高度。
4)min-height在IE6下不起作用
解決方案:添加 height:auto !important;height:xxpx;其中xx就是min-height設(shè)置的值。
5)a(有href屬性)標(biāo)簽嵌套下的img標(biāo)簽,在IE下會(huì)帶有邊框
解決方案:加上a img{border:none;}樣式。
6)IE6下border:none無效
解決方案:用:border:0或border:0 none;或border:none:border-color:transparent;,推薦用第三種方案。
3、CSS3的新特性
- 選擇器(E:last-child)
- @Font-face
- 圓角
- 多列布局
- 陰影效果
- 彈性盒子
- 特效
- 漸變效果
4、CSS優(yōu)化、提高性能的方法有哪些?
- 加載性能,不要用import、壓縮等,減少文件體積,減少阻塞加載,提高并發(fā)
- 選擇器性能 建議使用ID,類選擇器,避免屬性,后代選擇器,通用選擇器。組合選擇器,優(yōu)化最右邊的關(guān)鍵選擇器。
- 渲染性能 是不是大量使用了 text-shadow?是不是開了字體抗鋸齒?CSS 動(dòng)畫怎么實(shí)現(xiàn)的?合理利用 GPU 加速了嗎?
- 可維護(hù)性能 命名合理嗎?結(jié)構(gòu)層次設(shè)計(jì)是否足夠健壯?對(duì)樣式進(jìn)行抽象復(fù)用了嗎?
5、簡要說說CSS的元素分類?
- 塊級(jí)元素:div、h1、form、ul、li、p
- 行內(nèi)元素:span、a、label、input、img
- CSS盒模型:內(nèi)容、border、margin、padding
6、CSS清除浮動(dòng)的幾種方法
- 父級(jí) div 定義 height;
- 父級(jí) div 定義 display:table;
- 結(jié)尾處使用帶 clear 屬性的空 div;
- 使用 CSS 的 overflow 屬性(hidden、auto);
- 使用 CSS的 :after 偽元素。
7、display有哪些值?說明他們的作用。
- block 塊類型。默認(rèn)寬度為父元素寬度,可設(shè)置寬高,換行顯示。
- none 缺省值。象行內(nèi)元素類型一樣顯示。
- inline 行內(nèi)元素類型。默認(rèn)寬度為內(nèi)容寬度,不可設(shè)置寬高,同行顯示。
- inline-block 默認(rèn)寬度為內(nèi)容寬度,可以設(shè)置寬高,同行顯示。
- list-item 象塊類型元素一樣顯示,并添加樣式列表標(biāo)記。
- table 此元素會(huì)作為塊級(jí)表格來顯示。
- inherit 規(guī)定應(yīng)該從父元素繼承 display 屬性的值。
8、position的值, relative和absolute分別是相對(duì)于誰進(jìn)行定位的?
- absolute 生成絕對(duì)定位的元素, 相對(duì)于最近一級(jí)的 定位不是 static 的父元素來進(jìn)行定位。
- fixed(老IE不支持)生成絕對(duì)定位的元素,通常相對(duì)于瀏覽器窗口或 frame 進(jìn)行定位。
- relative 生成相對(duì)定位的元素,相對(duì)于其在普通流中的位置進(jìn)行定位。
- static 默認(rèn)值。沒有定位,元素出現(xiàn)在正常的流中
- sticky 生成粘性定位的元素,容器的位置根據(jù)正常文檔流計(jì)算得出
9、CSS引入的方式有哪些? link和@import的區(qū)別是?
內(nèi)聯(lián) 內(nèi)嵌 外鏈 導(dǎo)入
區(qū)別:同時(shí)加載
前者無兼容性,后者CSS2.1以下瀏覽器不支持
Link 支持使用javascript改變樣式,后者不可
10、CSS選擇器 ~ 和 + 有什么區(qū)別?
~ 匹配所有兄弟元素,+ 匹配緊挨著的兄弟元素。
另外:
>匹配所有子元素,(空格)匹配所有后代元素。
11、CSS中的常見單位?
- px: 絕對(duì)單位,頁面按精確像素展示;
- em: 相對(duì)單位,基準(zhǔn)點(diǎn)為父節(jié)點(diǎn)字體的大小,如果自身定義了font-size按自身來計(jì)算,整個(gè)頁面內(nèi)1em不是一個(gè)固定的值;
- rem: 相對(duì)單位,可理解為“root em”,相當(dāng)于根節(jié)點(diǎn)html的字體大小來計(jì)算。
- vm: viewpoint width,視窗寬度,1vm等于視窗寬度的1%;
- vh: viewpoint height,視窗高度,1vh等于視窗高度的1%。
JS相關(guān)
1、談一談JavaScript作用域鏈
當(dāng)執(zhí)行一段 JavaScript 代碼(全局代碼或函數(shù))時(shí),JavaScript 引擎會(huì)為其創(chuàng)建一個(gè)作用域(又稱為執(zhí)行上下文),在頁面加載后會(huì)首先創(chuàng)建一個(gè)全局作用域,然后每執(zhí)行一個(gè)函數(shù),會(huì)建立一個(gè)對(duì)應(yīng)的作用域,從而形成一條作用域鏈。每個(gè)作用域都有一條對(duì)應(yīng)的作用域鏈,鏈頭是全局作用域,鏈尾是當(dāng)前函數(shù)作用域。
作用域鏈的作用是用于解析標(biāo)識(shí)符,當(dāng)函數(shù)被創(chuàng)建時(shí)(不是被執(zhí)行),會(huì)將this、arguments、命名參數(shù)和該函數(shù)中所有局部變量添加到當(dāng)前作用域中。當(dāng)JavaScript需要查找變量x的時(shí)候(這個(gè)過程被稱為解析),它首先會(huì)從作用域鏈中的鏈尾(也就是當(dāng)前作用域)進(jìn)行查找是否有x屬性,如果沒有找到就順著作用域鏈繼續(xù)查找,直到查找到鏈頭(也就是全局作用域鏈),仍未找到該變量的話,就認(rèn)為這段代碼的作用域鏈上不存在x變量,并拋出一個(gè)引用錯(cuò)誤的異常。
2、原型是什么?原型鏈?zhǔn)鞘裁矗?/h2>
JavaScript中的每個(gè)對(duì)象都有一個(gè)prototype屬性,我們稱之為原型,而原型的值也是一個(gè)對(duì)象,因此它也有自己的原型,這樣就串聯(lián)起來了一條原型鏈,原型鏈的鏈頭是object,它的prototype比較特殊,值為null。
原型鏈的作用是用于對(duì)象繼承,函數(shù)A的原型屬性(prototype property)是一個(gè)對(duì)象,當(dāng)這個(gè)函數(shù)被用作構(gòu)造函數(shù)來創(chuàng)建實(shí)例時(shí),該函數(shù)的原型將被作為原型賦值給所有實(shí)例對(duì)象,比如我們創(chuàng)建一個(gè)數(shù)組,數(shù)組的方法便從數(shù)組的原型上繼承而來。
原型五項(xiàng)規(guī)則
- 所有的引用類型(數(shù)組、對(duì)象、函數(shù)),都具有對(duì)象特性,即可自由擴(kuò)展屬性(除了null除外)
- 所有的引用類型(數(shù)組、對(duì)象、函數(shù)),都有一個(gè)
__proto__(隱式原型)屬性,屬性值是一個(gè)普通的對(duì)象;
- 所有的引用類型(數(shù)組、對(duì)象、函數(shù)),都有一個(gè)
- 所有的函數(shù),都有一個(gè)prototype(顯式原型)屬性,屬性值也是一個(gè)普通的對(duì)象;
- 所有的引用類型(數(shù)組、對(duì)象、函數(shù)),
__proto__屬性值指向它的構(gòu)造函數(shù)的prototype屬性值;
- 所有的引用類型(數(shù)組、對(duì)象、函數(shù)),
- 當(dāng)試圖得到一個(gè)對(duì)象的某個(gè)屬性時(shí),如果這個(gè)對(duì)象本身沒有這個(gè)屬性,那么會(huì)去它的
__proto__(即它的構(gòu)造函數(shù)的prototype)中尋找。
- 當(dāng)試圖得到一個(gè)對(duì)象的某個(gè)屬性時(shí),如果這個(gè)對(duì)象本身沒有這個(gè)屬性,那么會(huì)去它的
3、構(gòu)造函數(shù),原型對(duì)象,實(shí)例對(duì)象三者之間的關(guān)系
每創(chuàng)建一個(gè)函數(shù),該函數(shù)都會(huì)自動(dòng)帶有一個(gè)prototype屬性。該屬性是一個(gè)指針,指向一個(gè)對(duì)象,該對(duì)象稱之為原型對(duì)象。
原型對(duì)象上默認(rèn)有一個(gè)屬性constructor,該屬性也有一個(gè)指針,指向其關(guān)聯(lián)的構(gòu)造函數(shù)。
通過調(diào)用構(gòu)造函數(shù)產(chǎn)生的實(shí)例對(duì)象,都擁有一個(gè)內(nèi)部屬性,指向了原型對(duì)象。其實(shí)例對(duì)象能夠訪問原型對(duì)象上的所有對(duì)象和方法。
總結(jié):三者的關(guān)系是,每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象,原型對(duì)象上包含著一個(gè)指向構(gòu)造函數(shù)的指針,而實(shí)例都包含著一個(gè)指向原型對(duì)象的內(nèi)部指針。通俗的講,實(shí)例可以通過內(nèi)部指針訪問到原型對(duì)象,原型對(duì)象可以通過constructor找到構(gòu)造函數(shù)。
4、什么是閉包?閉包的作用?
閉包就是函數(shù)中的函數(shù),里面的函數(shù)可以訪問外面函數(shù)的變量,外面的變量是這個(gè)內(nèi)部函數(shù)的一部分。
閉包就是函數(shù)能夠記住并訪問它的詞法作用域,即使當(dāng)這個(gè)函數(shù)在它的詞法作用域之外執(zhí)行時(shí)。
閉包作用
- 使用閉包可以訪問函數(shù)中的變量;
- 可以將變量長期保存在內(nèi)存中,生命周期比較長。
閉包使用場景
- 函數(shù)作為返回值
- 函數(shù)作為參數(shù)傳遞
閉包不能濫用,否則會(huì)導(dǎo)致內(nèi)存泄漏,影響網(wǎng)頁的性能。閉包使用完成后,要立即釋放資源,將引用變量指向 null 。
4、JSON是什么
JSON(JavaScript Object Notation)是一種輕量級(jí)的數(shù)據(jù)交換格式。它是基于 JavaScript 的一個(gè)子集。數(shù)據(jù)格式簡單,易于讀寫,占用寬帶小。是前后臺(tái)交互最常見的一種數(shù)據(jù)格式。JSON也只不過就是一個(gè)js對(duì)象而已。
常用方法
JSON.stringify({name: 'xiaoxin', age: 20}) //對(duì)象轉(zhuǎn)為字符串
JSON.parse('{name: \'xiaoxin\', age: 20}') //字符串轉(zhuǎn)為對(duì)象
5、JavaScript有幾種類型的值?區(qū)別是什么?
兩大類
- 棧: 原始數(shù)據(jù)類型(Undefined、Null、Boolean、Number、String、Symbol);
- 堆: 引用數(shù)據(jù)類型(Object、Array、Function)
區(qū)別
原始數(shù)據(jù)類型 直接存儲(chǔ)在棧(stack)中的簡單數(shù)據(jù)段,占用空間小、大小固定,屬于被頻繁使用數(shù)據(jù)。
引用數(shù)據(jù)類型 存儲(chǔ)在堆(heap)中的對(duì)象,占用空間大、大小不固定,如果存儲(chǔ)在棧中,將會(huì)影響程序運(yùn)行的性能;引用數(shù)據(jù)類型在棧中存儲(chǔ)了指針,該指針指向堆中該實(shí)體的起始地址。當(dāng)解釋器尋找引用值時(shí),首先會(huì)檢索其在棧中的地址,然后從堆中獲取實(shí)體。
6、談?wù)剬?duì)this的理解?
this 表示當(dāng)前對(duì)象,this 的指向是根據(jù)調(diào)用的上下文來決定的,默認(rèn)指向 window 對(duì)象,指向 window 對(duì)象時(shí)可以省略不寫,例如
this.alert() === window.this.alert() === alert()
,調(diào)用的上下文環(huán)境包括全局和局部。
執(zhí)行時(shí)才能確認(rèn)值,定義時(shí)無法確認(rèn)
全局環(huán)境 就是在<script></script>中,這里的 this 始終指向的是 window 對(duì)象;
局部環(huán)境
- 在全局作用域下直接調(diào)用函數(shù),this 指向 window(普通執(zhí)行);
- 對(duì)象函數(shù)調(diào)用,哪個(gè)函數(shù)調(diào)用就指向哪個(gè)對(duì)象(對(duì)象屬性執(zhí)行);
- 使用 new 實(shí)例化對(duì)象,在構(gòu)造函數(shù)中 this 指向?qū)嵗瘜?duì)象(構(gòu)造函數(shù)執(zhí)行);
- 使用 call 或 apply 可以改變 this 的指向。
7、同步和異步的區(qū)別?
同步是一種線性執(zhí)行的方式,執(zhí)行的流程不能跨越。一般用于流程性比較強(qiáng)的程序,比如用戶登錄;
異步是一種并行處理的方式,不必等待一個(gè)程序執(zhí)行完,就可以執(zhí)行其它任務(wù)。在程序中異步處理的結(jié)果通常使用回調(diào)函數(shù)來處理結(jié)果。在 JavaScript 中實(shí)現(xiàn)異步的方式一般是 Ajax 和 H5 新增的 Web Worker。
- 同步會(huì)阻塞代碼執(zhí)行,而異步不會(huì)
- alert是同步,setTimeOut是異步
何時(shí)需要異步?
- 在可能發(fā)生等待的情況
- 等待過程中不能像alert一樣阻塞程序運(yùn)行
因此,所有的“等待的情況”都需要異步
前端使用異步的場景?
- 定時(shí)任務(wù):setTimeOut、setInterval
- 網(wǎng)絡(luò)請(qǐng)求:ajax請(qǐng)求、動(dòng)態(tài)img加載
- 事件綁定
8、call和apply的區(qū)別?
相同點(diǎn) 兩個(gè)方法產(chǎn)生的作用是一樣的,都用來改變當(dāng)前函數(shù)調(diào)用的對(duì)象;
不同點(diǎn) 調(diào)用的參數(shù)不同,
foo.call(this, arg1, arg2, arg3) == foo.apply(this, args) == this.foo(arg1, arg2, arg3)
9、eval是做什么的?
把字符串參數(shù)解析成JS代碼運(yùn)行,并返回執(zhí)行的結(jié)果。
10、new操作符干了什么?
- 創(chuàng)建一個(gè)空對(duì)象
var obj = new Object();
- 創(chuàng)建一個(gè)空對(duì)象
- 設(shè)置原型鏈
obj.__proto__ = Function.prototype;
- 設(shè)置原型鏈
- 讓 Function 中的 this 指向 obj,并執(zhí)行 Function 的函數(shù)體
var result = Function.call(obj);
- 讓 Function 中的 this 指向 obj,并執(zhí)行 Function 的函數(shù)體
- 判斷 Function 的返回值類型,如果是值類型,返回 obj,如果是引用類型,就返回引用類型的對(duì)象。
11、造成JS內(nèi)存泄漏的情況?
- 全局變量
- 閉包
- DOM被清空時(shí),事件未被清除
- 子元素存在引用
12、寫出下列結(jié)果?
console.log(null == NaN); //false
console.log(null == undefined); //true
console.log(null == false); //false
console.log(false == ''); //true
console.log(false == 0); //true
console.log(2 + 1 + '3'); //33
console.log('2' + 1 + 3); //213
console.log(Number(undefined)); //NaN
console.log(Number(NaN)); //NaN
console.log(Number(null)); //0
console.log(Number('')); //0
console.log(Number('123')); //123
console.log(isNaN(23)); //false
console.log(isNaN(NaN)); //true
console.log(isNaN(undefined));//true
console.log(isNaN(null)); //false
console.log(typeof NaN); //number
console.log(typeof '123'); //string
console.log(typeof undefined); //undefined
console.log(typeof 123); //number
console.log(typeof null); //object
console.log(typeof []); //object
console.log(typeof Array); //function
console.log(typeof console.log); //function
console.log(NaN == NaN); //false
console.log(undefined == undefined); //true
13、JS綁定事件的方法?
1)在DOM上直接綁定
<input type="button" value="click me" onclick="hello()" />
<script>
function hello(){
alert('hello')
}
</script>
2)在JavaScript代碼中綁定事件
<input type="button" value="click me" id="btn">
<script>
document.getElementById('btn').onclick = function(){
alert('hello');
}
</script>
3)使用事件監(jiān)聽綁定
W3C標(biāo)準(zhǔn)語法:
element.addEventListener(event, function, useCapture)
- event(必選)事件名,支持所有DOM事件;
- function(必選)指定事件觸發(fā)后執(zhí)行的函數(shù);
- useCapture(可選)指定事件是否在捕獲或冒泡階段執(zhí)行。true,捕獲;false,冒泡(default);
<input type="button" value="click me" id="btn">
<script>
document
.getElementById('btn')
.addEventListener('click', function() {
alert('hello);
})
</script>
IE標(biāo)準(zhǔn)語法:
element.attachEvent(event, function)
- event(必須)事件類型,需要加“on”,例如“onClick”
- function(必選)指定事件觸發(fā)后執(zhí)行的函數(shù)
14、JavaScript事件流機(jī)制?
1)冒泡型機(jī)制
事件按照從最特定的事件目標(biāo)到最不特定的事件目標(biāo)(document對(duì)象)的順序觸發(fā)
2)捕獲型機(jī)制
事件從最不精確的對(duì)象(document對(duì)象)開始觸發(fā),然后到最精確。
3)DOM事件流
同時(shí)支持兩種事件模型:捕獲型事件和冒泡型事件,但是捕獲型事件先發(fā)生。兩種事件都會(huì)觸發(fā)DOM中的所有對(duì)象,從document對(duì)象開始,也在document對(duì)象結(jié)束。
事件捕獲機(jī)制:事件從最上一級(jí)標(biāo)簽開始往下查找,直到捕獲到事件目標(biāo);
事件冒泡機(jī)制:事件從事件目標(biāo)開始,往上冒泡直到頁面的最上一級(jí)標(biāo)簽。
事件的傳播是可以阻止的:
- 在W3C中,使用stopPropagation()方法;
- 在IE下設(shè)置cancelBubble = true;
在捕獲的事件中stopPropagation()后,后面的冒泡過程也不會(huì)發(fā)生了
阻止事件的默認(rèn)行為:
- 在W3C中,使用preventDefault()方法;
- 在IE下設(shè)置window.event.returnValue = false
不是所有事件都能冒泡,例如:blur、focus、load、unload等
普通事件和事件綁定的區(qū)別?
普通事件的方法不支持添加多個(gè),最下面的事件會(huì)覆蓋上面的;事件綁定可以添加多個(gè)
15、JavaScript實(shí)現(xiàn)繼承的幾種方式?
//父類
function Animal(name) {
this.name = name || 'Animal';
this.sleep = function () {
console.log(this.name + ' sleep');
};
}
Animal.prototype.eat = function (food) {
console.log(this.name + ' eating ' + food)
};
//原型鏈繼承
function Cat() {
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';
//構(gòu)造繼承(不能繼承原型方法)
function Cat(name) {
Animal.call(this);
this.name = name || 'Tom';
}
//實(shí)例繼承
function Cat(name) {
const instance = new Animal();
instance.name = name || 'Tom';
return instance;
}
//拷貝繼承
function Cat(name) {
const animal = new Animal();
for (let p in animal) {
Cat.prototype[p] = animal[p];
}
Cat.prototype.name = name || 'Tom';
}
16、簡要說明對(duì)模塊化開發(fā)的理解?
所謂模塊化開發(fā)就是封裝細(xì)節(jié),提供使用接口,彼此之間互不影響,每個(gè)模塊都是實(shí)現(xiàn)某一特定的功能。模塊化開發(fā)的基礎(chǔ)就是函數(shù)。
17、Ajax的工作原理?寫一個(gè)Ajax請(qǐng)求?
Ajax的工作原理相當(dāng)于在用戶和服務(wù)器之間加了一個(gè)中間件(Ajax引擎),是用戶操作與瀏覽器響應(yīng)異步化。
const xhr = new XMLHttpRequest();
xhr.open('get', '/api', false);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) { // 0 請(qǐng)求未初始化 1 請(qǐng)求已建立 2 請(qǐng)求已發(fā)送 3 請(qǐng)求處理中 4 響應(yīng)已完成
if (xhr.status == 200) { // 2xx 請(qǐng)求成功 3xx 請(qǐng)求重定向 4xx 客戶端錯(cuò)誤 5xx 服務(wù)端錯(cuò)誤
console.log(xhr.responseText)
}
}
};
xhr.send(null);
18、寫出兩種單例模式的實(shí)現(xiàn)?
//自變量
const singleton = {
attr: 1,
method: function () {
return this.attr;
}
};
//構(gòu)造函數(shù)內(nèi)部判斷
function Construct() {
if(Construct.unique !== undefined){
return Construct.unique;
}
this.name = 'name';
this.age = 24;
Construct.unique = this;
}
19、ES6中Array.isArray的代碼實(shí)現(xiàn)?
Array.isArray = function(obj) {
return Object.prototype.toString.call(obj) == '[object Array]';
}
20、window.onload 和 DOMContentLoaded 區(qū)別
- window.onload 頁面的全部資源加載完才會(huì)執(zhí)行,包括圖片、視頻等
- DOMContentLoaded DOM渲染完即可執(zhí)行,此時(shí)圖片、視頻還沒有加載完
21、隨機(jī)打印1-100間的10個(gè)數(shù)字,去重后取出該10個(gè)數(shù)字之間的最大值和最小值。
function randomMaxMin() {
const numbers = [...new Set([...new Array(10)].reduce(origin => {
origin.push(Math.ceil(Math.random() * 100));
return origin;
}, []))].sort((a, b) => a - b);
return {min: numbers[0], max: numbers[numbers.length - 1]};
}
22、寫一個(gè)長度一致的隨機(jī)數(shù)
let random = Math.random() + '0000000000';
random = random.slice(0, 10);
23、寫一個(gè)能遍歷數(shù)組和對(duì)象的forEach函數(shù)
function forEach(obj, fn) {
if (obj instanceof Array) {
obj.forEach((item, index) => fn(index, item));
} else {
Object.keys(obj).forEach(key => fn(key, obj[key]));
}
}
forEach({name: 'pp', age: 20}, (key, value) => {});
forEach([1,2,3], (index, item) => {});
24、寫一個(gè)閉包的使用場景
function isFirstLoad() {
const _list = [];
return function (id) {
if(_list.indexOf(id) >= 0){
return false;
}else{
_list.push(id);
return true;
}
};
}
const firstLoad = isFirstLoad();
console.log(firstLoad(10)); //true
console.log(firstLoad(10)); //false
console.log(firstLoad(20)); //true
console.log(firstLoad(20)); //false
25、動(dòng)態(tài)創(chuàng)建10個(gè)標(biāo)簽,點(diǎn)擊彈出對(duì)應(yīng)的序號(hào)
for (var i = 0; i < 10; i++) {
(function (i) {
var a = document.createElement('a');
a.innerHTML = 'aaa' + (i + 1) + '</br>';
a.addEventListener('click', function (e) {
e.preventDefault();
alert(i + 1);
});
document.body.appendChild(a);
})(i);
}
最簡單的方式用
let替換var進(jìn)行定義。
26、寫一個(gè)原型繼承的案例
function Elem(id) {
this.elem = document.getElementById(id);
}
Elem.prototype.html = function (val) {
const elem = this.elem;
if(val){
elem.innerHTML = val;
return this;
}else{
return elem.innerHTML;
}
};
Elem.prototype.on = function (type, fun) {
const elem = this.elem;
elem.addEventListener(type, fun);
return this;
};
//exec
const div1 = new Elem('app');
div1.html('<p>Hello</p>').on('click', function () {
alert('hello');
}).html('<p>peter</p>');
27、編寫一個(gè)通用的事件監(jiān)聽函數(shù)?
function bindEvent(elem, type, selector, fn) {
if (fn == null) {
fn = selector;
selector = null;
}
elem.addEventListener(type, function (e) {
if (selector) {
//代理
const target = e.target;
if (target.matches(selector)) {
fn.call(target, e);
}
} else {
//不是代理
fn(e);
}
});
}
const div1 = document.getElementById('div1');
bindEvent(div1, 'click', 'a', function (e) {
e.preventDefault();
console.log(this.innerHTML);
});
const p1 = document.getElementById('p1');
bindEvent(p1, 'click', function () {
console.log(p1.innerHTML);
});
28、js寫一個(gè)冒泡排序算法
//冒泡排序
function bubble() {
const arr = [3, 1, 2, 4];
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
console.log(arr);
}
bubble(); //[1, 2, 3, 4]
29、JS寫一個(gè)選擇排序算法
//選擇算法
function selection() {
const arr = [3, 1, 2, 4];
for (let i = 0; i < arr.length - 1; i++) {
let min = i;
for (let j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[min]) {
min = j;
}
}
[arr[i], arr[min]] = [arr[min], arr[i]];
}
console.log(arr);
}
selection(); //[1, 2, 3, 4]
30、JS寫一個(gè)插入排序算法
//插入排序
function insertion() {
const arr = [3, 1, 2, 4];
for (let i = 1; i < arr.length; i++) {
for (let j = i - 1; j >= 0; j--) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
console.log(arr);
}
insertion(); //[1, 2, 3, 4]
31、寫一個(gè)二分法的函數(shù),返回給定值的索引
//二分法找索引
function dichotomy(arr, val) {
let start = 0, end = arr.length - 1;
while (start < end) {
let middle = end == 1 ? 0 : Math.floor((start + end + 1) / 2);
if (arr[middle] > val) {
end = middle;
} else if (arr[middle] < val) {
start = middle;
} else {
return middle;
}
}
return -1;
}
console.log(dichotomy([2,3,4,5], 3)); //1
32、現(xiàn)有一個(gè)URL字符串“http://www.xxx.com?pn=0”,請(qǐng)寫出刪除其中的pn屬性的js代碼,請(qǐng)盡量實(shí)現(xiàn)完整,考慮全面。
const arr = url.split('?');
const new_url = arr[0] + '?' + arr[1].split('&')
.reduce((origin, item) => {
(item.split('=')[0] != 'pn') && origin.push(item);
return origin;
}, []).join('&');
console.log(new_url); //http://www.xxx.com
33、寫一個(gè)函數(shù),計(jì)算100以內(nèi)的質(zhì)數(shù)(只能被1或本身整除的數(shù))。
const calcPrimeNumbers = sum => (
[...new Array(sum)].reduce((origin, item, index) => {
const [number, arr] = [++index, []];
for (let i = 1; i <= number; i++) {
number % i == 0 && arr.push(i);
}
arr.length == 2 && origin.push(number);
return origin;
}, [])
);
console.log(calcPrimeNumbers(100)); //[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47 ]
34、用 JS 實(shí)現(xiàn)一個(gè)無限累加的函數(shù) add
function add() {
let sum = [...arguments].reduce((a, b) => a + b);
const foo = function () {
sum += [...arguments].reduce((a, b) => a + b);
return foo;
};
foo.toString = () => sum;
return foo;
}
console.log(add(1)(2)(3)(4)); // 10
console.log(add(1,1)(2,2)(3,3)(4,4)); // 20
35、手動(dòng)實(shí)現(xiàn)一個(gè)sleep函數(shù)?
function sleep(time) {
const start = Date.now();
while (true) {
if(Date.now() - time > start)
break;
}
console.log('休息了' + time / 1000 + '秒')
}
sleep(3000); //休息了3秒
36、普通函數(shù)和箭頭函數(shù)的區(qū)別?
- 箭頭函數(shù)是匿名函數(shù),不能作為構(gòu)造函數(shù),不能使用 new;
- 箭頭函數(shù)不綁定 arguments,取而代之用rest參數(shù)(...)解決;
- 箭頭函數(shù)不綁定 this,會(huì)捕獲其所在的上下文的 this 值,作為自己的 this 值;
- 箭頭函數(shù)沒有原型屬性。
37、如何發(fā)送攜帶cookie的跨域請(qǐng)求?
設(shè)置 withCredentials = true;
38、根據(jù)id快速查找對(duì)應(yīng)的元素
const tree = {
id: 'root',
children: [
{ id: 1, children: [] },
{ id: 2, children: [] },
{ id: 3, children: [] },
{
id: 4,
children: [
{ id: 5, children: [] },
]
},
]
};
function find(id, node = tree) {
if (node.id == id) {
return node.children;
}
let target;
node.children.forEach(child => {
if (child.id == id) {
target = child.children;
} else {
find(child.id, child);
}
});
return target;
}
console.log(find(1)); // []
39、實(shí)現(xiàn)對(duì)數(shù)組進(jìn)行亂序
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var sign = 1;
arr.sort((a, b) => {
sign = Math.random() > 0.5 ? 1 : -1;
return (a - b) * sign;
});
console.log(arr);
40、計(jì)算長度為100的數(shù)組前10個(gè)元素之和。
var arr = [...new Array(100)].map((item, i) => i + 1);
var result = arr.slice(0, 10).reduce((pre, current) => pre + current);
console.log(result); // 55
41、手動(dòng)實(shí)現(xiàn)一個(gè)bind函數(shù)
Function.prototype.myBind = function (oThis) {
let args = [...arguments].slice(1);
const context = this;
const bound = function () {
args = [...args, ...arguments];
return context.apply(this instanceof F && oThis ? this : oThis, args);
};
const F = function () {
};
F.prototype = context.prototype;
bound.prototype = new F();
return bound;
};
function read(name, time, book) {
console.log(`${name} is reading ${book} at ${time}`)
}
const tomRead = read.myBind(this, 'Tom', 'morning');
tomRead('三體'); // Tom is reading 三體 at morning
42、手動(dòng)實(shí)現(xiàn)一個(gè)深拷貝
function copy(obj) {
const result = obj instanceof Array ? [] : {};
for (let item in obj) {
if (typeof obj[item] == 'object') {
result[item] = copy(obj[item]);
} else {
result[item] = obj[item];
}
}
return result;
}
6、HTTP狀態(tài)碼分別表示什么?
2xx 成功
- 200 OK,表示從客戶端發(fā)來的請(qǐng)求在服務(wù)器端被正確處理
- 204 No content,表示請(qǐng)求成功,但響應(yīng)報(bào)文不含實(shí)體的主體部分
- 205 Reset Content,表示請(qǐng)求成功,但響應(yīng)報(bào)文不含實(shí)體的主體部分,但是與 204 響應(yīng)不同在于要求請(qǐng)求方重置內(nèi)容
- 206 Partial Content,進(jìn)行范圍請(qǐng)求
3xx 重定向
- 301 moved permanently,永久性重定向,表示資源已被分配了新的 URL
- 302 found,臨時(shí)性重定向,表示資源臨時(shí)被分配了新的 URL
- 303 see other,表示資源存在著另一個(gè) URL,應(yīng)使用 GET 方法獲取資源
- 304 not modified,表示服務(wù)器允許訪問資源,但因發(fā)生請(qǐng)求未滿足條件的情況
- 307 temporary redirect,臨時(shí)重定向,和302含義類似,但是期望客戶端保持請(qǐng)求方法不變向新的地址發(fā)出請(qǐng)求
4xx 客戶端錯(cuò)誤
- 400 bad request,請(qǐng)求報(bào)文存在語法錯(cuò)誤
- 401 unauthorized,表示發(fā)送的請(qǐng)求需要有通過 HTTP 認(rèn)證的認(rèn)證信息
- 403 forbidden,表示對(duì)請(qǐng)求資源的訪問被服務(wù)器拒絕
- 404 not found,表示在服務(wù)器上沒有找到請(qǐng)求的資源
5xx 服務(wù)端錯(cuò)誤
- 500 internal sever error,表示服務(wù)器端在執(zhí)行請(qǐng)求時(shí)發(fā)生了錯(cuò)誤
- 501 Not Implemented,表示服務(wù)器不支持當(dāng)前請(qǐng)求所需要的某個(gè)功能
- 503 service unavailable,表明服務(wù)器暫時(shí)處于超負(fù)載或正在停機(jī)維護(hù),無法處理請(qǐng)求
details
- 100 Continue 初始的請(qǐng)求已經(jīng)接受,客戶應(yīng)當(dāng)繼續(xù)發(fā)送請(qǐng)求的其余部分
- 101 Switching Protocols 服務(wù)器將遵從客戶的請(qǐng)求轉(zhuǎn)換到另外一種協(xié)議
- 200 OK 一切正常,對(duì)GET和POST請(qǐng)求的應(yīng)答文檔跟在后面
- 201 Created 服務(wù)器已經(jīng)創(chuàng)建了文檔,Location頭給出了它的URL。
- 202 Accepted 已經(jīng)接受請(qǐng)求,但處理尚未完成。
- 203 Non-Authoritative Information 文檔已經(jīng)正常地返回,但一些應(yīng)答頭可能不正確,因?yàn)槭褂玫氖俏臋n的拷貝
- 204 No Content 沒有新文檔,瀏覽器應(yīng)該繼續(xù)顯示原來的文檔。如果用戶定期地刷新頁面,而Servlet可以確定用戶文檔足夠新,這個(gè)狀態(tài)代碼是很有用的
- 205 Reset Content 沒有新的內(nèi)容,但瀏覽器應(yīng)該重置它所顯示的內(nèi)容。用來強(qiáng)制瀏覽器清除表單輸入內(nèi)容
- 206 Partial Content 客戶發(fā)送了一個(gè)帶有Range頭的GET請(qǐng)求,服務(wù)器完成了它
- 300 Multiple Choices 客戶請(qǐng)求的文檔可以在多個(gè)位置找到,這些位置已經(jīng)在返回的文檔內(nèi)列出。如果服務(wù)器要提出優(yōu)先選擇,則應(yīng)該在Location應(yīng)答頭指明。
- 301 Moved Permanently 客戶請(qǐng)求的文檔在其他地方,新的URL在Location頭中給出,瀏覽器應(yīng)該自動(dòng)地訪問新的URL。
- 302 Found 類似于301,但新的URL應(yīng)該被視為臨時(shí)性的替代,而不是永久性的。
- 303 See Other 類似于301/302,不同之處在于,如果原來的請(qǐng)求是POST,Location頭指定的重定向目標(biāo)文檔應(yīng)該通過GET提取
- 304 Not Modified 客戶端有緩沖的文檔并發(fā)出了一個(gè)條件性的請(qǐng)求(一般是提供If-Modified-Since頭表示客戶只想比指定日期更新的文檔)。服務(wù)器告訴客戶,原來緩沖的文檔還可以繼續(xù)使用。
- 305 Use Proxy 客戶請(qǐng)求的文檔應(yīng)該通過Location頭所指明的代理服務(wù)器提取
- 307 Temporary Redirect和302(Found)相同。許多瀏覽器會(huì)錯(cuò)誤地響應(yīng)302應(yīng)答進(jìn)行重定向,即使原來的請(qǐng)求是 POST,即使它實(shí)際上只能在POST請(qǐng)求的應(yīng)答是303時(shí)才能重定向。由于這個(gè)原因,HTTP 1.1新增了307,以便更加清除地區(qū)分幾個(gè)狀態(tài)代碼: 當(dāng)出現(xiàn)303應(yīng)答時(shí),瀏覽器可以跟隨重定向的GET和POST請(qǐng)求;如果是307應(yīng)答,則瀏覽器只能跟隨對(duì)GET請(qǐng)求的重定向。
- 400 Bad Request 請(qǐng)求出現(xiàn)語法錯(cuò)誤。
- 401 Unauthorized 客戶試圖未經(jīng)授權(quán)訪問受密碼保護(hù)的頁面。應(yīng)答中會(huì)包含一個(gè)WWW-Authenticate頭,瀏覽器據(jù)此顯示用戶名字/密碼對(duì)話框,然后在填寫合適的Authorization頭后再次發(fā)出請(qǐng)求。
- 403 Forbidden 資源不可用。
- 404 Not Found 無法找到指定位置的資源
- 405 Method Not Allowed 請(qǐng)求方法(GET、POST、HEAD、Delete、PUT、TRACE等)對(duì)指定的資源不適用。
-
406 Not Acceptable
指定的資源已經(jīng)找到,但它的MIME類型和客戶在Accpet頭中所指定的不兼容 -
407 Proxy Authentication Required
類似于401,表示客戶必須先經(jīng)過代理服務(wù)器的授權(quán)。 - 408 Request Timeout 在服務(wù)器許可的等待時(shí)間內(nèi),客戶一直沒有發(fā)出任何請(qǐng)求。客戶可以在以后重復(fù)同一請(qǐng)求。
- 409 Conflict 通常和PUT請(qǐng)求有關(guān)。由于請(qǐng)求和資源的當(dāng)前狀態(tài)相沖突,因此請(qǐng)求不能成功。
- 410 Gone 所請(qǐng)求的文檔已經(jīng)不再可用,而且服務(wù)器不知道應(yīng)該重定向到哪一個(gè)地址。它和404的不同在于,返回407表示文檔永久地離開了指定的位置,而404表示由于未知的原因文檔不可用。
- 411 Length Required 服務(wù)器不能處理請(qǐng)求,除非客戶發(fā)送一個(gè)Content-Length頭。
- 412 Precondition Failed 請(qǐng)求頭中指定的一些前提條件失敗
- 413 Request Entity Too Large 目標(biāo)文檔的大小超過服務(wù)器當(dāng)前愿意處理的大小。如果服務(wù)器認(rèn)為自己能夠稍后再處理該請(qǐng)求,則應(yīng)該提供一個(gè)Retry-After頭
- 414 Request URI Too Long URI太長
- 416 Requested Range Not Satisfiable 服務(wù)器不能滿足客戶在請(qǐng)求中指定的Range頭
- 500 Internal Server Error 服務(wù)器遇到了意料不到的情況,不能完成客戶的請(qǐng)求
- 501 Not Implemented 服務(wù)器不支持實(shí)現(xiàn)請(qǐng)求所需要的功能。例如,客戶發(fā)出了一個(gè)服務(wù)器不支持的PUT請(qǐng)求
- 502 Bad Gateway 服務(wù)器作為網(wǎng)關(guān)或者代理時(shí),為了完成請(qǐng)求訪問下一個(gè)服務(wù)器,但該服務(wù)器返回了非法的應(yīng)答
- 503 Service Unavailable 服務(wù)器由于維護(hù)或者負(fù)載過重未能應(yīng)答。例如,Servlet可能在數(shù)據(jù)庫連接池已滿的情況下返回503。服務(wù)器返回503時(shí)可以提供一個(gè)Retry-After頭
- 504 Gateway Timeout 由作為代理或網(wǎng)關(guān)的服務(wù)器使用,表示不能及時(shí)地從遠(yuǎn)程服務(wù)器獲得應(yīng)答
- 505 HTTP Version Not Supported 服務(wù)器不支持請(qǐng)求中所指明的HTTP版本