前端面試題

HTML相關(guān)

1、XHTML和HTML有什么區(qū)別

HTML是一種基本的WEB網(wǎng)頁實(shí)際語言,XHTML是一種基于XML的置標(biāo)語言

最主要的不同:

    1. XHTML 元素必須被正確的嵌套;
    1. XHTML 元素必須被關(guān)閉;
    1. XHTML 標(biāo)簽名必須用小寫字母;
    1. XHTML 文檔必須擁有根元素。

2、什么是語義化的HTML?

    1. 直觀的認(rèn)識(shí)標(biāo)簽,對(duì)于搜索引擎的抓取有好處,用正確的標(biāo)簽做正確的事。HTML語義化就是讓頁面的內(nèi)容結(jié)構(gòu)化,便于對(duì)瀏覽器、搜索引擎解析;
    1. 在沒有css樣式加持的情況下也以一種文檔格式顯示,并且是容易閱讀的。搜索引擎的爬蟲依賴于標(biāo)記來確定上下文和各個(gè)關(guān)鍵字的權(quán)重,利于SEO。
    1. 使閱讀源代碼的人對(duì)網(wǎng)站更容易將網(wǎng)站分塊,便于閱讀維護(hù)理解。

3、常見的瀏覽器內(nèi)核有哪些?

    1. Trident內(nèi)核 IE、360、搜狗等
    1. Gecko內(nèi)核 Netscape6及以上版本、Firefox
    1. Presto內(nèi)核 Opera7及以上
    1. Webkit Safari、Chrome等

4、H5有哪些新特性?移除了哪些元素?如何處理HTML5新標(biāo)簽的瀏覽器兼容問題?

新特性

    1. canvas繪圖;
    1. 本地離線存儲(chǔ)localStorage長期存儲(chǔ)數(shù)據(jù),瀏覽器關(guān)閉后數(shù)據(jù)不丟失;
    1. sessionStorage數(shù)據(jù)在瀏覽器關(guān)閉后會(huì)自動(dòng)刪除;
    1. 用于媒體回放的video和audio;
    1. 語義化更好的內(nèi)容標(biāo)簽如article、footer、header、nav、setion;
    1. 表單控件 calendar、date、time、email、url、search;
    1. 新的技術(shù) web worker、web socket、geolocation。

移除元素

    1. 純表現(xiàn)元素 font、big、center、u、tt、s;
    1. 對(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中的常見單位?

    1. px: 絕對(duì)單位,頁面按精確像素展示;
    1. em: 相對(duì)單位,基準(zhǔn)點(diǎn)為父節(jié)點(diǎn)字體的大小,如果自身定義了font-size按自身來計(jì)算,整個(gè)頁面內(nèi)1em不是一個(gè)固定的值;
    1. rem: 相對(duì)單位,可理解為“root em”,相當(dāng)于根節(jié)點(diǎn)html的字體大小來計(jì)算。
    1. vm: viewpoint width,視窗寬度,1vm等于視窗寬度的1%;
    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ī)則

    1. 所有的引用類型(數(shù)組、對(duì)象、函數(shù)),都具有對(duì)象特性,即可自由擴(kuò)展屬性(除了null除外)
    1. 所有的引用類型(數(shù)組、對(duì)象、函數(shù)),都有一個(gè) __proto__(隱式原型)屬性,屬性值是一個(gè)普通的對(duì)象;
    1. 所有的函數(shù),都有一個(gè)prototype(顯式原型)屬性,屬性值也是一個(gè)普通的對(duì)象;
    1. 所有的引用類型(數(shù)組、對(duì)象、函數(shù)),__proto__ 屬性值指向它的構(gòu)造函數(shù)的prototype屬性值;
    1. 當(dāng)試圖得到一個(gè)對(duì)象的某個(gè)屬性時(shí),如果這個(gè)對(duì)象本身沒有這個(gè)屬性,那么會(huì)去它的__proto__(即它的構(gòu)造函數(shù)的prototype)中尋找。

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í)。

閉包作用

    1. 使用閉包可以訪問函數(shù)中的變量;
    1. 可以將變量長期保存在內(nèi)存中,生命周期比較長。

閉包使用場景

    1. 函數(shù)作為返回值
    1. 函數(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)境

    1. 在全局作用域下直接調(diào)用函數(shù),this 指向 window(普通執(zhí)行);
    1. 對(duì)象函數(shù)調(diào)用,哪個(gè)函數(shù)調(diào)用就指向哪個(gè)對(duì)象(對(duì)象屬性執(zhí)行);
    1. 使用 new 實(shí)例化對(duì)象,在構(gòu)造函數(shù)中 this 指向?qū)嵗瘜?duì)象(構(gòu)造函數(shù)執(zhí)行);
    1. 使用 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。

    1. 同步會(huì)阻塞代碼執(zhí)行,而異步不會(huì)
    1. alert是同步,setTimeOut是異步

何時(shí)需要異步?

    1. 在可能發(fā)生等待的情況
    1. 等待過程中不能像alert一樣阻塞程序運(yùn)行

因此,所有的“等待的情況”都需要異步

前端使用異步的場景?

    1. 定時(shí)任務(wù):setTimeOut、setInterval
    1. 網(wǎng)絡(luò)請(qǐng)求:ajax請(qǐng)求、動(dòng)態(tài)img加載
    1. 事件綁定

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操作符干了什么?

    1. 創(chuàng)建一個(gè)空對(duì)象 var obj = new Object();
    1. 設(shè)置原型鏈obj.__proto__ = Function.prototype;
    1. 讓 Function 中的 this 指向 obj,并執(zhí)行 Function 的函數(shù)體 var result = Function.call(obj);
    1. 判斷 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ū)別?

    1. 箭頭函數(shù)是匿名函數(shù),不能作為構(gòu)造函數(shù),不能使用 new;
    1. 箭頭函數(shù)不綁定 arguments,取而代之用rest參數(shù)(...)解決;
    1. 箭頭函數(shù)不綁定 this,會(huì)捕獲其所在的上下文的 this 值,作為自己的 this 值;
    1. 箭頭函數(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版本
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在線閱讀 http://interview.poetries.top[http://interview.poetr...
    前端進(jìn)階之旅閱讀 115,552評(píng)論 24 450
  • <a name='html'>HTML</a> Doctype作用?標(biāo)準(zhǔn)模式與兼容模式各有什么區(qū)別? (1)、<...
    clark124閱讀 3,822評(píng)論 1 19
  • 1.一些開放性題目 1.自我介紹:除了基本個(gè)人信息以外,面試官更想聽的是你與眾不同的地方和你的優(yōu)勢(shì)。 2.項(xiàng)目介紹...
    55lover閱讀 705評(píng)論 0 6
  • 請(qǐng)參看我github中的wiki,不定期更新。https://github.com/ivonzhang/Front...
    zhangivon閱讀 7,762評(píng)論 2 19
  • 我是 從南方而來的 紫色暴雨 紅色的雨點(diǎn) 灑在你藍(lán)色的嘆息里 滴落在 你新買的 灰色鞋子上
    草堂秋客閱讀 426評(píng)論 0 3

友情鏈接更多精彩內(nèi)容