常見前端面試問題彙總2018
轉載請註明來源
---------------------
作者:MrCris
來源:CSDN
原文:https://blog.csdn.net/weixin_37861326/article/details/80620576?utm_source=copy
版權宣告:本文為博主原創文章,轉載請附上博文連結!
2)2018/6/10
1. 如何解決跨域問題
JSONP:
原理是:動態插入script標籤,通過script標籤引入一個js檔案,這個js檔案載入成功後會執行我們在url引數中指定的函式,並且會把我們需要的json資料作為引數傳入。
由於同源策略的限制,XmlHttpRequest只允許請求當前源(域名、協議、埠)的資源,為了實現跨域請求,可以通過script標籤實現跨域請求,然後在服務端輸出JSON資料並執行回撥函式,從而解決了跨域的資料請求。
優點是相容性好,簡單易用,支援瀏覽器與伺服器雙向通訊。缺點是隻支援GET請求。
JSONP:json+padding(內填充),顧名思義,就是把JSON填充到一個盒子裡
<script> function createJs(sUrl){ var oScript = document.createElement('script'); oScript.type = 'text/javascript'; oScript.src = sUrl; document.getElementsByTagName('head')[0].appendChild(oScript); } createJs('jsonp.js'); box({ 'name': 'test' }); function box(json){ alert(json.name); } </script>
CORS:
伺服器端對於CORS的支援,主要就是通過設定Access-Control-Allow-Origin來進行的。如果瀏覽器檢測到相應的設定,就可以允許Ajax進行跨域的訪問。
通過修改document.domain來跨子域
將子域和主域的document.domain設為同一個主域.前提條件:這兩個域名必須屬於同一個基礎域名!而且所用的協議,埠都要一致,否則無法利用document.domain進行跨域
主域相同的使用document.domain
使用window.name來進行跨域
window物件有個name屬性,該屬性有個特徵:即在一個視窗(window)的生命週期內,視窗載入的所有的頁面都是共享一個window.name的,每個頁面對window.name都有讀寫的許可權,window.name是持久存在一個視窗載入過的所有頁面中的
使用HTML5中新引進的window.postMessage方法來跨域傳送資料
還有flash、在伺服器上設定代理頁面等跨域方式。個人認為window.name的方法既不復雜,也能相容到幾乎所有瀏覽器,這真是極好的一種跨域方法。
2. XML和JSON的區別?
(1).資料體積方面。
JSON相對於XML來講,資料的體積小,傳遞的速度更快些。
(2).資料互動方面。
JSON與JavaScript的互動更加方便,更容易解析處理,更好的資料互動。
(3).資料描述方面。
JSON對資料的描述性比XML較差。
(4).傳輸速度方面。
JSON的速度要遠遠快於XML。
3. 快速排序的思想並實現一個快排?
“快速排序”的思想很簡單,整個排序過程只需要三步:
(1)在資料集之中,找一個基準點
(2)建立兩個陣列,分別儲存左邊和右邊的陣列
(3)利用遞迴進行下次比較
<script type="text/javascript">
function quickSort(arr){
if(arr.length<=1){
return arr;//如果陣列只有一個數,就直接返回;
}
var num = Math.floor(arr.length/2);//找到中間數的索引值,如果是浮點數,則向下取整
var numValue = arr.splice(num,1);//找到中間數的值
var left = [];
var right = [];
for(var i=0;i<arr.length;i++){
if(arr[i]<numValue){
left.push(arr[i]);//基準點的左邊的數傳到左邊陣列
}
else{
right.push(arr[i]);//基準點的右邊的數傳到右邊陣列
}
}
return quickSort(left).concat([numValue],quickSort(right));//遞迴不斷重複比較
}
alert(quickSort([32,45,37,16,2,87]));//彈出“2,16,32,37,45,87”
</script>
3)2018/6/16
window.onload和$(function(){})區別
window.onload是js原生的事件,$(function(){})是Jquery的方法(等價於$(document).ready(function(){}) ),兩者主要有以下幾點差別:
1、window.onload:在頁面所有資源載入完後執行,如果有多個定義則只執行最後一個
2、$(function(){}):在Dom節點建立完成後執行,如果有多個定義則依次執行
可以看出$(function(){})在window.onload前執行
比如:頁面中只有一個img標籤,當img節點建立完後就會執行$(function(){})中的程式碼,當img的src指定的圖片完全載入完後才會觸發window.onload事件。
4)2018/6/20
1. 用div+css寫出文字水平垂直居中,圖片水平垂直居中的樣式及佈局
// 單文字垂直居中:
.align_cc{height:30px;line-height:30px;text-align:center; }
// 多行文字垂直居中:
.align_box {width: 220px;height: 200px;display: table-cell;vertical-align: middle;text-align: center;*position: relative;}
.align_box span.align_word {display: inline-block;*position: absolute;*left: 0;*top: 50%;*width: 100%;}
.align_box span.align_word a {*display: inline-block;*position: relative;*top: -50%;}
<div class="align_box">
<span class="align_word">
<a href="">文字垂直居中對齊文字垂直居中對齊文字垂直居中對齊</a>
</span>
</div>
// 圖片垂直居中:
.ver_pic {width: 200px; height: 200px;line-height:200px;text-align: center;background: #eee;}
.ver_pic img { vertical-align:middle;width:100px;height:100px;}
2. 用div+css寫出左側固定(width:200px),右側自適應的頁面佈局
.c_left{float:left;display:inline-block;width:200px;}
.c_right{margin-left:200px;}
3. css瀏覽器相容性的寫法
* :IE6、IE7可以識別;
_和- :IE6可以識別;
!important :表示高優先順序,IE7及以上、Firefox都支援,IE6認識帶!important的樣式屬性,但不認識!important的優先順序
-webkit- :針對谷歌瀏覽器核心支援的CSS樣式
-moz- :針對Firefox瀏覽器的核心CSS寫法
-ms- :針對ie核心CSS寫法
-o- :針對opera核心CSS寫法
4. jQuery中提供了四種事件監聽方式,分別是bind、live、delegate、on,對應的解除監聽的函式分別是unbind、die、undelegate、off
bind()可以向匹配的元素繫結一個或者多個事件處理器。但是它不會在沒有存在dom樹中的元素繫結該事件;而live()、delegate()則可以實現在不存在dom樹中的元素繼續繫結事件.
live方法其實是bind方法的變種,其基本功能同bind方法的功能一樣都是為一個元素繫結某個事件,但是bind方法只能給當前存在的元素繫結事件,對於事後採用JS等方式新生成的元素無效,而live方法則正好彌補了bind方法的這個缺陷,它可以對後生成的元素也可以繫結相應的事件。
live()方法用到了事件委託的概念來處理事件的繫結,會繫結相應的事件到你所選擇的元素的根元素上,即是document元素上,一旦事件冒泡到document上,jQuery將會查詢selector/event metadata,然後決定那個handler應該被呼叫。
delegate()有點像.live(),不同於.live()的地方在於,它不會把所有的event全部繫結到document,而是由你決定把它放在哪兒。而和.live()相同的地方在於都是用event delegation.
其實.bind(), .live(), .delegate()都是通過.on()來實現的,.unbind(), .die(), .undelegate(),也是一樣的都是通過.off()來實現的。
bind的缺點:
它會繫結事件到所有的選出來的元素上,當元素很多時,會出現效率問題;
當頁面載入完的時候,你才可以進行bind();
它不會繫結到在它執行完後動態新增的那些元素上。
live的優點:
僅有一次的事件繫結,繫結到document上;
動態新增的elemtns依然可以觸發那些早先繫結的事件,因為事件真正的繫結是在document上;
可以在document ready之前就可以繫結那些需要的事件。
live的缺點:
從jq1.7開始已經不被推薦了;
當一個元素採用live方法進行事件的繫結的時候,如果想阻止事件的傳遞或冒泡,就要在函式中return false,僅僅呼叫stopPropagation()是無法實現阻止事件的傳遞或者冒泡的,因為都要到達document,所以速度也會非常慢;
delegate的優點:
可以選擇把這個事件放到哪個元素上了,可以有效的減小你所要查詢的元素;
可以用在動態新增的元素上。
delegate的缺點:
需要查詢哪個元素上發生了那個事件,儘管比document少很多了,不過,還是得浪費時間來查詢。
on的優點:
提供了一種統一繫結事件的方法,可以用.on()來代替上述的3種方法。
one是在dom樹載入後,對元素的繫結,和bind一樣屬於後期繫結,但是會在事件執行之後移除元素的繫結事件,事件只執行一次。
5. js瀏覽器相容性的寫法(檢視)
6. 造成js記憶體洩漏的問題
記憶體洩漏指任何物件在您不再擁有或需要它之後仍然存在。
垃圾回收器定期掃描物件,並計算引用了每個物件的其他物件的數量。如果一個物件的引用數量為 0(沒有其他物件引用過該物件),或對該物件的惟一引用是迴圈的,那麼該物件的記憶體即可回收。
1)setTimeout 的第一個引數使用字串而非函式的話,會引發記憶體洩漏。
2)閉包
3)控制檯日誌
4)迴圈(在兩個物件彼此引用且彼此保留時,就會產生一個迴圈)
7. 談你對js閉包的理解
考的是變數的作用域。閉包可以用在許多地方。它的最大用處有兩個,一個是前面提到的可以讀取函式內部的變數,另一個就是讓這些變數的值始終保持在記憶體中。
1)由於閉包會使得函式中的變數都被儲存在記憶體中,記憶體消耗很大,所以不能濫用閉包,否則會造成網頁的效能問題,
在IE中可能導致記憶體洩露。解決方法是,在退出函式之前,將不使用的區域性變數全部刪除。
2)閉包會在父函式外部,改變父函式內部變數的值。
所以,如果你把父函式當作物件(object)使用,把閉包當作它的公用方法(Public Method),把內部變數當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函式內部變數的值。
8. js面向物件的幾種方式
第一種模式:工廠方式
var lev=function(){ return "指令碼之家"; };
function Parent(){ var Child = new Object(); Child.name="指令碼"; Child.age="4"; Child.lev=lev; return Child; };
var x = Parent();
alert(x.name);
alert(x.lev());
第二種模式:建構函式方式
var lev=function(){ return "指令碼之家"; };
function Parent(){ this.name="指令碼"; this.age="30"; this.lev=lev; };
var x =new Parent();
alert(x.name);
alert(x.lev());
第三種模式:原型模式
var lev=function(){ return "指令碼之家"; };
function Parent(){ };
Parent.prototype.name="李小龍";
Parent.prototype.age="30";
Parent.prototype.lev=lev;
var x =new Parent();
alert(x.name);
alert(x.lev());
第四種模式:混合的建構函式,原型方式(推薦)
function Parent(){ this.name="指令碼"; this.age=4; };
Parent.prototype.lev=function(){ return this.name; };
var x =new Parent();
alert(x.lev());
第五種模式:動態原型方式
function Parent(){ this.name="指令碼"; this.age=4; if(typeof Parent._lev=="undefined"){
Parent.prototype.lev=function(){ return this.name; } Parent._lev=true; }
};
var x =new Parent();
alert(x.lev());
5)2018/6/21
1. display:none和visibility:hidden
CSS display:none;
使用該屬性後,HTML元素(物件)的寬度、高度等各種屬性值都將“丟失”,視為不存在,不載入;
一旦父節點元素應用了display:none,父節點及其子孫節點元素全部不可見
隱藏產生reflow和repaint(迴流與重繪)
visibility:hidden;
使用該屬性後,HTML元素(物件)僅僅是在視覺上看不見(完全透明),而它所佔據的空間位置仍然存在,也即是說它仍具有高度、寬度等屬性值。
2. 清除浮動
方法一:使用帶clear屬性的空元素
在浮動元素後使用一個空元素如<div class="clear"></div>,並在CSS中賦予.clear{clear:both;}屬性即可清理浮動。
優點:簡單,程式碼少,瀏覽器相容性好。
缺點:需要新增大量無語義的html元素,程式碼不夠優雅,後期不容易維護。
方法二:使用CSS的overflow屬性
給浮動元素的容器新增overflow:hidden;或overflow:auto;可以清除浮動
方法三:給浮動的元素的容器新增浮動
給浮動元素的容器也新增上浮動屬性即可清除內部浮動,但是這樣會使其整體浮動,影響佈局,不推薦使用。
方法四:使用鄰接元素處理
給浮動元素後面的元素換行符 br 新增clear屬性。
方法五:父級div定義 height
原理:父級div手動定義height,就解決了父級div無法自動獲取到高度的問題。
方法六:父級div定義 偽類:after 和 zoom
在網頁主要佈局時使用:after偽元素方法並作為主要清理浮動方式;在**小模組如ul裡使用overflow:hidde**n;(留意可能產生的隱藏溢位元素問題);如果本身就是浮動元素則可自動清除內部浮動,無需格外處理;正文中使用鄰接元素清理之前的浮動。最後可以使用相對完美的:after偽元素方法清理浮動,文件結構更加清晰。
6)2018/7/16
1.HTML 定義了網頁的內容
2.CSS 描述了網頁的佈局
3.JavaScript 網頁的行為
console.log(),會在瀏覽器控制檯打印出資訊。
console.dir()可以顯示一個物件所有的屬性和方法。
1 null和undefined的區別?
null是一個表示”無”的物件,轉為數值時為0
undefined是一個表示”無”的原始值,轉為數值時為NaN
當宣告的變數還未被初始化時,變數的預設值為undefined
null用來表示尚未存在的物件,常用來表示函式企圖返回一個不存在的物件
undefined表示 “缺少值”,就是此處應該有一個值,但是還沒有定義。典型用法是:
1. 變數被聲明瞭,但沒有賦值時,就等於 undefined
2. 呼叫函式時,應該提供的引數沒有提供,該引數等於 undefined
3. 物件沒有賦值的屬性,該屬性的值為 undefined
4. 函式沒有返回值時,預設返回 undefined
null表示“沒有物件”,即該處不應該有值。典型用法是:
1. 作為函式的引數,表示該函式的引數不是物件
2. 作為物件原型鏈的終點
2 new操作符具體幹了什麼?
1)建立一個空物件,並且 this 變數引用該物件,同時還繼承了該函式的原型
2)屬性和方法被加入到 this 引用的物件中
3)新建立的物件由 this 所引用,並且最後隱式的返回 this
3 js延遲載入的方式有哪些?
1)defer和async
沒有defer或async,瀏覽器會立即載入並執行指定的指令碼,立即是在渲染該script標籤下的文件元素之前,不等待後續載入的文件元素,讀到就載入並執行
有async,載入和渲染後續文件元素的過程和script.js載入和執行並行執行(非同步)
有defer,並行,但是在所有元素解析完成後執行。
2)動態建立DOM方式(建立script,插入到DOM中,載入完畢後callBack)
3)按需非同步載入js
4 有哪些效能優化的方法
1)減少http請求次數:CSS Sprites, JS、CSS 原始碼壓縮、圖片大小控制合適;網頁 Gzip,CDN 託管,data 快取 ,圖片伺服器
2)前端模板 JS + 資料,減少由於HTML標籤導致的頻寬浪費,前端用變數儲存 AJAX 請求結果,每次操作本地變數,不用請求,減少請求次數
3)用 innerHTML 代替 DOM 操作,減少 DOM 操作次數,優化 javascript 效能
4)當需要設定的樣式很多時設定 className 而不是直接操作 style
5)少用全域性變數、快取DOM節點查詢的結果。減少 IO 讀取操作
6)避免使用 CSS Expression(css表示式)又稱 Dynamic properties(動態屬性)
7)圖片預載入,將樣式表放在頂部,將指令碼放在底部,加上時間戳
5 哪些操作會造成記憶體洩漏?
記憶體洩漏指任何物件在您不再擁有或不再需要它之後仍然存在。
垃圾回收器定期掃描物件,並計算引用了每個物件的其他物件的數量。如果一個物件的引用數量為 0(沒有其他物件引用過該物件),或對該物件的惟一引用是迴圈的,那麼該物件的記憶體即可回收。
1)setTimeout 的第一個引數使用字串而非函式的話,會引發記憶體洩漏。
2)閉包
3)控制檯日誌
4)迴圈(在兩個物件彼此引用且彼此保留時,就會產生一個迴圈)
垃圾回收機制?
答:在Javascript中,如果一個物件不再被引用,那麼這個物件就會被GC回收。如果兩個物件互相引用,而不再被第3者所引用,那麼這兩個互相引用的物件也會被回收。因為函式a被b引用,b又被a外的c引用,這就是為什麼函式a執行後不會被回收的原因。
6 javascript的typeof返回哪些資料型別(7種)
Object number function boolean underfind string symbol
typeof ‘123’ // string
typeof null // object
typeof 123 //number
typeof false // boolean
typeof [1,2,3] // object
typeof {‘name’:’tony’} // object
typeof undefined // undefined
typeof function fn(){} // function
另外ES6新加一種 symbol
var symbol = Symbol()
typeof symbol //"symbol"
7 例舉3種強制型別轉換和2種隱式型別轉換?
強制(parseInt,parseFloat,number)
隱式(== – ===)
8 split() join() 的區別
前者是切割成陣列的形式,後者是將陣列轉換成字串
('string').split('') // ["s", "t", "r", "i", "n", "g"]
('string').split('t') // ["s", "ring"]
["s", "t", "r", "i", "n", "g"].join('') // “string”
["s", "t", "r", "i", "n", "g"].join() // "s,t,r,i,n,g"
["s", "t", "r", "i", "n", "g"].join(',') // "s,t,r,i,n,g"
["s", "t", "r", "i", "n", "g"].join('.') // "s.t.r.i.n.g"
9 陣列方法pop() push() unshift() shift()
push()尾部新增 pop()尾部刪除
unshift()頭部新增 shift()頭部刪除
var arr = [1,2,3,4]
arr.push(5) // arr = [1, 2, 3, 4, 5]
var arr = [1,2,3,4]
arr.pop(3) // 返回的值為4
// arr = [1, 2, 3]
var arr = [1,2,3,4]
arr.unshift(5) // arr = [5, 1, 2, 3, 4]
var arr = [1,2,3,4]
arr.shift() // arr = [2, 3, 4]
10 事件繫結和普通事件有什麼區別
事件繫結是指把事件註冊到具體的元素之上,普通事件指的是可以用來註冊的事件
11 IE和DOM事件流的區別
1.執行順序不一樣
2.引數不一樣
3.事件加不加on
4.this指向問題
12 IE和標準下有哪些相容性的寫法
var ev = ev || window.event
document.documentElement.clientWidth || document.body.clientWidth
var target = ev.srcElement||ev.target
13 call和apply的區別
Object.call(this,obj1,obj2,obj3)
Object.apply(this,arguments)
14 已知ID的Input輸入框,希望獲取這個輸入框的輸入值,怎麼做?(不使用第三方框架)
document.getElementById(“ID”).value
15 希望獲取到頁面中所有的checkbox怎麼做?(不使用第三方框架)
var domList = document.getElementsByTagName(‘input’)
var checkBoxList = [];
var len = domList.length; //快取到區域性變數
while (len--) { //使用while的效率會比for迴圈更高
if (domList[len].type == ‘checkbox’) {
checkBoxList.push(domList[len]);
}
}
16 設定一個已知ID的DIV的html內容為xxxx,字型顏色設定為黑色(不使用第三方框架)
var dom = document.getElementById(“ID”);
dom.innerHTML = “xxxx”
dom.style.color = “#000”
17 當一個DOM節點被點選時候,我們希望能夠執行一個函式,應該怎麼做?
直接在DOM裡繫結事件:<div onclick=”test()”></div>
在JS裡通過onclick繫結:xxx.onclick = test
通過事件新增進行繫結:addEventListener(xxx, ‘click’, test)
那麼問題來了,Javascript的事件流模型都有什麼?
“事件冒泡”:事件開始由最具體的元素接收,然後逐級向上傳播
“事件捕捉”:事件由最不具體的節點先接收,然後逐級向下,一直到最具體的
“DOM事件流”:三個階段:事件捕捉,目標階段,事件冒泡
18 看下列程式碼輸出為何?解釋原因。
var a;
alert(typeof a); // undefined
alert(b); // 報錯
解釋:undefined是一個只有一個值的資料型別,這個值就是“undefined”,在使用var宣告變數但並未對其賦值進行初始化時,這個變數的值就是undefined。而b由於未宣告將報錯。注意未申明的變數和聲明瞭未賦值的是不一樣的。
--------------------------------------------------------
var a = null;
alert(typeof a); //object
解釋:null是一個只有一個值的資料型別,這個值就是null。表示一個空指標物件,所以用typeof檢測會返回”object”。
--------------------------------------------------------
var undefined;
undefined == null; // true
1 == true; // true
2 == true; // false
0 == false; // true
2 == false; // false
0 == ''; // true
NaN == NaN; // false
null == null // true
undefined == undefined // true
[] == false; // true
[] == ![]; // true
[] == [] // false
!NaN // true
undefined與null相等,但不恆等(===)
一個是number一個是string時,會嘗試將string轉換為number
嘗試將boolean轉換為number,0或1
嘗試將Object轉換成number或string,取決於另外一個對比量的型別
所以,對於0、空字串的判斷,建議使用 “===” 。“===”會先判斷兩邊的值型別,型別不匹配時為false。
--------------------------------------------------------
var foo = "11"+2-"1";
console.log(foo);
console.log(typeof foo);
執行完後foo的值為111,foo的型別為number。
--------------------------------------------------------
console.log(1+ "2"+"2");//1+"2"先轉化為“12”然後進行字串的相加結果是“122”
console.log(1+ +"2"+"2");//由於一元運算子“+”的優先順序更高,因此+“2”轉換為數值2,然後1+2=3,最後數值和字串相加,轉換為字串的拼接,結果“32”
console.log(1+ -"1"+"2");//先執行取反,變成1-1=0,然後0+“2”,結果“02”
console.log(+"1"+ "1"+"2");//先執行數值轉換,相當於執行1+“1”+“2”,結果“112”
console.log("A"- "B"+"2");//先執行"A"- "B"返回NaN,再執行NaN+"2"=>"NaN2"
console.log("A"- "B"+2);//先執行"A"- "B"返回NaN+2,NaN執行加減法均返回NaN
--------------------------------------------------------
var a = new Object();
a.value = 1;
b = a;
b.value = 2;
alert(a.value);
答案:2(考察引用資料型別細節)
--------------------------------------------------------
var foo = 1;
function(){
console.log(foo);
var foo = 2;
console.log(foo);
}
答案:輸出undefined 和 2。上面程式碼相當於:
var foo = 1;
function test(){
var foo;
console.log(foo); //undefined
foo = 2;
console.log(foo); // 2;
}
test()
函式宣告與變數宣告會被JavaScript引擎隱式地提升到當前作用域的頂部,但是隻提升宣告不會提升賦值部分。
--------------------------------------------------------
for(var i=1;i<=3;i++){
setTimeout(function(){
console.log(i);
},0);
};
答案:4 4 4。
原因:Javascript事件處理器線上程空閒之前不會執行。追問,如何讓上述程式碼輸出1 2 3?
for(var i=1;i<=3;i++){
setTimeout((function(a){ //改成立即執行函式
console.log(a);
})(i),0);
};
1 //輸出
2
3
--------------------------------------------------------
var arr = new Array(1 ,3 ,5);
arr[4]='z';
arr2 = arr.reverse(); // arr = [“z”,‘’,5,3,1]
arr3 = arr.concat(arr2);
alert(arr3);
彈出提示對話方塊:z,,5,3,1,z,,5,3,1
提示:引用型別
--------------------------------------------------------
<script>
var a = 1;
</script>
<script>
var a;
console.log(a);
</script>
輸出結果為 1;宣告提前
--------------------------------------------------------
var a;
var b = a * 0; // undefined*0 = NaN
if (b == b) {
console.log(b * 2 + "2" - 0 + 4);
} else {
console.log(!b * 2 + "2" - 0 + 4);
}
答案輸出 26
--------------------------------------------------------
<script>
var a = 1;
</script>
<script>
var a;
var b = a * 0;
if (b == b) {
console.log(b * 2 + "2" - 0 + 4);
} else {
console.log(!b * 2 + "2" - 0 + 4);
}
</script>
答案輸出 6
--------------------------------------------------------
var t = 10;
function test(t){
var t = t++;
}
test(t);
console.log(t);
答案輸出10
--------------------------------------------------------
var t = 10;
function test(test){
var t = test++;
console.log(t) // 10
}
test(t);
console.log(t);
答案輸出10
--------------------------------------------------------
var t = 10;
function test(test){
t = test++;
}
test(t);
console.log(t);
答案:10
--------------------------------------------------------
var t = 10;
function test(test){
t = ++test;
}
test(t);
console.log(t);
答案:11
--------------------------------------------------------
var t = 10;
function test(test){
t = t + test;
console.log(t);
var t = 3;
}
test(t);
console.log(t);
答案:NaN 10
--------------------------------------------------------
var a;
var b = a / 0; // NaN
if (b == b) {
console.log(b * 2 + "2" - 0 + 4);
} else {
console.log(!b * 2 + "2" - 0 + 4);
}
答案:26
--------------------------------------------------------
<script>
var a = 1;
</script>
<script>
var a;
var b = a / 0; // Infinity
if (b == b) {
console.log(b * 2 + "2" + 4);
} else {
console.log(!b * 2 + "2" + 4);
}
</script>
答案:Infinity24
此外 !Infinity = false
--------------------------------------------------------
var iNum = 0;
for(var i = 1; i< 10; i++){
if(i % 5 == 0){
continue;
}
iNum++;
}
console.log(iNum)
答案:8
--------------------------------------------------------
var obj = {proto: {a:1,b:2}};
function F(){};
F.prototype = obj.proto;
var f = new F();
obj.proto.c = 3;
obj.proto = {a:-1, b:-2};
console.log(f.a);
console.log(f.c);
delete F.prototype['a'];
console.log(f.a);
console.log(obj.proto.a);
答案
1
3
undefined
-1
--------------------------------------------------------
function setName(){
name="張三";
}
setName();
console.log(name);
答案:"張三"
--------------------------------------------------------
//考點:1、變數宣告提升 2、變數搜尋機制
var a=1;
function test(){
console.log(a);
var a=1;
}
test();
答案:undefined
--------------------------------------------------------
var b=2;
function test2(){
window.b=3;
console.log(b);
}
test2();
答案:3
--------------------------------------------------------
c=5;//宣告一個全域性變數c
function test3(){
window.c=3;
console.log(c); //答案:undefined,原因:由於此時的c是一個區域性變數c,並且沒有被賦值
var c;
console.log(window.c);//答案:3,原因:這裡的c就是一個全域性變數c
}
test3();
--------------------------------------------------------
var arr = [];
arr[0] = 'a';
arr[1] = 'b';
arr[10] = 'c';
alert(arr.length); //答案:11
console.log(arr[5]); //答案:undefined
--------------------------------------------------------
var a=1;
console.log(a++); //答案:1
console.log(++a); //答案:3
--------------------------------------------------------
console.log(null==undefined); //答案:true
console.log("1"==1); //答案:true,因為會將數字1先轉換為字串1
console.log("1"===1); //答案:false,因為資料型別不一致
--------------------------------------------------------
typeof 1; "number"
typeof "hello"; "string"
typeof /[0-9]/; "object"
typeof {}; "object"
typeof null; "object"
typeof undefined; "undefined"
typeof [1,2,3]; "object"
typeof function(){}; //"function"
--------------------------------------------------------
parseInt(3.14); //3
parseFloat("3asdf"); //3
parseInt("1.23abc456"); // 1
parseInt(true);// NaN
--------------------------------------------------------
//考點:函式宣告提前
function bar() {
return foo;
foo = 10;
function foo() {}
//var foo = 11;
}
alert(typeof bar());//"function"
--------------------------------------------------------
var foo = 1;
function bar() {
foo = 10;
return;
function foo() {}
}
bar();
alert(foo);//答案:1
--------------------------------------------------------
console.log(a);//是一個函式
var a = 3;
function a(){}
console.log(a); //3
--------------------------------------------------------
//考點:對arguments的操作
function foo(a) {
arguments[0] = 2;
alert(a);//答案:2,因為:a、arguments是對實參的訪問,b、通過arguments[i]可以修改指定實參的值
}
foo(1);
--------------------------------------------------------
function foo(a) {
alert(arguments.length);//答案:3,因為arguments是對實參的訪問
}
foo(1, 2, 3);
--------------------------------------------------------
bar();//報錯
var foo = function bar(name) {
console.log("hello"+name);
console.log(bar);
};
//alert(typeof bar);
foo("world");//"hello"
console.log(bar);//undefined
console.log(foo.toString());
bar();//報錯
--------------------------------------------------------
function test(){
console.log("test函式");
}
setTimeout(function(){
console.log("定時器回撥函式");
}, 0)
test();
function foo(){
var name="hello";
}
--------------------------------------------------------
19 已知陣列var stringArray = [“This”, “is”, “Baidu”, “Campus”],Alert出”This is Baidu Campus”。
var stringArray = ["This", "is", "Baidu", "Campus"];
console.log(stringArray.join(" "))
答案:alert(stringArray.join(" "))
20 輸出今天的日期,以YYYY-MM-DD的方式,比如今天是2014年9月26日,則輸出2014-09-26
var d = new Date();
// 獲取年,getFullYear()返回4位的數字
var year = d.getFullYear();
// 獲取月,月份比較特殊,0是1月,11是12月
var month = d.getMonth() + 1;
// 變成兩位
month = month < 10 ? '0' + month : month;
// 獲取日
var day = d.getDate();
day = day < 10 ? '0' + day : day;
alert(year + '-' + month + '-' + day);
21 為了保證頁面輸出安全,我們經常需要對一些特殊的字元進行轉義,請寫一個函式escapeHtml,將<, >, &, “進行轉義
function escapeHtml(str) {
return str.replace(/[<>”&]/g, function(match) {
switch (match) {
case “<”:
return “<”;
case “>”:
return “>”;
case “&”:
return “&”;
case “\””:
return “"”;
}
};
}
22 foo = foo||bar ,這行程式碼是什麼意思?為什麼要這樣寫?
答案:if(!foo) foo = bar; //如果foo存在,值不變,否則把bar的值賦給foo。
短路表示式:作為”&&”和”||”操作符的運算元表示式,這些表示式在進行求值時,只要最終的結果已經可以確定是真或假,求值過程便告終止,這稱之為短路求值。
23 用js實現隨機選取10–100之間的10個數字,存入一個數組,並排序。
var iArray = [];
funtion getRandom(istart, iend){
var iChoice = iend - istart +1;
return Math.floor(Math.random() * iChoice + istart);
}
for(var i=0; i<10; i++){
iArray.push(getRandom(10,100));
}
iArray.sort();
24 把兩個數組合並,並刪除第二個元素。
var array1 = ['a','b','c'];
var bArray = ['d','e','f'];
var cArray = array1.concat(bArray);
cArray.splice(1,1);
25 怎樣新增、移除、移動、複製、建立和查詢節點
1)建立新節點
createDocumentFragment() //建立一個DOM片段
createElement() //建立一個具體的元素
createTextNode() //建立一個文字節點
2)新增、移除、替換、插入
appendChild() //新增
removeChild() //移除
replaceChild() //替換
insertBefore() //插入
3)查詢
getElementsByTagName() //通過標籤名稱
getElementsByName() //通過元素的Name屬性的值
getElementById() //通過元素Id,唯一性
26 簡述建立函式的幾種方式
第一種(函式宣告):
function sum1(num1,num2){
return num1+num2;
}
第二種(函式表示式):
var sum2 = function(num1,num2){
return num1+num2;
}
第三種(函式物件方式):
var sum3 = new Function("num1","num2","return num1+num2");
27 documen.write和 innerHTML 的區別?
document.write 只能重繪整個頁面
innerHTML 可以重繪頁面的一部分
28介紹一下box-sizing屬性?
box-sizing屬性主要用來控制元素的盒模型的解析模式。預設值是content-box。
content-box:讓元素維持W3C的標準盒模型。元素的寬度/高度由border + padding + content的寬度/高度決定,設定width/height屬性指的是content部分的寬/高
border-box:讓元素維持IE傳統盒模型(IE6以下版本和IE6~7的怪異模式)。設定width/height屬性指的是border + padding + content
標準瀏覽器下,按照W3C規範對盒模型解析,一旦修改了元素的邊框或內距,就會影響元素的盒子尺寸,就不得不重新計算元素的盒子尺寸,從而影響整個頁面的佈局。
29 什麼是閉包?寫一個簡單的閉包?
閉包就是能夠讀取其他函式內部變數的函式。在本質上,閉包就是將函式內部和函式外部連線起來的一座橋樑。
function outer(){
var num = 1;
function inner(){
var n = 2;
alert(n + num);
}
return inner;
}
outer()();
30 常見 == 和 === 運算結果
console.log(NaN==NaN) // false
console.log(NaN===NaN) // false
console.log(!NaN) // true
console.log(undefined = undefined) // undefined
console.log(undefined == undefined) // true
console.log(undefined === undefined) // true
console.log(undefined == null) // true
console.log(undefined === null) // false
按位與 &
console.log(1&2) // 0 0001&0010 = 0000 0
console.log(2&2) // 2 0010&0010 = 0010 2
console.log(0&2) // 0 0000&0010 = 0000 0
console.log(2&3) // 2 0010&0011 = 0010 2
按位或 |
console.log(1|2) // 3 0001&0010 = 0011 3
console.log(2|2) // 2 0010|0010 = 0010 2
console.log(0|2) // 2 0000|0010 = 0010 2
console.log(2|3) // 3 0010|0011 = 0011 3
且 && (第一個量為true則輸出第二個量;第一個量為false 直接為false)
console.log(1&&2) // 2
console.log(0&&2) // 0
console.log("string"&&2) // 2
console.log(true&&2) // 2
console.log([1,2,3]&&2) // 2
console.log(2&&true) // true
console.log(2&&[1,2,3]) // [1,2,3]
console.log(2&&"string") // string
console.log(2&&1) // 1
或 || (第一個量為true輸出第一個量)
console.log(2||3) // 2
console.log(1||3) // 1
console.log("string"||3) // string
console.log(NaN||3) // 3
console.log(undefined||3) // 3
console.log(undefined||NaN) // NaN
31 請描述一下cookies,sessionStorage和localStorage的區別?
cookies相容所有的瀏覽器,Html5提供的storage儲存方式。
• Document.cookie
• Window.localstorage
• Window.sessionstorage
cookie資料始終在同源的http請求中攜帶(即使不需要),即cookie在瀏覽器和伺服器間來回傳遞。而sessionStorage和localStorage不會自動把資料發給伺服器,僅在本地儲存。
儲存大小限制也不同,cookie資料不能超過4k,同時因為每次http請求都會攜帶cookie,所以cookie只適合儲存很小的資料,如會話標識。sessionStorage和localStorage 雖然也有儲存大小的限制,但比cookie大得多,可以達到5M或更大。
資料有效期不同,sessionStorage:僅在當前瀏覽器視窗關閉前有效,自然也就不可能持久保持;localStorage:始終有效,視窗或瀏覽器關閉也一直儲存,因此用作持久資料;cookie只在設定的cookie過期時間之前一直有效,即使視窗或瀏覽器關閉。
作用域不同,sessionStorage不在不同的瀏覽器視窗中共享,即使是同一個頁面;localStorage 在所有同源視窗中都是共享的;cookie也是在所有同源視窗中都是共享的。
32 js取消事件冒泡
function stopBubble(e) {
// 如果提供了事件物件,則這是一個非IE瀏覽器
var ev = e||window.event;
if (ev.stopPropagation ) {
// 因此它支援W3C的stopPropagation()方法
ev.stopPropagation();
} else {
// 否則,我們需要使用IE的方式來取消事件冒泡
ev.cancelBubble = true;
}
}
33 js阻止事件預設行為
function stopDefault( e ) {
// 阻止預設瀏覽器動作(W3C)
var ev = e||window.event;
if (ev.preventDefault ) {
ev.preventDefault();
} else {
// IE中阻止函式器預設動作的方式
ev.returnValue = false;
}
return false;
}
34 js陣列元素新增、刪除、排序等方法有哪些?
1)Array.concat( ) //連線陣列
arrayObject.concat(arrayX,arrayX,......,arrayX)
arrayX //必需。該引數可以是具體的值,也可以是陣列物件。可以是任意多個。
var arr = [1,2];
arr2 = [4,5];
arr3 = arr.concat(arr2)
// arr3 = [1,2,4,5]
2)Array.join( ) //將陣列元素連線起來以構建一個字串
arrayObject.join(separator)
separator 可選。指定要使用的分隔符。如果省略該引數,則使用逗號作為分隔符。
var arr = [2,3,4,5];
var arr2 = arr.join()
// arr2 = "2,3,4,5"
var arr2 = arr.join(‘’)
// arr2 = "2345"
3)Array.length //陣列的大小
var arr = [2,3,4,5];
arr.length
// arr.length = 4
4)Array.pop( ) //刪除並返回陣列的最後一個元素
pop() 方法將刪除 arrayObject 的最後一個元素,把陣列長度減 1,並且返回它刪除的元素的值。如果陣列已經為空,則 pop() 不改變陣列,並返回 undefined 值。
var arr = [1,2,3,4];
var result = arr.pop();
console.log(result) // 4
console.log(arr) // [1,2,3]
5)Array.push( ) //給陣列新增元素
push() 方法可向陣列的末尾新增一個或多個元素,並返回新的長度。
arrayObject.push(newelement1,newelement2,....,newelementX)
newelement1 //必需。要新增到陣列的第一個元素。
newelement2 //可選。要新增到陣列的第二個元素。
newelementX可選。可新增多個元素。
var arr = [1,2,3,4];
var result = arr.push(5);
console.log(result);// 5
console.log(arr) // [1,2,3,4,5]
6)Array.reverse( ) //顛倒陣列中元素的順序
該方法會改變原來的陣列,而不會建立新的陣列
var arr = [1,2,3,4];
var result = arr.reverse();
console.log(result); // [4, 3, 2, 1]
console.log(arr); // [4, 3, 2, 1]
7)Array.shift( ) //將第一個元素移出陣列
shift() 方法用於把陣列的第一個元素從其中刪除,並返回第一個元素的值
var arr = [1,2,3,4];
var result = arr.shift();
console.log(result) // 1
console.log(arr) // [2, 3, 4]
8)Array.unshift( ) //在陣列頭部插入一個元素,返回陣列長度
unshift() 方法可向陣列的開頭新增一個或更多元素,並返回新的長度
arrayObject.unshift(newelement1,newelement2,....,newelementX)
newelement1 //必需。向陣列新增的第一個元素
newelement2 //可選。向陣列新增的第二個元素
newelementX //可選。可新增若干個元素
var arr = [1,2,3,4];
var result = arr.unshift(0);
console.log(result)// 5
console.log(arr) // [0, 1, 2, 3, 4]
9)Array.sort( ) //對陣列元素進行排序
var arr = [2,4,7,1,0,9];
var result = arr.sort()
console.log(result)// [0, 1, 2, 4, 7, 9]
console.log(arr)// [0, 1, 2, 4, 7, 9]
若需要規定排序方式 則需傳入一個排序函式
arrayObject.sort(sortby)
sortby // 可選。規定排序順序。必須是函式。
// 從小到大排序
function sortby(a,b){
return a - b
}
Exp:
function sortNumber(a,b){
return a - b
}
arr = [2,7,3,1,9,7,0];
arr.sort(sortNumber) // 結果 [0, 1, 2, 3, 7, 7, 9]
// 從大到小排序
function sortby(a,b){
return b - a
}
Exp:
function sortNumber(a,b){
return b - a
}
arr = [2,7,3,1,9,7,0];
arr.sort(sortNumber) // 結果 [9, 7, 7, 3, 2, 1, 0]
10)Array.splice(開始索引號,長度) //插入、刪除或替換陣列的元素
arrayObject.splice(index,howmany,item1,.....,itemX)
index //必需。整數,規定新增/刪除專案的位置,使用負數可從陣列結尾處規定位置。
Howmany //必需。要刪除的專案數量。如果設定為 0,則不會刪除專案。
item1, ..., itemX //可選。向陣列新增的新專案。
// 刪除 並返回刪除的結果
var arr = [1,2,3,4];
var result = arr.splice(2,9)
console.log(result)// [3, 4]
console.log(arr)// [1, 2]
// 從指定位置刪除並開始新增專案
var arr = [1,2,3,4];
var result = arr.splice(2,0,5,6)
console.log(result)// [ ]
console.log(arr)// [1, 2, 5, 6, 3, 4]
11)Array.toLocaleString( ) //把陣列轉換成本地字串
把陣列轉換為本地字串。
var arr = [1,2,3,4];
var result = arr.toLocaleString();
console.log(arr);// [1, 2, 3, 4]
console.log(result)// 1,2,3,4
12)Array.toString( ) //將陣列轉換成一個字串
var arr = [1,2,3,4];
var result = arr.toString();
console.log(arr); // [1, 2, 3, 4]
console.log(result) // 1,2,3,4
toString() 方法可把一個邏輯值轉換為字串,並返回結果。
var boo = new Boolean(true);
var result = boo.toString();
console.log(boo); // Boolean {true}
console.log(result); // "true"
13)Array.slice( ) //返回陣列的一部分
slice() 方法可從已有的陣列中返回選定的元素。
arrayObject.slice(start,end)
start //必需。規定從何處開始選取。如果是負數,那麼它規定從陣列尾部開始算起的位置。也就是說,-1 指最後一個元素,-2 指倒數第二個元素,以此類推。
End //可選。規定從何處結束選取。該引數是陣列片斷結束處的陣列下標。如果沒有指定該引數,那麼切分的陣列包含從 start 到陣列結束的所有元素。如果這個引數是負數,那麼它規定的是從陣列尾部開始算起的元素。
返回一個新的陣列,包含從 start 到 end (不包括該元素)的 arrayObject 中的元素。
var arr = [2,3,5,6,9,0,3,4];
var result = arr.slice(2,5);
console.log(arr); // [2, 3, 5, 6, 9, 0, 3, 4]
console.log(result) // [5, 6, 9]
35 識別符號變數定義規則
識別符號是一個名字。在javascript中,識別符號用來對變數和函式進行命名,或者用作javascript程式碼中某些迴圈語句中的跳轉位置標記。
Js中識別符號必須以字母、下劃線(_)或者美元($)開始。後續字元可以是字母、數字、下劃線或美元符(數字不允許作為首字母出現),另外關鍵字不允許做識別符號。
36 cookies,sessionStorage和localStorage的區別
共同點:都是儲存在瀏覽器端,且同源的。
區別:
1)cookie資料始終在同源的http請求中攜帶(即使不需要),即cookie在瀏覽器和伺服器間來回傳遞。
2)而sessionStorage和localStorage不會自動把資料發給伺服器,僅在本地儲存。
3)cookie資料還有路徑(path)的概念,可以限制cookie只屬於某個路徑下。儲存大小限制也不同,cookie資料不能超過4k,同時因為每次http請求都會攜帶cookie,所以cookie只適合儲存很小的資料,如會話標識。sessionStorage和localStorage 雖然也有儲存大小的限制,但比cookie大得多,可以達到5M或更大。
4)資料有效期不同,sessionStorage:僅在當前瀏覽器視窗關閉前有效,自然也就不可能持久保持;localStorage:始終有效,視窗或瀏覽器關閉也一直儲存,因此用作持久資料;cookie只在設定的cookie過期時間之前一直有效,即使視窗或瀏覽器關閉。
5)作用域不同,sessionStorage不在不同的瀏覽器視窗中共享,即使是同一個頁面;localStorage 在所有同源視窗中都是共享的;cookie也是在所有同源視窗中都是共享的。Web Storage 支援事件通知機制,可以將資料更新的通知傳送給監聽者。Web Storage 的 api 介面使用更方便。
sessionStorage用於本地儲存一個會話(session)中的資料,這些資料只有在同一個會話中的頁面才能訪問並且當會話結束後資料也隨之銷燬。
因此sessionStorage不是一種持久化的本地儲存,僅僅是會話級別的儲存。
而localStorage用於持久化的本地儲存,除非主動刪除資料,否則資料是永遠不會過期的。
web storage和cookie的區別
Web Storage的概念和cookie相似,區別是它是為了更大容量儲存設計的。Cookie的大小是受限的,並且每次你請求一個新的頁面的時候Cookie都會被髮送過去,這樣無形中浪費了頻寬,另外cookie還需要指定作用域,不可以跨域呼叫。
除此之外,Web Storage擁有setItem,getItem,removeItem,clear等方法,不像cookie需要前端開發者自己封裝setCookie,getCookie。
但是Cookie也是不可以或缺的:Cookie的作用是與伺服器進行互動,作為HTTP規範的一部分而存在 ,而Web Storage僅僅是為了在本地“儲存”資料而生。
Cookies:伺服器和客戶端都可以訪問;大小隻有4KB左右;有有效期,過期後將會刪除;
本地儲存:只有本地瀏覽器端可訪問資料,伺服器不能訪問本地儲存直到故意通過POST或者GET的通道傳送到伺服器;每個域5MB;沒有過期資料,它將保留知道使用者從瀏覽器清除或者使用Javascript程式碼移除
37 JavaScript的資料型別都有什麼?
基本資料型別:String,boolean,Number,Undefined, Null
引用資料型別:Object(Array,Date,RegExp,Function)
如何判斷某變數是否為陣列資料型別?
1)方法一.判斷其是否具有“陣列性質”,如slice()方法。可自己給該變數定義slice方法,故有時會失效
2)方法二.obj instanceof Array 在某些IE版本中不正確
3)方法三.方法一二皆有漏洞,在ECMA Script5中定義了新方法Array.isArray(), 保證其相容性,最好的方法如下
if(typeof Array.isArray==="undefined")
{
Array.isArray = function(arg){
return Object.prototype.toString.call(arg)==="[object Array]"
};
}
38 什麼是Ajax和JSON,它們的優缺點
Ajax是非同步JavaScript和XML,用於在Web頁面中實現非同步資料互動。
優點:
1)可以使得頁面不過載全部內容的情況下載入區域性內容,降低資料傳輸量
2)避免使用者不斷重新整理或者跳轉頁面,提高使用者體驗
缺點:
1)對搜尋引擎不友好
2)要實現ajax下的前後退功能成本較大
3)可能造成請求數的增加
4)跨域問題限制
JSON是一種輕量級的資料交換格式,ECMA的一個子集
優點:輕量級、易於人的閱讀和編寫,便於機器(JavaScript)解析,支援複合資料型別(陣列、物件、字串、數字)
39 將字串”<tr><td>{$id}</td><td>{$name}</td></tr>”中的{$id}替換成10,{$name}替換成Tony (使用正則表示式)
”<tr><td>{$id}</td><td>{$id}_{$name}</td></tr>”.replace(/{\$id}/g, ’10’).replace(/{\$name}/g, ‘Tony’);
40 為了保證頁面輸出安全,我們經常需要對一些特殊的字元進行轉義,請寫一個函式escapeHtml,將<, >, &, “進行轉義
function escapeHtml(str) {
return str.replace(/[<>”&]/g, function (match) {
switch (match) {
case“ <”:
return“ <”;
case“ >”:
return“ >”;
case“ &”:
return“ &”;
case“\”” :
return“ "”;
}
});
}
41 對BFC規範的理解?
BFC,塊級格式化上下文,一個建立了新的BFC的盒子是獨立佈局的,盒子裡面的子元素的樣式不會影響到外面的元素。在同一個BFC中的兩個毗鄰的塊級盒在垂直方向(和佈局方向有關係)的margin會發生摺疊。
(W3C CSS 2.1 規範中的一個概念,它決定了元素如何對其內容進行佈局,以及與其他元素的關係和相互作用。
42 Doctype作用? 嚴格模式與混雜模式如何區分?它們有何意義?
1)、<!DOCTYPE> 宣告位於文件中的最前面,處於 <html> 標籤之前。告知瀏覽器以何種模式來渲染文件。
2)、嚴格模式的排版和 JS 運作模式是 以該瀏覽器支援的最高標準執行。
3)、在混雜模式中,頁面以寬鬆的向後相容的方式顯示。模擬老式瀏覽器的行為以防止站點無法工作。
4)、DOCTYPE不存在或格式不正確會導致文件以混雜模式呈現。
43你知道多少種Doctype文件型別?
該標籤可宣告三種 DTD 型別,分別表示嚴格版本、過渡版本以及基於框架的 HTML 文件。
HTML 4.01 規定了三種文件型別:Strict、Transitional 以及 Frameset。
XHTML 1.0 規定了三種 XML 文件型別:Strict、Transitional 以及 Fra