前端面試題

HTML相關

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

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

最主要的不同:

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

2、什么是語義化的HTML?

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

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新標簽的瀏覽器兼容問題?

新特性

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

移除元素

    1. 純表現(xiàn)元素 font、big、center、u、tt、s;
    1. 對可用性產(chǎn)生負面影響的元素:frame、frameset、noframes

兼容

IE8/IE7/IE6支持通過document.createElement方法產(chǎn)生的標簽,可以利用這一特性讓這些瀏覽器支持HTML5新標簽。

5、如何實現(xiàn)瀏覽器內(nèi)多個標簽頁之間的通信?

調(diào)用 localStroage、cookie 等本地存儲方式

6、HTML5為什么只需要寫!DOCTYPE HTML?

HTML5 不基于 SGML,因此不需要對DTD進行引用,但是需要doctype來規(guī)范瀏覽器的行為(讓瀏覽器按照他們應該的方式來運行);而HTML4.0基于SGML,所以需要對DTD進行引用,才能告知瀏覽器文檔所使用的文檔類型。

7、Doctype作用?標準模式與兼容模式各有什么區(qū)別?

!DOCTYPE聲明位于HTML文檔中的第一行,處于html標簽之前。告知瀏覽器的解析器用什么文檔標準解析這個文檔。DOCTYPE不存在或格式不正確會導致文檔以兼容模式呈現(xiàn)。

標準模式的排版和JS運作模式都是以該瀏覽器支持的最高標準運行。在兼容模式中,頁面以寬松的向后兼容的方式顯示,模擬老式瀏覽器的行為以防止站點無法工作。

8、label的作用是什么?怎么用?

label標簽是用來定義表單控制間的關系,當用戶選擇該標簽時,瀏覽器會自動將焦點轉(zhuǎn)到和標簽相關的表單控件上。

用法:

<label for = "Name">Number:</label>
<input type="text" name="Name" id="Name" />

or

<label>Data:<input type="text" name="B" /><label>

CSS相關

1、如何居中div?如何居中一個浮動元素?

//居中div
margin: 0 auto

//居中浮動元素
float:left;
position:relative;
left:50%;

//居中絕對定位div
position:absolute; 
top: 50%; 
left: 50%;
margin:-100px 0px 0px -100

2、經(jīng)常遇到的瀏覽器兼容性有哪些?簡述原因和解決辦法?

1)不同瀏覽器的標簽,默認的margin和padding不同

解決方案:加一個全局的*{margin:0;padding:0;}來統(tǒng)一。

2)IE6雙邊距bug:塊屬性標簽float后,又有橫行的margin情況下,在ie6顯示margin比設置的大。

解決方案:在float的標簽樣式控制中加入 display:inline;將其轉(zhuǎn)化為行內(nèi)屬性。

3)在IE6,IE7中元素高度超出自己設置高度。

原因:IE8以前的瀏覽器中會給元素設置默認的行高的高度導致的。

解決方案:加上overflow:hidden或設置line-height為更小的高度。

4)min-height在IE6下不起作用

解決方案:添加 height:auto !important;height:xxpx;其中xx就是min-height設置的值。

5)a(有href屬性)標簽嵌套下的img標簽,在IE下會帶有邊框

解決方案:加上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)化最右邊的關鍵選擇器。
  • 渲染性能 是不是大量使用了 text-shadow?是不是開了字體抗鋸齒?CSS 動畫怎么實現(xiàn)的?合理利用 GPU 加速了嗎?
  • 可維護性能 命名合理嗎?結構層次設計是否足夠健壯?對樣式進行抽象復用了嗎?

5、簡要說說CSS的元素分類?

  • 塊級元素:div、h1、form、ul、li、p
  • 行內(nèi)元素:span、a、label、input、img
  • CSS盒模型:內(nèi)容、border、margin、padding

6、CSS清除浮動的幾種方法

  • 父級 div 定義 height;
  • 父級 div 定義 display:table;
  • 結尾處使用帶 clear 屬性的空 div;
  • 使用 CSS 的 overflow 屬性(hidden、auto);
  • 使用 CSS的 :after 偽元素。

