強烈推薦最新 js 面試題
JavaScript面試題集錦
1.js基礎
1.eval是做什麼的?
它的功能是把對應的字串解析成JS程式碼並執行;
應該避免使用eval,不安全,非常耗效能(2次,一次解析成js語句,一次執行)。
由JSON字串轉換為JSON物件的時候可以用eval,var obj =eval(’(’+ str +’)’);
2.什麼是window物件? 什麼是document物件?
window物件是指瀏覽器開啟的視窗。
document物件是Document物件(HTML 文件物件)的一個只讀引用,window物件的一個屬性。
3.null,undefined 的區別?
null 表示一個物件是“沒有值”的值,也就是值為“空”;
undefined 表示一個變數聲明瞭沒有初始化(賦值);
undefined不是一個有效的JSON,而null是;
undefined的型別(typeof)是undefined;
null的型別(typeof)是object;
Javascript將未賦值的變數預設值設為undefined;
Javascript從來不會將變數設為null。它是用來讓程式設計師表明某個用var宣告的變數時沒有值的。
typeof undefined
//“undefined”
undefined :是一個表示"無"的原始值或者說表示"缺少值",就是此處應該有一個值,但是還沒有定義。當嘗試讀取時會返回 undefined;
例如變數被聲明瞭,但沒有賦值時,就等於undefined
typeof null
//“object”
null : 是一個物件(空物件, 沒有任何屬性和方法);
例如作為函式的引數,表示該函式的引數不是物件;
注意:
在驗證null時,一定要使用 === ,因為 == 無法分別 null 和 undefined
null == undefined // true
null === undefined // false
再來一個例子:
null
Q:有張三這個人麼?
A:有!
Q:張三有房子麼?
A:沒有!
undefined
Q:有張三這個人麼?
A:有!
Q: 張三有多少歲?
A: 不知道(沒有被告訴)
- [“1”, “2”, “3”].map(parseInt) 答案是多少?
parseInt() 函式能解析一個字串,並返回一個整數,需要兩個引數 (val, radix),
其中 radix 表示要解析的數字的基數。【該值介於 2 ~ 36 之間,並且字串中的數字不能大於radix才能正確返回數字結果值】;
但此處 map 傳了 3 個 (element, index, array),我們重寫parseInt函式測試一下是否符合上面的規則。
function parseInt(str, radix) {
return str+’-’+radix;
};
var a=[“1”, “2”, “3”];
a.map(parseInt); // [“1-0”, “2-1”, “3-2”] 不能大於radix
因為二進位制裡面,沒有數字3,導致出現超範圍的radix賦值和不合法的進位制解析,才會返回NaN
所以[“1”, “2”, “3”].map(parseInt) 答案也就是:[1, NaN, NaN]
5.事件是?IE與火狐的事件機制有什麼區別?如何阻止冒泡?
- 我們在網頁中的某個操作(有的操作對應多個事件)。例如:當我們點選一個按鈕就會產生一個事件。是可以被 JavaScript 偵測到的行為。
- 事件處理機制:I.E.是事件冒泡、Firefox同時支援兩種事件模型,也就是:捕獲型事件和冒泡型事件;
- ev.stopPropagation();(舊ie的方法 ev.cancelBubble = true;)
6.javascript 程式碼中的"use strict";是什麼意思 ? 使用它區別是什麼?
use strict是一種ECMAscript 5 新增的(嚴格)執行模式,這種模式使得 Javascript 在更嚴格的條件下執行,
使JS編碼更加規範化的模式,消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行為。
預設支援的糟糕特性都會被禁用,比如不能用with,也不能在意外的情況下給全域性變數賦值;
全域性變數的顯示宣告,函式必須宣告在頂層,不允許在非函式程式碼塊內宣告函式,arguments.callee也不允許使用;
消除程式碼執行的一些不安全之處,保證程式碼執行的安全,限制函式中的arguments修改,嚴格模式下的eval函式的行為和非嚴格模式的也不相同;
提高編譯器效率,增加執行速度;
為未來新版本的Javascript標準化做鋪墊。
7.Javascript中,有一個函式,執行時物件查詢時,永遠不會去查詢原型,這個函式是?
hasOwnProperty
javaScript中hasOwnProperty函式方法是返回一個布林值,指出一個物件是否具有指定名稱的屬性。此方法無法檢查該物件的原型鏈中是否具有該屬性;該屬性必須是物件本身的一個成員。
使用方法:
object.hasOwnProperty(proName)
其中引數object是必選項。一個物件的例項。
proName是必選項。一個屬性名稱的字串值。
如果 object 具有指定名稱的屬性,那麼JavaScript中hasOwnProperty函式方法返回 true,反之則返回 false。
8.JSON 的瞭解?
JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。
它是基於JavaScript的一個子集。資料格式簡單, 易於讀寫, 佔用頻寬小
如:{“age”:“12”, “name”:“back”}
JSON字串轉換為JSON物件:
var obj =eval(’(’+ str +’)’);
var obj = str.parseJSON();
var obj = JSON.parse(str);
JSON物件轉換為JSON字串:
var last=obj.toJSONString();
var last=JSON.stringify(obj);
9.js延遲載入的方式有哪些?
1.
有了defer屬性,載入後續文件的過程和js指令碼的載入(此時僅載入不執行)是並行進行的(非同步),js指令碼的執行需要等到文件所有元素解析完成之後,DOMContentLoaded事件觸發執行之前
defer和async、動態建立DOM方式(用得最多)、按需非同步載入js
10.如何判斷當前指令碼執行在瀏覽器還是node環境中?(阿里)
this === window ? ‘browser’ : ‘node’;
通過判斷Global物件是否為window,如果不為window,當前指令碼沒有執行在瀏覽器中
11.javascript的typeof返回哪些資料型別
alert(typeof [1, 2]); //object
alert(typeof ‘leipeng’); //string
var i = true;
alert(typeof i); //boolean
alert(typeof 1); //number
var a;
alert(typeof a); //undefined
function a(){;};
alert(typeof a) //function
12.例舉3種強制型別轉換和2種隱式型別轉換?
強制(parseInt(),parseFloat(),Number())
隱式(== ,!=)
13.split() 、join() 的區別
前者是切割成陣列的形式,後者是將陣列轉換成字串
14.陣列方法pop() push() unshift() shift()
-
push()尾部新增 pop()尾部刪除
-
unshift()頭部新增 shift()頭部刪除
-
map() : 遍歷陣列中的元素, 返回一個新陣列(包含回撥函式返回的資料)
-
filter():遍歷陣列中的元素, 返回一個新陣列(包含回撥函式返回true的元素)
15.事件繫結和普通事件有什麼區別 -
普通新增事件的方法:
var btn = document.getElementById(“hello”);
btn.onclick = function(){
alert(1);
}
btn.onclick = function(){
alert(2);
}
執行上面的程式碼只會alert 2 -
事件繫結方式新增事件:
var btn = document.getElementById(“hello”);
btn.addEventListener(“click”,function(){
alert(1);
},false);
btn.addEventListener(“click”,function(){
alert(2);
},false);
執行上面的程式碼會先alert 1 再 alert 2 -
普通新增事件的方法不支援新增多個事件,最下面的事件會覆蓋上面的,而事件繫結(addEventListener)方式新增事件可以新增多個。
-
addEventListener不相容低版本IE
-
普通事件無法取消
-
addEventLisntener還支援事件冒泡+事件捕獲
- IE和谷歌中DOM事件流的區別
1.執行順序不一樣、
2.引數不一樣
3.事件加不加on
4.this指向問題
1.執行的順序不一樣
冒泡型事件模型: button->div->body (IE事件流)
捕獲型事件模型: body->div->button (Netscape事件流)
DOM事件模型: body->div->button->button->div->body (先捕獲後冒泡)
回到頂部
2.事件偵聽函式的區別
IE使用:
[Object].attachEvent(“name_of_event_handler”, fnHandler); //繫結函式
[Object].detachEvent(“name_of_event_handler”, fnHandler); //移除繫結
DOM使用:
[Object].addEventListener(“name_of_event”, fnHandler, bCapture); //繫結函式
[Object].removeEventListener(“name_of_event”, fnHandler, bCapture); //移除繫結
回到頂部
3、引數不一樣和this指向不一樣
IE下注冊多個事件監聽器與移除監聽器方法
註冊多個事件監聽器
element.attachEvent(‘onclick’, observer);
attachEvent接受兩個引數。
第一個引數是事件名稱
第二個引數observer是回撥處理函式。
這裡得說明一下,有個經常會出錯的地方,IE下利用attachEvent註冊的處理函式呼叫時this指向不再是先前註冊事件的元素,這時的this為window物件了,筆者很奇怪IE為什麼要這麼做,完全看不出好處所在。
移除先前註冊的事件的監聽器
element.detachEvent(‘onclick’, observer);
DOM標準下注冊多個事件監聽器與移除監聽器方法
註冊多個事件監聽器
實現DOM標準的瀏覽器與IE瀏覽器中註冊元素事件監聽器方式有所不同,它通過元素的addEventListener方法註冊,該方法既支援註冊冒泡型事件處理,又支援捕獲型事件處理。
element.addEventListener(‘click’, observer, useCapture);
addEventListener方法接受三個引數。
第一個引數是事件名稱,值得注意的是,這裡事件名稱與IE的不同,事件名稱是沒’on’開頭的;
第二個引數observer是回撥處理函式;
第三個引數註明該處理回撥函式是在事件傳遞過程中的捕獲階段被呼叫還是冒泡階段被呼叫
它可以在一個DOM元素上繫結多個事件處理器,並且在處理函式內部,this關鍵字仍然指向被繫結的DOM元素,另外處理函式引數列表的第一個位置傳遞事件event物件。
移除先前註冊的事件的監聽器
element.removeEventListener(‘click’, observer, useCapture);
17.IE和標準下有哪些相容性的寫法
var ev = ev || window.event
document.documentElement.clientWidth || document.body.clientWidth
var target = ev.srcElement||ev.target
18.如何阻止事件冒泡和事件預設行為
//阻止事件冒泡
if(typeof ev.stopPropagation==‘function’) { //標準的
ev.stopPropagation();
} else { //非標準IE
window.event.cancelBubble = true;
}
//阻止事件預設行為
return false
19. window.onload 和document ready的區別
window.onload 是在dom文件樹載入完和所有檔案載入完之後執行一個函式 document.ready原生中沒有這個方法,jquery中有 $().ready(function),在dom文件樹加 載完之後執行一個函式(注意,這裡面的文件樹載入完不代表全部檔案載入完)。
(document).ready可以出現多次
20.””和“=”的不同
前者會自動轉換型別
後者不會
21.JavaScript是一門什麼樣的語言,它有哪些特點?
javaScript一種直譯式指令碼語言,是一種動態型別、弱型別、基於原型的語言,內建支援型別。它的直譯器被稱為JavaScript引擎,為瀏覽器的一部分,廣泛用於客戶端的指令碼語言,最早是在HTML網頁上使用,用來給HTML網頁增加動態功能。JavaScript兼容於ECMA標準,因此也稱為ECMAScript。
基本特點
- 是一種解釋性指令碼語言(程式碼不進行預編譯)。
- 主要用來向HTML(標準通用標記語言下的一個應用)頁面新增互動行為。
- 可以直接嵌入HTML頁面,但寫成單獨的js檔案有利於結構和行為的分離。
跨平臺特性,在絕大多數瀏覽器的支援下,可以在多種平臺下執行(如Windows、Linux、Mac、Android、iOS等)。
22.JavaScript的資料型別都有什麼?
基本資料型別:String,boolean,Number,Undefined, Null
引用資料型別:Object, Array, Function
那麼問題來了,如何判斷某變數是否為陣列資料型別?
方法一.判斷其是否具有“陣列性質”,如slice()方法。可自己給該變數定義slice方法, 故有時會失效
方法二.obj instanceof Array 在某些IE版本中不正確
方法三.方法一二皆有漏洞,在ECMA Script5中定義了新方法Array.isArray(), 保證其相容 性,最好的方法如下:
if(typeof Array.isArray===“undefined”){
Array.isArray = function(arg){
return Object.prototype.toString.call(arg)==="[object Array]"
};
}
23.當一個DOM節點被點選時候,我們希望能夠執行一個函式,應該怎麼做?
直接在DOM裡繫結事件:
在JS裡通過onclick繫結:xxx.onclick = test
通過事件新增進行繫結:addEventListener(xxx, ‘click’, test)
那麼問題來了,Javascript的事件流模型都有什麼?
“事件冒泡”:事件開始由最具體的元素接受,然後逐級向上傳播
“事件捕捉”:事件由最不具體的節點先接收,然後逐級向下,一直到最具體的
“DOM事件流”:三個階段:事件捕捉,目標階段,事件冒泡
24.看下列程式碼輸出為何?解釋原因。
var a;
alert(typeof a); // undefined
alert(b); // 報錯
解釋:Undefined是一個只有一個值的資料型別,這個值就是“undefined”,在使用var 宣告變數但並未對其賦值進行初始化時,這個變數的值就是undefined。而b由於未聲 明將報錯。注意未申明的變數和聲明瞭未賦值的是不一樣的。
25.看下列程式碼,輸出什麼?解釋原因。
var undefined;
undefined == null; // true
1 == true; // true
2 == true; // false
0 == false; // true
0 == ‘’; // true
NaN == NaN; // false
[] == false; // true
[] == ![]; // true
undefined與null相等,但不恆等(=)
一個是number一個是string時,會嘗試將string轉換為number
嘗試將boolean轉換為number,0或1
嘗試將Object轉換成number或string,取決於另外一個對比量的型別
所以,對於0、空字串的判斷,建議使用“=”。“===”會先判斷兩邊的值型別, 型別不匹配時為false。
那麼問題來了,看下面的程式碼,輸出什麼,foo的值為什麼?
var foo = “11”+2-“1”;
console.log(foo);
console.log(typeof foo);
執行完後foo的值為111,foo的型別為String。
-
已知陣列 var stringArr = [“This”,“ is”, “Baidu”, “Campus” ], Alert出 “This is Baidu Campus”;
alert(stringArray.join(“”)) -
已知有字串foo=”get-element-by-id”,寫一個function將其轉化成駝峰表示法”getElementById”
function combo(msg){
var arr=msg.split("-");
for(var i=1;i<arr.length;i++){
arr[i]=arr[i].charAt(0).toUpperCase()+arr[i]
.substr(1,arr[i].length-1);
}
msg=arr.join("");
return msg;
} -
輸出今天的日期,以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;
var d = new Date();
// 獲取年,getFullYear()返回4位的數字
var year = d.getFullYear();
// 獲取月,月份比較特殊,0是1月,11是12月
var month = d.getMonth() + 1; -
將字串”{KaTeX parse error: Expected 'EOF', got '}' at position 3: id}̲</td><td>{name}”中的{KaTeX parse error: Expected 'EOF', got '}' at position 3: id}̲替換成10,{name}替換成Tony (使用正則表示式)
“{KaTeX parse error: Expected 'EOF', got '}' at position 3: id}̲</td><td>{id}_{$name}”.replace(/{$id}/g, ‘10’).replace(/{$name}/g, ‘Tony’); -
為了保證頁面輸出安全,我們經常需要對一些特殊的字元進行轉義,請寫一個函式escapeHtml,將<, >, &, “進行轉義
function escapeHtml(str) {
return str.replace(/[<>”&]/g, function(match) {
switch (match) {
case “<”:
return “<”;
case “>”:
return “>”;
case “&”:
return “&”;
case “\””:
return “"”;
}
});
} -
foo = foo||bar ,這行程式碼是什麼意思?為什麼要這樣寫?
如果foo存在,值不變,否則把bar的值賦給foo。
短路表示式:作為”&&”和”||”操作符的運算元表示式,這些表示式在進行求值時, 只要最終的結果已經可以確定是真或假,求值過程便告終止,這稱之為短路求值。 -
看下列程式碼,將會輸出什麼?(變數宣告提升)
var foo = 1;
(function(){
console.log(foo);
var foo = 2;
console.log(foo);
})()
答案:輸出undefined 和 2。上面程式碼相當於:
var foo = 1;
(function(){
var foo;
console.log(foo); //undefined
foo = 2;
console.log(foo); // 2;
})()
函式宣告與變數宣告會被JavaScript引擎隱式地提升到當前作用域的頂部,但是隻提升名稱不會提升賦值部分。 -
用js實現隨機選取10–100之間的10個數字,存入一個數組,並排序。
function randomNub(aArray, len, min, max) {
if (len >= (max - min)) {
return ‘超過’ + min + ‘-’ + max + ‘之間的個數範圍’ + (max - min - 1) + ‘個的總數’;
}
if (aArray.length >= len) {
aArray.sort(function(a, b) {
return a - b
});
return aArray;
}
var nowNub = parseInt(Math.random() * (max - min - 1)) + (min + 1);
for (var j = 0; j < aArray.length; j++) {
if (nowNub == aArray[j]) {
randomNub(aArray, len, min, max);
return;
}
}
aArray.push(nowNub);
randomNub(aArray, len, min, max);
return aArray;var arr=[]; randomNub(arr,10,10,100);
34.把兩個數組合並,並刪除第二個元素。
var array1 = [‘a’,‘b’,‘c’];
var bArray = [‘d’,‘e’,‘f’];
var cArray = array1.concat(bArray);
cArray.splice(1,1);
35.有這樣一個URL:http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e,請寫一段JS程式提取URL中的各個GET引數(引數名和引數個數不確定),將其按key-value形式返回到一個json結構中,如{a:’1′, b:’2′, c:”, d:’xxx’, e:undefined}。
function serilizeUrl(url) {
var urlObject = {};
if (/?/.test(url)) {
var urlString = url.substring(url.indexOf("?") + 1);
var urlArray = urlString.split("&");
for (var i = 0, len = urlArray.length; i < len; i++) {
var urlItem = urlArray[i];
var item = urlItem.split("=");
urlObject[item[0]] = item[1];
}
return urlObject;
}
return null;
}
36.正則表示式建構函式var reg=new RegExp(“xxx”)與正則表達字面量var reg=//有什麼不同?匹配郵箱的正則表示式?
當使用RegExp()建構函式的時候,不僅需要轉義引號(即\”表示”),並且還需要雙反斜槓(即\表示一個\)。使用正則表達字面量的效率更高。
郵箱的正則匹配:
var regMail = /^([a-zA-Z0-9_-])[email protected]([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})KaTeX parse error: Expected group after '^' at position 129: … this.replace(/^̲\s+/, "").repla…/,"");
}
}
//測試
var str = " \t\n test string “.trim();
alert(str == “test string”); // alerts “true”
38.以下兩個變數a和b,a+b的哪個結果是NaN?
A、var a=undefined; b=NaN
B、var a= ‘123’; b=NaN
C、var a =undefined , b =NaN
D、var a=NaN , b=‘undefined’
39.下面的JavaScript語句中,()實現檢索當前頁面中的表單元素中的所有文字框,並將它們全部清空
A. for(vari=0;i< form1.elements.length;i++) {
if(form1.elements.type==”text”)
form1.elements.value=””;}
B. for(vari=0;i<document.forms.length;i++) {
if(forms[0].elements.type==”text”)
forms[0].elements.value=”";
}
C. if(document.form.elements.type==”text”)
form.elements.value=”";
D. for(vari=0;i<document.forms.length; i++){
for(var j=0;j<document.forms.elements.length; j++){
if(document.forms.elements[j].type==”text”)
document.forms.elements[j].value=”";
}
}
40.typeof運算子返回值中有一個跟javascript資料型別不一致,它是?如何判斷是不是陣列?
Array,Array.isArray(data)
41.寫出函式DateDemo的返回結果,系統時間假定為今天
function DateDemo(){
var d, s=“今天日期是:”;
d = new Date();
s += d.getMonth() +1+ “/”;
s += d.getDate() + “/”;
s += d.getFullYear();
return s;
}
結果:今天日期是:7/21/2016
42.寫出簡單描述html標籤(不帶屬性的開始標籤和結束標籤)的正則表示式,並將以下字串中的html標籤去除掉
var str = “
裡面的段落
”;<scripttype=”text/javascript”>
var reg = /</?\w+/?>/gi;
var str = “ 這裡是div
裡面的段落
”;alert(str.replace(reg,”"));
43.擷取字串abcdefg的efg
alert(‘abcdefg’.substring(4));
44.簡述建立函式的幾種方式
第一種(函式宣告):
function sum1(num1,num2){
return num1+num2;
}
第二種(函式表示式):
var sum2 = function(num1,num2){
return num1+num2;
}
第三種(函式物件方式):
var sum3 = new Function(“num1”,“num2”,“return num1+num2”);
45.Javascript如何實現繼承?
1.構造繼承法
2.原型繼承法
3.例項繼承法
46.Javascript建立物件的幾種方式?
1、var obj = {};(使用json建立物件)
如: obj.name = ‘張三’;
obj.action = function ()
{
alert(‘吃飯’);
};
2、var obj = new Object();(使用Object建立物件)
如: obj.name = ‘張三’;
obj.action = function ()
{
alert(‘吃飯’);
};
3、通過建構函式建立物件。
(1)、使用this關鍵字
如:var obj = function (){
this.name =‘張三’;
this.age = 19;
this.action = function ()
{
alert(‘吃飯’);
};
}
(2)、使用prototype關鍵字
如:function obj (){}
obj.prototype.name =‘張三’;
obj.prototype.action=function ()
{
alert(‘吃飯’);
};
4、使用內建物件建立物件。
如:var str = new String(“例項初始化String”);
var str1 = “直接賦值的String”;
var func = new Function(“x”,“alert(x)”);//示例初始化func
var obj = new Object();//示例初始化一個Object
47.js延遲載入的方式有哪些?
- defer和async
- 動態建立DOM方式(建立script,插入到DOM中,載入完畢後callBack)
- 按需非同步載入js
48.哪些操作會造成記憶體洩漏?
記憶體洩漏指任何物件在您不再擁有或需要它之後仍然存在。
垃圾回收器定期掃描物件,並計算引用了每個物件的其他物件的數量。如果一個物件的 引用數量為 0(沒有其他物件引用過該物件),或對該物件的惟一引用是迴圈的,那麼 該物件的記憶體即可回收。 - setTimeout 的第一個引數使用字串而非函式的話,會引發記憶體洩漏。
- 閉包
- 控制檯日誌
- 迴圈(在兩個物件彼此引用且彼此保留時,就會產生一個迴圈)
49.判斷一個字串中出現次數最多的字元,統計這個次數
var str = ‘asdfssaaasasasasaa’;
var json = {};
for (var i = 0; i < str.length; i++) {
if(!json[str.charAt(i)]){
json[str.charAt(i)] = 1;
}else{
json[str.charAt(i)]++;
}
};
var iMax = 0;
var iIndex = ‘’;
for(var i in json){
if(json[i]>iMax){
iMax = json[i];
iIndex = i;
}
}
alert(‘出現次數最多的是:’+iIndex+‘出現’+iMax+‘次’);
50.寫一個獲取非行間樣式的函式
function getStyle(obj,attr,value)
{
if(!value)
{
if(obj.currentStyle)
{
return obj.currentStyle(attr);
}
else{
obj.getComputedStyle(attr,false);
}
}
else
{
obj.style[attr] = value;
}
}
51.字串反轉,如將 ‘12345678’ 變成 ‘87654321’
//思路:先將字串轉換為陣列 split(),利用陣列的反序函式 reverse()顛倒陣列,再利 用 jion() 轉換為字串
var str = ‘12345678’;
str = str.split(’’).reverse().join(’’);
52.將數字 12345678 轉化成 RMB形式如: 12,345,678
//思路:先將數字轉為字元, str= str + ‘’ ;
//利用反轉函式,每三位字元加一個 ','最後一位不加; re()是自定義的反轉函式,最後再反轉回去!
function re(str) {
str += ‘’;
return str.split("").reverse().join("");
}
function toRMB(num) {
var tmp=’’;
for (var i = 1; i <= re(num).length; i++) {
tmp += re(num)[i - 1];
if (i % 3 == 0 && i != re(num).length) {
tmp += ‘,’;
}
}
return re(tmp);
}
53.生成5個不同的隨機數;
//思路:5個不同的數,每生成一次就和前面的所有數字相比較,如果有相同的,則放 棄當前生成的數字!
var num1 = [];
for(var i = 0; i < 5; i++){
num1[i] = Math.floor(Math.random()*10) + 1; //範圍是 [1, 10]
for(var j = 0; j < i; j++){
if(num1[i] == num1[j]){
i–;
}
}
}
54.去掉陣列中重複的數字
方法一:
//思路:每遍歷一次就和之前的所有做比較,不相等則放入新的陣列中!
//這裡用的原型個人做法;
Array.prototype.unique = function(){
var len = this.length,
newArr = [],
flag = 1;
for(var i = 0; i < len; i++, flag = 1){
for(var j = 0; j < i; j++){
if(this[i] == this[j]){
flag = 0; //找到相同的數字後,不執行新增資料
}
}
flag ? newArr.push(this[i]) : ‘’;
}
return newArr;
}
方法二:
var arr=[1,2,3,3,4,4,5,5,6,1,9,3,25,4];
Array.prototype.unique2 = function()
{
var n = []; //一個新的臨時陣列
for(var i = 0; i < this.length; i++) //遍歷當前陣列
{
//如果當前陣列的第i已經儲存進了臨時陣列,那麼跳過,
//否則把當前項push到臨時數組裡面
if (n.indexOf(this[i]) == -1) n.push(this[i]);
}
return n;
}
var newArr2=arr.unique2(arr);
alert(newArr2); //輸出1,2,3,4,5,6,9,25
55.階乘函式;
//原型方法
Number.prototype.N = function(){
var re = 1;
for(var i = 1; i <= this; i++){
re *= i;
}
return re;
}
var num = 5;
alert(num.N());
56.window.location.search() 返回的是什麼?
http://localhost:8080/xxx?ver=1.0&id=123
返回值:?ver=1.0&id=timlq 也就是問號後面的部分
57.window.location.reload() 作用?
新當前頁面。
58.javascript 中的垃圾回收機制?
在Javascript中,如果一個物件不再被引用,那麼這個物件就會被GC回收。如果兩個物件互相引用,而不再被第3者所引用,那麼這兩個互相引用的物件也會被回收。因為函式a被b引用,b又被a外的c引用,這就是為什麼函式a執行後不會被回收的原因。
59.精度問題: JS 精度不能精確到 0.1 所以 。。。。同時存在於值和差值中
var n = 0.3,m = 0.2, i = 0.2, j = 0.1;
alert((n - m) == (i - j)); //false
alert((n-m) == 0.1); //false
alert((i-j)==0.1); //true
60.計算字串位元組數:
new function(s){
if(!arguments.length||!s) return null;
if(""==s) return 0;
var l=0;
for(var i=0;i<s.length;i++){
if(s.charCodeAt(i)>255) l+=2; else l+=1; //charCodeAt()得到的是unCode碼
} //漢字的unCode碼大於 255bit 就是兩個位元組
alert(l);
}(“hello world!”);
61.匹配輸入的字元:第一個必須是字母或下劃線開頭,長度5-20
var reg = /1[a-zA-Z0-9_]{5,20}/,
name1 = ‘leipeng’,
name2 = ‘0leipeng’,
name3 = ‘你好leipeng’,
name4 = ‘hi’;
alert(reg.test(name1));
alert(reg.test(name2));
alert(reg.test(name3));
alert(reg.test(name4));
62.如何在HTML中新增事件,幾種方法?
1、標籤之中直接新增 onclick=“fun()”;
2、JS新增 Eobj.onclick = method;
3、繫結事件 IE: obj.attachEvent(‘onclick’, method);
FF: obj.addEventListener(‘click’, method, false);
63.你如何優化自己的程式碼?
程式碼重用
避免全域性變數(名稱空間,封閉空間,模組化mvc…)
拆分函式避免函式過於臃腫
註釋
64.使用js實現這樣的效果:在文字域裡輸入文字時,當按下enter鍵時不換行,而是替換成“{{enter}}”,(只需要考慮在行尾按下enter鍵的情況).
}
2.confirm
//彈出一個詢問框,有確定和取消按鈕
function firm() {
//利用對話方塊返回的值(true 或者 false)
if (confirm(“你確定提交嗎?”)) {
alert(“點選了確定”);
}
else {
alert(“點選了取消”);
}
}
3.prompt
//彈出一個輸入框,輸入一段文字,可以提交
function prom() {
var name = prompt(“請輸入您的名字”, “”); //將輸入的內容賦給變數 name ,
//這裡需要注意的是,prompt有兩個引數,前面是提示的話,後面是當對話框出來後,在對話方塊裡的預設值
if (name)//如果返回的有內容
{
alert("歡迎您:" + name)
}
}
70.主流瀏覽器核心
IE trident 火狐gecko 谷歌蘋果webkit Opera:Presto
71.JavaScript的迴圈語句有哪些?
for,for…in,while,do…while
72.閉包:下面這個ul,如何點選每一列的時候alert其index?
- 這是第一條
- 這是第二條
- 這是第三條
(2) 獲取事件源
IE用srcElement獲取事件源,而FF用target獲取事件源
(3) 新增,去除事件
IE:element.attachEvent(“onclick”, function) element.detachEvent(“onclick”, function)
FF:element.addEventListener(“click”, function, true) element.removeEventListener(“click”, function, true)
(4) 獲取標籤的自定義屬性
IE:div1.value或div1[“value”]
FF:可用div1.getAttribute(“value”)
74.在Javascript中什麼是偽陣列?如何將偽陣列轉化為標準陣列?
偽陣列(類陣列):無法直接呼叫陣列方法或期望length屬性有什麼特殊的行為,但仍可以對真正陣列遍歷方法來遍歷它們。典型的是函式的argument引數,還有像呼叫getElementsByTagName,document.childNodes之類的,它們都返回NodeList物件都屬於偽陣列。可以使用Array.prototype.slice.call(fakeArray)將陣列轉化為真正的Array物件。
75.請寫出一個程式,在頁面載入完成後動態建立一個form表單,並在裡面新增一個input物件並給它任意賦值後義post方式提交到:http://127.0.0.1/save.php
window.onload=function(){
var form=document.createElement(“form”);
form.setAttribute(“method”, “post”);
form.setAttribute(“action”, “http://127.0.0.1/save.php”);
var input=document.createElement("input");
form.appendChild(input);
document.body.appendChild(form);
input.value="cxc";
form.submit();//提交表單
}
76.用JavaScript實現升序排序。資料為23、45、18、37、92、13、24
//升序演算法
function sort(arr){
for (var i = 0; i <arr.length; i++) {
for (var j = 0; j <arr.length-i; j++) {
if(arr[j]>arr[j+1]){
var c=arr[j];//交換兩個變數的位置
arr[j]=arr[j+1];
arr[j+1]=c;
}
};
};
return arr.toString();
}
console.log(sort([23,45,18,37,92,13,24]));
77. 請說出下列輸出的結果
var User = {
count = 1,
getCount:function(){
return this.count;
}
}
console.log(User.getCount());
var func = User.getCount;
console.log(func());
1 undefined(因為是window物件執行了func函式);
78.用程式實現找到html中id名相同的元素?
81.請說出三種減低頁面載入時間的方法
1、壓縮css、js檔案
2、合併js、css檔案,減少http請求
3、外部js、css檔案放在最底下
4、減少dom操作,儘可能用變數替代不必要的dom操作
82.實現一個函式clone,可以對JavaScript中的5種主要的資料型別(包括Number、String、Object、Array、Boolean)進行值複製
// 方法一:
Object.prototype.clone = function(){
var o = this.constructor === Array ? [] : {};
for(var e in this){
o[e] = typeof this[e] === “object” ? this[e].clone() : this[e];
}
return o;
}
//方法二:
/**
* 克隆一個物件
* @param Obj
* @returns
*/
function clone(Obj) {
var buf;
if (Obj instanceof Array) {
buf = [];//建立一個空的陣列
var i = Obj.length;
while (i–) {
buf[i] = clone(Obj[i]);
}
return buf;
}else if (Obj instanceof Object){
buf = {};//建立一個空物件
for (var k in Obj) { //為這個物件新增新的屬性
buf[k] = clone(Obj[k]);
}
return buf;
}else{ //普通變數直接賦值
return Obj;
}
}
- 如何消除一個數組裡面重復的元素?
var arr=[1,2,3,3,4,4,5,5,6,1,9,3,25,4];
function deRepeat(){
var newArr=[];
var obj={};
var index=0;
var l=arr.length;
for(var i=0;i<l;i++){
if(obj[arr[i]]==undefined)
{
obj[arr[i]]=1;
newArr[index++]=arr[i];
}
else if(obj[arr[i]]==1)
continue;
}
return newArr;
}
var newArr2=deRepeat(arr);
alert(newArr2); //輸出1,2,3,4,5,6,9,25
84.定義一個log方法,讓它可以代理console.log的方法。
function log(msg) {
console.log(msg);
}
log(“hello world!”) // hello world!
如果要傳入多個引數呢?顯然上面的方法不能滿足要求,所以更好的方法是:
function log(){
console.log.apply(console, arguments);
};
到此,追問apply和call方法的異同。
對於apply和call兩者在作用上是相同的,即是呼叫一個物件的一個方法,以另一個物件替換當前物件。將一個函式的物件上下文從初始的上下文改變為由 thisObj 指定的新物件。
但兩者在引數上有區別的。對於第一個引數意義都一樣,但對第二個引數: apply傳入的是一個引數陣列,也就是將多個引數組合成為一個數組傳入,而call則作為call的引數傳入(從第二個引數開始)。如 func.call(func1,var1,var2,var3)對應的apply寫法為:func.apply(func1,[var1,var2,var3]) 。
85.原生JS的window.onload與Jquery的$(document).ready(function(){})有什麼不同?如何用原生JS實現Jq的ready方法?
window.onload()方法是必須等到頁面內包括圖片的所有元素載入完畢後才能執行。
$(document).ready()是DOM結構繪製完畢後就執行,不必等到載入完畢。
/*
- 傳遞函式給whenReady()
- 當文件解析完畢且為操作準備就緒時,函式作為document的方法呼叫
*/
var whenReady = (function() { //這個函式返回whenReady()函式
var funcs = []; //當獲得事件時,要執行的函式
var ready = false; //當觸發事件處理程式時,切換為true
//當文件就緒時,呼叫事件處理程式
function handler(e) {
if(ready) return; //確保事件處理程式只完整執行一次
//如果發生onreadystatechange事件,但其狀態不是complete的話,那麼文件尚未準備好
if(e.type === ‘onreadystatechange’ && document.readyState !== ‘complete’) {
return;
}
//執行所有註冊函式
//注意每次都要計算funcs.length
//以防這些函式的呼叫可能會導致註冊更多的函式
for(var i=0; i<funcs.length; i++) {
funcs[i].call(document);
}
//事件處理函式完整執行,切換ready狀態, 並移除所有函式
ready = true;
funcs = null;
}
//為接收到的任何事件註冊處理程式
if(document.addEventListener) {
document.addEventListener(‘DOMContentLoaded’, handler, false);
document.addEventListener(‘readystatechange’, handler, false); //IE9+
window.addEventListener(‘load’, handler, false);
}else if(document.attachEvent) {
document.attachEvent(‘onreadystatechange’, handler);
window.attachEvent(‘onload’, handler);
}
//返回whenReady()函式
return function whenReady(fn) {
if(ready) { fn.call(document); }
else { funcs.push(fn); }
}
})();
如果上述程式碼十分難懂,下面這個簡化版:
function ready(fn){
if(document.addEventListener) {//標準瀏覽器
document.addEventListener(‘DOMContentLoaded’, function() {
//登出事件, 避免反覆觸發
document.removeEventListener(‘DOMContentLoaded’,arguments.callee, false);
fn();//執行函式
}, false);
}else if(document.attachEvent) {//IE
document.attachEvent(‘onreadystatechange’, function() {
if(document.readyState == ‘complete’) {
document.detachEvent(‘onreadystatechange’, arguments.callee);
fn();//函式執行
}
});
}
};
- (設計題)想實現一個對頁面某個節點(比如:對某個div)的拖曳?如何做?(使用原生JS)
回答出概念即可,下面是幾個要點
給需要拖拽的節點繫結mousedown, mousemove, mouseup事件
mousedown事件觸發後,開始拖拽
mousemove時,需要通過event.clientX和clientY獲取拖拽位置,並實時更新位置
mouseup時,拖拽結束
需要注意瀏覽器邊界的情況 - 陣列和物件有哪些原生方法,列舉一下?
- Array.concat( ) 連線陣列
- Array.join( ) 將陣列元素連線起來以構建一個字串
- Array.length 陣列的大小
- Array.pop( ) 刪除並返回陣列的最後一個元素
- Array.push( ) 給陣列新增元素
- Array.reverse( ) 顛倒陣列中元素的順序
- Array.shift( ) 將元素移出陣列
- Array.slice( ) 返回陣列的一部分
- Array.sort( ) 對陣列元素進行排序
- Array.splice( ) 插入、刪除或替換陣列的元素
- Array.toLocaleString( ) 把陣列轉換成區域性字串
- Array.toString( ) 將陣列轉換成一個字串
- Array.unshift( ) 在陣列頭部插入一個元素
- Object.hasOwnProperty( ) 檢查屬性是否被繼承
- Object.isPrototypeOf( ) 一個物件是否是另一個物件的原型
- Object.propertyIsEnumerable( ) 是否可以通過for/in迴圈看到屬性
- Object.toLocaleString( ) 返回物件的本地字串表示
- Object.toString( ) 定義一個物件的字串表示
- Object.valueOf( ) 指定物件的原始值
88.JS 怎麼實現一個類。怎麼例項化這個類
嚴格來講js中並沒有類的概念,不過js中的函式可以作為建構函式來使用,通過new來例項化,其實函式本身也是一個物件。
89.在JS中有哪些會被隱式轉換為false
Undefined、null、關鍵字false、NaN、零、空字串
90.外部JS檔案出現中文字元,會出現什麼問題,怎麼解決?
會出現亂碼,加charset=”utf-8”;
91.寫一個通用的事件偵聽器函式
// event(事件)工具集,來源:https://github.com/markyun
markyun.Event = {
// 頁面載入完成後
readyEvent : function(fn) {
if (fn==null) {
fn=document;
}
var oldonload = window.onload;
if (typeof window.onload != ‘function’) {
window.onload = fn;
} else {
window.onload = function() {
oldonload();
fn();
};
}
},
// 視能力分別使用dom0||dom2||IE方式來繫結事件
// 引數:操作的元素,事件名稱 ,事件處理程式
addEvent : function(element, type, handler) {
if (element.addEventListener) {
//事件型別、需要執行的函式、是否捕捉
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent(‘on’ + type, function() {
handler.call(element);
});
} else {
element[‘on’ + type] = handler;
}
},
// 移除事件
removeEvent : function(element, type, handler) {
if (element.removeEnentListener) {
element.removeEnentListener(type, handler, false);
} else if (element.datachEvent) {
element.detachEvent(‘on’ + type, handler);
} else {
element[‘on’ + type] = null;
}
},
// 阻止事件 (主要是事件冒泡,因為IE不支援事件捕獲)
stopPropagation : function(ev) {
if (ev.stopPropagation) {
ev.stopPropagation();
} else {
ev.cancelBubble = true;
}
},
// 取消事件的預設行為
preventDefault : function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
// 獲取事件目標
getTarget : function(event) {
return event.target || event.srcElement;
},
// 獲取event物件的引用,取到事件的所有資訊,確保隨時能使用event;
getEvent : function(e) {
var ev = e || window.event;
if (!ev) {
var c = this.getEvent.caller;
while © {
ev = c.arguments[0];
if (ev && Event == ev.constructor) {
break;
}
c = c.caller;
}
}
return ev;
}
};
92.JSON 的瞭解
JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。它是基於JavaScript的 一個子集。資料格式簡單, 易於讀寫, 佔用頻寬小
{‘age’:‘12’, ‘name’:‘back’}
2.DOM相關
1.target與currentTarget區別
target在事件流的目標階段;currentTarget在事件流的捕獲,目標及冒泡階段。只有當事件流處在目標階段的時候,兩個的指向才是一樣的,而當處於捕獲和冒泡階段的時候,target指向被單擊的物件而currentTarget指向當前事件活動的物件(一般為父級)。
-
DOM的增刪改查操作?
(1)建立新節點
createDocumentFragment() //建立一個DOM片段
createElement() //建立一個具體的元素
createTextNode() //建立一個文字節點
(2)新增、移除、替換、插入
appendChild()
removeChild()
replaceChild()
insertBefore() //在已有的子節點前插入一個新的子節點
(3)查詢
getElementsByTagName() //通過標籤名稱
getElementsByName() //通過元素的Name屬性的值(IE容錯能力較強,會得到一個數組,其中包括id等於name值的)
getElementById() //通過元素Id,唯一性 -
請描述DOM事件流的過程?
DOM事件流包括三個階段:事件捕獲階段、處於目標階段、事件冒泡階段。首先發生的事件捕獲,為截獲事件提供機會。然後是實際的目標接受事件。最後一個階段是時間冒泡階段,可以在這個階段對事件做出響應。 -
事件委託的原理,作用,和觸發事件的物件是誰?
因為事件具有冒泡機制,因此我們可以利用冒泡的原理,把事件加到父級上,觸發執行效果。這樣做的好處當然就是提高效能了
最重要的是通過event.target判斷觸發事件的物件是誰
5.documen.write和 innerHTML的區別
document.write只能重繪整個頁面
innerHTML可以重繪頁面的一部分
3.BOM相關
4.JS高階
1.函式高階
1.閉包
特性: 1.函式巢狀函式 2.函式內部可以引用外部的引數和變數 3.引數和變數不會被垃 圾回收機制回收
閉包的缺點就是常駐記憶體,會增大記憶體使用量,使用不當很容易造成記憶體洩露。
為什麼要使用閉包:
為了設計私有方法和變數,避免全域性變數汙染希望一個變數長期駐紮在記憶體中
view detail: https://segmentfault.com/a/1190000000652891
2.原型與原型鏈
當從一個物件那裡調取屬性或方法時,如果該物件自身不存在這樣的屬性或方法,就會去自己關聯的prototype物件那裡尋找,如果prototype沒有,就會去prototype關聯的前輩prototype那裡尋找,如果再沒有則繼續查詢Prototype.Prototype引用的物件,依次類推,直到Prototype.….Prototype為undefined(Object的Prototype就是undefined)從而形成了所謂的“原型鏈”。
其中foo是Function物件的例項。而Function的原型物件同時又是Object的例項。這樣就構成了一條原型鏈。
instanceof 確定原型和例項之間的關係
用來判斷某個建構函式的prototype屬性是否存在另外一個要檢測物件的原型鏈上
物件的__proto__指向自己建構函式的prototype。obj.proto.proto…的原型鏈由此產生,包括我們的操作符instanceof正是通過探測obj.proto.proto… === Constructor.prototype來驗證obj是否是Constructor的例項。
function C(){}
var o = new C(){}
//true 因為Object.getPrototypeOf(o) === C.prototype
o instanceof C
instanceof只能用來判斷物件和函式,不能用來判斷字串和數字
isPrototypeOf
用於測試一個物件是否存在於另一個物件的原型鏈上。
判斷父級物件可檢查整個原型鏈
3.作用域與作用域鏈
作用域鏈的作用是保證執行環境裡有權訪問的變數和函式是有序的,作用域鏈的變數只能向上訪問,變數訪問到window物件即被終止,作用域鏈向下訪問變數是不被允許的。
全域性函式無法檢視區域性函式的內部細節,但區域性函式可以檢視其上層的函式細節,直至全域性細節。
當需要從區域性函式查詢某一屬性或方法時,如果當前作用域沒有找到,就會上溯到上層作用域查詢,
直至全域性函式,這種組織形式就是作用域鏈。
4.apply, call和bind有什麼區別?
參考答案:三者都可以把一個函式應用到其他物件上,call、apply是修改函式的作用域(修改this指向),並且立即執行,而bind是返回了一個新的函式,不是立即執行.apply和call的區別是apply接受陣列作為引數,而call是接受逗號分隔的無限多個引數列表,
Array.prototype.slice.call(null, args)
function getMax(arr){
return Math.max.apply(null, arr);
}
//call
function foo() {
console.log(this);//{id: 42}
}
foo.call({ id: 42 });
如果該方法是非嚴格模式程式碼中的函式,則null和undefined將替換為全域性物件,並且原始值將被包裝。當你呼叫apply傳遞給它null時,就像是呼叫函式而不提供任何物件
5.談談對this的理解
this總是指向函式的直接呼叫者(而非間接呼叫者);
如果有new關鍵字,this指向new出來的那個物件;
在事件中,this指向觸發這個事件的物件,特殊的是,IE中的attachEvent中的this總是指向全域性物件Window;
6.那些操作會造成記憶體洩漏?
記憶體洩漏指任何物件在您不再擁有或需要它之後仍然存在。
垃圾回收器定期掃描物件,並計算引用了每個物件的其他物件的數量。如果一個物件的引用數量為 0(沒有其他物件引用過該物件),或對該物件的惟一引用是迴圈的,那麼該物件的記憶體即可回收。
setTimeout 的第一個引數使用字串而非函式的話,會引發記憶體洩漏。
閉包、控制檯日誌、迴圈(在兩個物件彼此引用且彼此保留時,就會產生一個迴圈)
7.深入貫徹閉包思想,全面理解JS閉包形成過程
https://segmentfault.com/a/1190000009886713
8.下面這個ul,如何點選每一列的時候alert其index?(閉包)
- 這是第一條
- 這是第二條
- 這是第三條
組合式繼承
組合式繼承是比較常用的一種繼承方法,其背後的思路是使用原型鏈實現對原型屬性和方法的繼承,而通過借用建構函式來實現對例項屬性的繼承。這樣,既通過在原型上定義方法實現了函式複用,又保證每個例項都有它自己的屬性。
2.上下文環境物件
3.new操作符具體做了什麼
1、建立一個空物件,並且this變數引用該物件,同時繼承了該函式的原型(例項物件通過__proto__屬性指向原型物件;obj.proto = Base.prototype;) 2、屬性和方法被加入到 this 引用的物件中。
function Animal(name) {
this.name = name;
}
Animal.prototype.run = function() {
console.log(this.name + ‘can run…’);
}
var cat = new Animal(‘cat’);
//模擬過程
new Animal(‘cat’)=function(){
let obj={}; //建立一個空物件
obj.proto=Animal.prototype;
//把該物件的原型指向建構函式的原型物件,就建立起原型了:obj->Animal.prototype->Object.prototype->null
return Animal.call(obj,‘cat’);// 繫結this到例項化的物件上
}
4.建立物件的幾種方式
javascript建立物件簡單的說,無非就是使用內建物件或各種自定義物件,當然還可以用JSON;但寫法有很多種,也能混合使用。
1、物件字面量的方式
person={firstname:"Mark",lastname:"Yun",age:25,eyecolor:"black"};
2、用function來模擬無參的建構函式
function Person(){}
var person=new Person();//定義一個function,如果使用new"例項化",該function可以看作是一個Class
person.name="Mark";
person.age="25";
person.work=function(){
alert(person.name+" hello...");
}
person.work();
3、用function來模擬參建構函式來實現(用this關鍵字定義構造的上下文屬性)
function Pet(name,age,hobby){
this.name=name;//this作用域:當前物件
this.age=age;
this.hobby=hobby;
this.eat=function(){
alert("我叫"+this.name+",我喜歡"+this.hobby+",是個程式設計師");
}
}
var maidou =new Pet("麥兜",25,"coding");//例項化、建立物件
maidou.eat();//呼叫eat方法
4、用工廠方式來建立(內建物件)
var wcDog =new Object();
wcDog.name="旺財";
wcDog.age=3;
wcDog.work=function(){
alert("我是"+wcDog.name+",汪汪汪......");
}
wcDog.work();
5、用原型方式來建立
function Dog(){
}
Dog.prototype.name="旺財";
Dog.prototype.eat=function(){
alert(this.name+"是個吃貨");
}
var wangcai =new Dog();
wangcai.eat();
5、用混合方式來建立
function Car(name,price){
this.name=name;
this.price=price;
}
Car.prototype.sell=function(){
alert("我是"+this.name+",我現在賣"+this.price+"萬元");
}
var camry =new Car("凱美瑞",27);
camry.sell();
3.執行緒機制
1.同步和非同步的區別?
同步:阻塞的
-張三叫李四去吃飯,李四一直忙得不停,張三一直等著,直到李四忙完兩個人一塊去吃飯
=瀏覽器向伺服器請求資料,伺服器比較忙,瀏覽器一直等著(頁面白屏),直到伺服器返回資料,瀏覽器才能顯示頁面
非同步:非阻塞的
-張三叫李四去吃飯,李四在忙,張三說了一聲然後自己就去吃飯了,李四忙完後自己去吃
=瀏覽器向伺服器請求資料,伺服器比較忙,瀏覽器可以自如的幹原來的事情(顯示頁面),伺服器返回資料的時候通知瀏覽器一聲,瀏覽器把返回的資料再渲染到頁面,區域性更新
5.ES6相關
1.談一談let與var和const的區別?
let為ES6新新增申明變數的命令,它類似於var,但是有以下不同:
let命令不存在變數提升,如果在let前使用,會導致報錯
暫時性死區的本質,其實還是塊級作用域必須“先聲明後使用”的性質。
let,const和class宣告的全域性變數不是全域性物件的屬性。
const宣告的變數與let宣告的變數類似,它們的不同之處在於,const宣告的變數只可以在宣告時賦值,不可隨意修改,否則會導致SyntaxError(語法錯誤)。
const只是保證變數名指向的地址不變,並不保證該地址的資料不變。const可以在多個模組間共享 let 暫時性死區的原因:var 會變數提升,let 不會。
2.箭頭函式
箭頭函式不屬於普通的 function,所以沒有獨立的上下文。箭頭函式體內的this物件,就是定義時所在的物件,而不是使用時所在的