HTML相關
1、XHTML和HTML有什么區(qū)別
HTML是一種基本的WEB網(wǎng)頁實際語言,XHTML是一種基于XML的置標語言
最主要的不同:
- XHTML 元素必須被正確的嵌套;
- XHTML 元素必須被關閉;
- XHTML 標簽名必須用小寫字母;
- XHTML 文檔必須擁有根元素。
2、什么是語義化的HTML?
- 直觀的認識標簽,對于搜索引擎的抓取有好處,用正確的標簽做正確的事。HTML語義化就是讓頁面的內(nèi)容結構化,便于對瀏覽器、搜索引擎解析;
- 在沒有css樣式加持的情況下也以一種文檔格式顯示,并且是容易閱讀的。搜索引擎的爬蟲依賴于標記來確定上下文和各個關鍵字的權重,利于SEO。
- 使閱讀源代碼的人對網(wǎng)站更容易將網(wǎng)站分塊,便于閱讀維護理解。
3、常見的瀏覽器內(nèi)核有哪些?
- Trident內(nèi)核 IE、360、搜狗等
- Gecko內(nèi)核 Netscape6及以上版本、Firefox
- Presto內(nèi)核 Opera7及以上
- Webkit Safari、Chrome等
4、H5有哪些新特性?移除了哪些元素?如何處理HTML5新標簽的瀏覽器兼容問題?
新特性
- canvas繪圖;
- 本地離線存儲localStorage長期存儲數(shù)據(jù),瀏覽器關閉后數(shù)據(jù)不丟失;
- sessionStorage數(shù)據(jù)在瀏覽器關閉后會自動刪除;
- 用于媒體回放的video和audio;
- 語義化更好的內(nèi)容標簽如article、footer、header、nav、setion;
- 表單控件 calendar、date、time、email、url、search;
- 新的技術 web worker、web socket、geolocation。
移除元素
- 純表現(xiàn)元素 font、big、center、u、tt、s;
- 對可用性產(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中的常見單位?
- px: 絕對單位,頁面按精確像素展示;
- em: 相對單位,基準點為父節(jié)點字體的大小,如果自身定義了font-size按自身來計算,整個頁面內(nèi)1em不是一個固定的值;
- rem: 相對單位,可理解為“root em”,相當于根節(jié)點html的字體大小來計算。
- vm: viewpoint width,視窗寬度,1vm等于視窗寬度的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ī)則
- 所有的引用類型(數(shù)組、對象、函數(shù)),都具有對象特性,即可自由擴展屬性(除了null除外)
- 所有的引用類型(數(shù)組、對象、函數(shù)),都有一個
__proto__
(隱式原型)屬性,屬性值是一個普通的對象;
- 所有的引用類型(數(shù)組、對象、函數(shù)),都有一個
- 所有的函數(shù),都有一個prototype(顯式原型)屬性,屬性值也是一個普通的對象;
- 所有的引用類型(數(shù)組、對象、函數(shù)),
__proto__
屬性值指向它的構造函數(shù)的prototype屬性值;
- 所有的引用類型(數(shù)組、對象、函數(shù)),
- 當試圖得到一個對象的某個屬性時,如果這個對象本身沒有這個屬性,那么會去它的
__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í)行時。
閉包作用
- 使用閉包可以訪問函數(shù)中的變量;
- 可以將變量長期保存在內(nèi)存中,生命周期比較長。
閉包使用場景
- 函數(shù)作為返回值
- 函數(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)境
- 在全局作用域下直接調(diào)用函數(shù),this 指向 window(普通執(zhí)行);
- 對象函數(shù)調(diào)用,哪個函數(shù)調(diào)用就指向哪個對象(對象屬性執(zhí)行);
- 使用 new 實例化對象,在構造函數(shù)中 this 指向?qū)嵗瘜ο螅嬙旌瘮?shù)執(zhí)行);
- 使用 call 或 apply 可以改變 this 的指向。
7、同步和異步的區(qū)別?
同步是一種線性執(zhí)行的方式,執(zhí)行的流程不能跨越。一般用于流程性比較強的程序,比如用戶登錄;
異步是一種并行處理的方式,不必等待一個程序執(zhí)行完,就可以執(zhí)行其它任務。在程序中異步處理的結果通常使用回調(diào)函數(shù)來處理結果。在 JavaScript 中實現(xiàn)異步的方式一般是 Ajax
和 H5 新增的 Web Worker
。
- 同步會阻塞代碼執(zhí)行,而異步不會
- alert是同步,setTimeOut是異步
何時需要異步?
- 在可能發(fā)生等待的情況
- 等待過程中不能像alert一樣阻塞程序運行
因此,所有的“等待的情況”都需要異步
前端使用異步的場景?
- 定時任務:setTimeOut、setInterval
- 網(wǎng)絡請求:ajax請求、動態(tài)img加載
- 事件綁定
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操作符干了什么?
- 創(chuàng)建一個空對象
var obj = new Object()
;
- 創(chuàng)建一個空對象
- 設置原型鏈
obj.__proto__ = Function.prototype
;
- 設置原型鏈
- 讓 Function 中的 this 指向 obj,并執(zhí)行 Function 的函數(shù)體
var result = Function.call(obj)
;
- 讓 Function 中的 this 指向 obj,并執(zhí)行 Function 的函數(shù)體
- 判斷 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ū)別?
- 箭頭函數(shù)是匿名函數(shù),不能作為構造函數(shù),不能使用 new;
- 箭頭函數(shù)不綁定 arguments,取而代之用rest參數(shù)(...)解決;
- 箭頭函數(shù)不綁定 this,會捕獲其所在的上下文的 this 值,作為自己的 this 值;
- 箭頭函數(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版本