7、display有哪些值?說明他們的作用。

  • block 塊類型。默認寬度為父元素寬度,可設置寬高,換行顯示。
  • none 缺省值。象行內(nèi)元素類型一樣顯示。
  • inline 行內(nèi)元素類型。默認寬度為內(nèi)容寬度,不可設置寬高,同行顯示。
  • inline-block 默認寬度為內(nèi)容寬度,可以設置寬高,同行顯示。
  • list-item 象塊類型元素一樣顯示,并添加樣式列表標記。
  • table 此元素會作為塊級表格來顯示。
  • inherit 規(guī)定應該從父元素繼承 display 屬性的值。

8、position的值, relative和absolute分別是相對于誰進行定位的?

  • absolute 生成絕對定位的元素, 相對于最近一級的 定位不是 static 的父元素來進行定位。
  • fixed(老IE不支持)生成絕對定位的元素,通常相對于瀏覽器窗口或 frame 進行定位。
  • relative 生成相對定位的元素,相對于其在普通流中的位置進行定位。
  • static 默認值。沒有定位,元素出現(xiàn)在正常的流中
  • sticky 生成粘性定位的元素,容器的位置根據(jù)正常文檔流計算得出

9、CSS引入的方式有哪些? link和@import的區(qū)別是?

內(nèi)聯(lián) 內(nèi)嵌 外鏈 導入

區(qū)別:同時加載

前者無兼容性,后者CSS2.1以下瀏覽器不支持
Link 支持使用javascript改變樣式,后者不可

10、CSS選擇器 ~ 和 + 有什么區(qū)別?

~ 匹配所有兄弟元素,+ 匹配緊挨著的兄弟元素。

另外:> 匹配所有子元素,(空格) 匹配所有后代元素。

11、CSS中的常見單位?

    1. px: 絕對單位,頁面按精確像素展示;
    1. em: 相對單位,基準點為父節(jié)點字體的大小,如果自身定義了font-size按自身來計算,整個頁面內(nèi)1em不是一個固定的值;
    1. rem: 相對單位,可理解為“root em”,相當于根節(jié)點html的字體大小來計算。
    1. vm: viewpoint width,視窗寬度,1vm等于視窗寬度的1%;
    1. vh: viewpoint height,視窗高度,1vh等于視窗高度的1%。

JS相關

1、談一談JavaScript作用域鏈

當執(zhí)行一段 JavaScript 代碼(全局代碼或函數(shù))時,JavaScript 引擎會為其創(chuàng)建一個作用域(又稱為執(zhí)行上下文),在頁面加載后會首先創(chuàng)建一個全局作用域,然后每執(zhí)行一個函數(shù),會建立一個對應的作用域,從而形成一條作用域鏈。每個作用域都有一條對應的作用域鏈,鏈頭是全局作用域,鏈尾是當前函數(shù)作用域。

作用域鏈的作用是用于解析標識符,當函數(shù)被創(chuàng)建時(不是被執(zhí)行),會將this、arguments、命名參數(shù)和該函數(shù)中所有局部變量添加到當前作用域中。當JavaScript需要查找變量x的時候(這個過程被稱為解析),它首先會從作用域鏈中的鏈尾(也就是當前作用域)進行查找是否有x屬性,如果沒有找到就順著作用域鏈繼續(xù)查找,直到查找到鏈頭(也就是全局作用域鏈),仍未找到該變量的話,就認為這段代碼的作用域鏈上不存在x變量,并拋出一個引用錯誤的異常。

2、原型是什么?原型鏈是什么?

JavaScript中的每個對象都有一個prototype屬性,我們稱之為原型,而原型的值也是一個對象,因此它也有自己的原型,這樣就串聯(lián)起來了一條原型鏈,原型鏈的鏈頭是object,它的prototype比較特殊,值為null。

原型鏈的作用是用于對象繼承,函數(shù)A的原型屬性(prototype property)是一個對象,當這個函數(shù)被用作構造函數(shù)來創(chuàng)建實例時,該函數(shù)的原型將被作為原型賦值給所有實例對象,比如我們創(chuàng)建一個數(shù)組,數(shù)組的方法便從數(shù)組的原型上繼承而來。

原型五項規(guī)則

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

3、構造函數(shù),原型對象,實例對象三者之間的關系

每創(chuàng)建一個函數(shù),該函數(shù)都會自動帶有一個prototype屬性。該屬性是一個指針,指向一個對象,該對象稱之為原型對象。

原型對象上默認有一個屬性constructor,該屬性也有一個指針,指向其關聯(lián)的構造函數(shù)。

通過調(diào)用構造函數(shù)產(chǎn)生的實例對象,都擁有一個內(nèi)部屬性,指向了原型對象。其實例對象能夠訪問原型對象上的所有對象和方法。

總結:三者的關系是,每個構造函數(shù)都有一個原型對象,原型對象上包含著一個指向構造函數(shù)的指針,而實例都包含著一個指向原型對象的內(nèi)部指針。通俗的講,實例可以通過內(nèi)部指針訪問到原型對象,原型對象可以通過constructor找到構造函數(shù)。

4、什么是閉包?閉包的作用?

閉包就是函數(shù)中的函數(shù),里面的函數(shù)可以訪問外面函數(shù)的變量,外面的變量是這個內(nèi)部函數(shù)的一部分。

閉包就是函數(shù)能夠記住并訪問它的詞法作用域,即使當這個函數(shù)在它的詞法作用域之外執(zhí)行時。

閉包作用

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

閉包使用場景

    1. 函數(shù)作為返回值
    1. 函數(shù)作為參數(shù)傳遞

閉包不能濫用,否則會導致內(nèi)存泄漏,影響網(wǎng)頁的性能。閉包使用完成后,要立即釋放資源,將引用變量指向 null 。

4、JSON是什么

JSON(JavaScript Object Notation)是一種輕量級的數(shù)據(jù)交換格式。它是基于 JavaScript 的一個子集。數(shù)據(jù)格式簡單,易于讀寫,占用寬帶小。是前后臺交互最常見的一種數(shù)據(jù)格式。JSON也只不過就是一個js對象而已

常用方法

JSON.stringify({name: 'xiaoxin', age: 20}) //對象轉(zhuǎn)為字符串
JSON.parse('{name: \'xiaoxin\', age: 20}') //字符串轉(zhuǎn)為對象

5、JavaScript有幾種類型的值?區(qū)別是什么?

兩大類

  • 棧: 原始數(shù)據(jù)類型(Undefined、Null、Boolean、Number、String、Symbol);
  • 堆: 引用數(shù)據(jù)類型(Object、Array、Function)

區(qū)別

原始數(shù)據(jù)類型 直接存儲在棧(stack)中的簡單數(shù)據(jù)段,占用空間小、大小固定,屬于被頻繁使用數(shù)據(jù)。

引用數(shù)據(jù)類型 存儲在堆(heap)中的對象,占用空間大、大小不固定,如果存儲在棧中,將會影響程序運行的性能;引用數(shù)據(jù)類型在棧中存儲了指針,該指針指向堆中該實體的起始地址。當解釋器尋找引用值時,首先會檢索其在棧中的地址,然后從堆中獲取實體。

6、談談對this的理解?

this 表示當前對象,this 的指向是根據(jù)調(diào)用的上下文來決定的,默認指向 window 對象,指向 window 對象時可以省略不寫,例如

this.alert() === window.this.alert() === alert()

,調(diào)用的上下文環(huán)境包括全局和局部。

執(zhí)行時才能確認值,定義時無法確認

全局環(huán)境 就是在<script></script>中,這里的 this 始終指向的是 window 對象;

局部環(huán)境

    1. 在全局作用域下直接調(diào)用函數(shù),this 指向 window(普通執(zhí)行);
    1. 對象函數(shù)調(diào)用,哪個函數(shù)調(diào)用就指向哪個對象(對象屬性執(zhí)行);
    1. 使用 new 實例化對象,在構造函數(shù)中 this 指向?qū)嵗瘜ο螅嬙旌瘮?shù)執(zhí)行);
    1. 使用 call 或 apply 可以改變 this 的指向。

7、同步和異步的區(qū)別?

同步是一種線性執(zhí)行的方式,執(zhí)行的流程不能跨越。一般用于流程性比較強的程序,比如用戶登錄;

異步是一種并行處理的方式,不必等待一個程序執(zhí)行完,就可以執(zhí)行其它任務。在程序中異步處理的結果通常使用回調(diào)函數(shù)來處理結果。在 JavaScript 中實現(xiàn)異步的方式一般是 Ajax 和 H5 新增的 Web Worker

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

何時需要異步?

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

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

前端使用異步的場景?

    1. 定時任務:setTimeOut、setInterval
    1. 網(wǎng)絡請求:ajax請求、動態(tài)img加載
    1. 事件綁定

8、call和apply的區(qū)別?

相同點 兩個方法產(chǎn)生的作用是一樣的,都用來改變當前函數(shù)調(diào)用的對象;

不同點 調(diào)用的參數(shù)不同,

foo.call(this, arg1, arg2, arg3) == foo.apply(this, args) == this.foo(arg1, arg2, arg3)

9、eval是做什么的?

把字符串參數(shù)解析成JS代碼運行,并返回執(zhí)行的結果。

10、new操作符干了什么?

    1. 創(chuàng)建一個空對象 var obj = new Object();
    1. 設置原型鏈obj.__proto__ = Function.prototype;
    1. 讓 Function 中的 this 指向 obj,并執(zhí)行 Function 的函數(shù)體 var result = Function.call(obj);
    1. 判斷 Function 的返回值類型,如果是值類型,返回 obj,如果是引用類型,就返回引用類型的對象。

11、造成JS內(nèi)存泄漏的情況?

  • 全局變量
  • 閉包
  • DOM被清空時,事件未被清除
  • 子元素存在引用

12、寫出下列結果?

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標準語法:

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標準語法:

element.attachEvent(event, function)

  • event(必須)事件類型,需要加“on”,例如“onClick”
  • function(必選)指定事件觸發(fā)后執(zhí)行的函數(shù)

14、JavaScript事件流機制?

1)冒泡型機制

事件按照從最特定的事件目標到最不特定的事件目標(document對象)的順序觸發(fā)

2)捕獲型機制

事件從最不精確的對象(document對象)開始觸發(fā),然后到最精確。

3)DOM事件流

同時支持兩種事件模型:捕獲型事件和冒泡型事件,但是捕獲型事件先發(fā)生。兩種事件都會觸發(fā)DOM中的所有對象,從document對象開始,也在document對象結束。

事件捕獲機制:事件從最上一級標簽開始往下查找,直到捕獲到事件目標;

事件冒泡機制:事件從事件目標開始,往上冒泡直到頁面的最上一級標簽。

事件的傳播是可以阻止的:

  • 在W3C中,使用stopPropagation()方法;
  • 在IE下設置cancelBubble = true;

在捕獲的事件中stopPropagation()后,后面的冒泡過程也不會發(fā)生了

阻止事件的默認行為:

  • 在W3C中,使用preventDefault()方法;
  • 在IE下設置window.event.returnValue = false

不是所有事件都能冒泡,例如:blur、focus、load、unload等

普通事件和事件綁定的區(qū)別?

普通事件的方法不支持添加多個,最下面的事件會覆蓋上面的;事件綁定可以添加多個

15、JavaScript實現(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';

//構造繼承(不能繼承原型方法)
function Cat(name) {
  Animal.call(this);
  this.name = name || 'Tom';
}

//實例繼承
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、簡要說明對模塊化開發(fā)的理解?

所謂模塊化開發(fā)就是封裝細節(jié),提供使用接口,彼此之間互不影響,每個模塊都是實現(xiàn)某一特定的功能。模塊化開發(fā)的基礎就是函數(shù)。

17、Ajax的工作原理?寫一個Ajax請求?

Ajax的工作原理相當于在用戶和服務器之間加了一個中間件(Ajax引擎),是用戶操作與瀏覽器響應異步化。

const xhr = new XMLHttpRequest();
xhr.open('get', '/api', false);
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) { // 0 請求未初始化 1 請求已建立 2 請求已發(fā)送 3 請求處理中 4 響應已完成
        if (xhr.status == 200) { // 2xx 請求成功 3xx 請求重定向 4xx 客戶端錯誤 5xx 服務端錯誤
            console.log(xhr.responseText)
        }
    }
};
xhr.send(null);

18、寫出兩種單例模式的實現(xiàn)?

//自變量
const singleton = {
    attr: 1,
    method: function () {
        return this.attr;
    }
};

//構造函數(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的代碼實現(xiàn)?

Array.isArray = function(obj) {
    return Object.prototype.toString.call(obj) == '[object Array]';
}

20、window.onload 和 DOMContentLoaded 區(qū)別

  • window.onload 頁面的全部資源加載完才會執(zhí)行,包括圖片、視頻等
  • DOMContentLoaded DOM渲染完即可執(zhí)行,此時圖片、視頻還沒有加載完

21、隨機打印1-100間的10個數(shù)字,去重后取出該10個數(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、寫一個長度一致的隨機數(shù)

let random = Math.random() + '0000000000';
random = random.slice(0, 10);

23、寫一個能遍歷數(shù)組和對象的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、寫一個閉包的使用場景

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、動態(tài)創(chuàng)建10個標簽,點擊彈出對應的序號

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 進行定義。

26、寫一個原型繼承的案例

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、編寫一個通用的事件監(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寫一個冒泡排序算法

//冒泡排序
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寫一個選擇排序算法

//選擇算法
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寫一個插入排序算法


//插入排序
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、寫一個二分法的函數(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)有一個URL字符串“http://www.xxx.com?pn=0”,請寫出刪除其中的pn屬性的js代碼,請盡量實現(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、寫一個函數(shù),計算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 實現(xiàn)一個無限累加的函數(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、手動實現(xiàn)一個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ù),不能作為構造函數(shù),不能使用 new;
    1. 箭頭函數(shù)不綁定 arguments,取而代之用rest參數(shù)(...)解決;
    1. 箭頭函數(shù)不綁定 this,會捕獲其所在的上下文的 this 值,作為自己的 this 值;
    1. 箭頭函數(shù)沒有原型屬性。

37、如何發(fā)送攜帶cookie的跨域請求?

設置 withCredentials = true;

38、根據(jù)id快速查找對應的元素

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、實現(xiàn)對數(shù)組進行亂序

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、計算長度為100的數(shù)組前10個元素之和。

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、手動實現(xiàn)一個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、手動實現(xiàn)一個深拷貝

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ā)來的請求在服務器端被正確處理
  • 204 No content,表示請求成功,但響應報文不含實體的主體部分
  • 205 Reset Content,表示請求成功,但響應報文不含實體的主體部分,但是與 204 響應不同在于要求請求方重置內(nèi)容
  • 206 Partial Content,進行范圍請求

3xx 重定向

  • 301 moved permanently,永久性重定向,表示資源已被分配了新的 URL
  • 302 found,臨時性重定向,表示資源臨時被分配了新的 URL
  • 303 see other,表示資源存在著另一個 URL,應使用 GET 方法獲取資源
  • 304 not modified,表示服務器允許訪問資源,但因發(fā)生請求未滿足條件的情況
  • 307 temporary redirect,臨時重定向,和302含義類似,但是期望客戶端保持請求方法不變向新的地址發(fā)出請求

4xx 客戶端錯誤

  • 400 bad request,請求報文存在語法錯誤
  • 401 unauthorized,表示發(fā)送的請求需要有通過 HTTP 認證的認證信息
  • 403 forbidden,表示對請求資源的訪問被服務器拒絕
  • 404 not found,表示在服務器上沒有找到請求的資源

5xx 服務端錯誤

  • 500 internal sever error,表示服務器端在執(zhí)行請求時發(fā)生了錯誤
  • 501 Not Implemented,表示服務器不支持當前請求所需要的某個功能
  • 503 service unavailable,表明服務器暫時處于超負載或正在停機維護,無法處理請求

details

  • 100 Continue 初始的請求已經(jīng)接受,客戶應當繼續(xù)發(fā)送請求的其余部分
  • 101 Switching Protocols 服務器將遵從客戶的請求轉(zhuǎn)換到另外一種協(xié)議
  • 200 OK 一切正常,對GET和POST請求的應答文檔跟在后面
  • 201 Created 服務器已經(jīng)創(chuàng)建了文檔,Location頭給出了它的URL。
  • 202 Accepted 已經(jīng)接受請求,但處理尚未完成。
  • 203 Non-Authoritative Information 文檔已經(jīng)正常地返回,但一些應答頭可能不正確,因為使用的是文檔的拷貝
  • 204 No Content 沒有新文檔,瀏覽器應該繼續(xù)顯示原來的文檔。如果用戶定期地刷新頁面,而Servlet可以確定用戶文檔足夠新,這個狀態(tài)代碼是很有用的
  • 205 Reset Content 沒有新的內(nèi)容,但瀏覽器應該重置它所顯示的內(nèi)容。用來強制瀏覽器清除表單輸入內(nèi)容
  • 206 Partial Content 客戶發(fā)送了一個帶有Range頭的GET請求,服務器完成了它
  • 300 Multiple Choices 客戶請求的文檔可以在多個位置找到,這些位置已經(jīng)在返回的文檔內(nèi)列出。如果服務器要提出優(yōu)先選擇,則應該在Location應答頭指明。
  • 301 Moved Permanently 客戶請求的文檔在其他地方,新的URL在Location頭中給出,瀏覽器應該自動地訪問新的URL。
  • 302 Found 類似于301,但新的URL應該被視為臨時性的替代,而不是永久性的。
  • 303 See Other 類似于301/302,不同之處在于,如果原來的請求是POST,Location頭指定的重定向目標文檔應該通過GET提取
  • 304 Not Modified 客戶端有緩沖的文檔并發(fā)出了一個條件性的請求(一般是提供If-Modified-Since頭表示客戶只想比指定日期更新的文檔)。服務器告訴客戶,原來緩沖的文檔還可以繼續(xù)使用。
  • 305 Use Proxy 客戶請求的文檔應該通過Location頭所指明的代理服務器提取
  • 307 Temporary Redirect和302(Found)相同。許多瀏覽器會錯誤地響應302應答進行重定向,即使原來的請求是 POST,即使它實際上只能在POST請求的應答是303時才能重定向。由于這個原因,HTTP 1.1新增了307,以便更加清除地區(qū)分幾個狀態(tài)代碼: 當出現(xiàn)303應答時,瀏覽器可以跟隨重定向的GET和POST請求;如果是307應答,則瀏覽器只能跟隨對GET請求的重定向。
  • 400 Bad Request 請求出現(xiàn)語法錯誤。
  • 401 Unauthorized 客戶試圖未經(jīng)授權訪問受密碼保護的頁面。應答中會包含一個WWW-Authenticate頭,瀏覽器據(jù)此顯示用戶名字/密碼對話框,然后在填寫合適的Authorization頭后再次發(fā)出請求。
  • 403 Forbidden 資源不可用。
  • 404 Not Found 無法找到指定位置的資源
  • 405 Method Not Allowed 請求方法(GET、POST、HEAD、Delete、PUT、TRACE等)對指定的資源不適用。
  • 406 Not Acceptable
    指定的資源已經(jīng)找到,但它的MIME類型和客戶在Accpet頭中所指定的不兼容
  • 407 Proxy Authentication Required
    類似于401,表示客戶必須先經(jīng)過代理服務器的授權。
  • 408 Request Timeout 在服務器許可的等待時間內(nèi),客戶一直沒有發(fā)出任何請求。客戶可以在以后重復同一請求。
  • 409 Conflict 通常和PUT請求有關。由于請求和資源的當前狀態(tài)相沖突,因此請求不能成功。
  • 410 Gone 所請求的文檔已經(jīng)不再可用,而且服務器不知道應該重定向到哪一個地址。它和404的不同在于,返回407表示文檔永久地離開了指定的位置,而404表示由于未知的原因文檔不可用。
  • 411 Length Required 服務器不能處理請求,除非客戶發(fā)送一個Content-Length頭。
  • 412 Precondition Failed 請求頭中指定的一些前提條件失敗
  • 413 Request Entity Too Large 目標文檔的大小超過服務器當前愿意處理的大小。如果服務器認為自己能夠稍后再處理該請求,則應該提供一個Retry-After頭
  • 414 Request URI Too Long URI太長
  • 416 Requested Range Not Satisfiable 服務器不能滿足客戶在請求中指定的Range頭
  • 500 Internal Server Error 服務器遇到了意料不到的情況,不能完成客戶的請求
  • 501 Not Implemented 服務器不支持實現(xiàn)請求所需要的功能。例如,客戶發(fā)出了一個服務器不支持的PUT請求
  • 502 Bad Gateway 服務器作為網(wǎng)關或者代理時,為了完成請求訪問下一個服務器,但該服務器返回了非法的應答
  • 503 Service Unavailable 服務器由于維護或者負載過重未能應答。例如,Servlet可能在數(shù)據(jù)庫連接池已滿的情況下返回503。服務器返回503時可以提供一個Retry-After頭
  • 504 Gateway Timeout 由作為代理或網(wǎng)關的服務器使用,表示不能及時地從遠程服務器獲得應答
  • 505 HTTP Version Not Supported 服務器不支持請求中所指明的HTTP版本
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容

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