JavaScript常見面試題

1.函數聲明和函數表達式的區別javascript

show1();//show1

function show1(){  //函數聲明

console.log("show1");

}

show1();//show1

console.log(show2);//undefined

var show2 = function(){ //函數表達式

console.log("show2");

}

show2();//show2
複製代碼

聲明的函數會有提高,在聲明先後都可使用,函數表達式聲明的函數會有提高,但只是聲明提高,函數名此時爲undefined,並不能執行,只有在賦值操做後才能執行php

2.什麼是閉包,閉包的做用 什麼是閉包:css

當內部函數被保存到外部時,將會生成閉包。閉包會致使原有做用域鏈不釋放,形成內存泄露。html

閉包的做用:java

實現公有變量 eg:函數累加器web

能夠作緩存 eg:eater面試

能夠實現封裝,屬性私有化。 eg: Person();ajax

經典例題:算法

function fun(n,o){

console.log(o);

return {

fun:function(m){

return fun(m,n);

}

}

}

var a = fun(0); a.fun(1); a.fun(2); a.fun(3);//undefined 0 0 0

var b = fun(0).fun(1).fun(2).fun(3);//undefined 0 1 2

var c = fun(0).fun(1); c.fun(2); c.fun(3);// undefined 0 1 1
複製代碼

3.什麼是跨域,如何解決跨域問題? 跨域,指的是瀏覽器不能執行其餘網站的腳本。它是由瀏覽器的同源策略形成的,是瀏覽器對JavaScript施加的安全限制。後端

同源:域名,協議,端口均相同

不一樣源:協議不一樣(http/https),域名不一樣,域名的前綴不一樣,端口不一樣,域名和域名對應ip也屬於跨域,請注意:localhost和127.0.0.1雖然都指向本機,但也屬於跨域。

一、後端配置cors:

本人對後端領域還沒有涉足,推薦博客:blog.csdn.net/envon123/ar…

二、JSONP:

SONP只支持GET請求,不支持POST請求,此方法使用較少

三、Proxy(代理):

例如www.123.com/index.html須要調用www.456.com/server.php,能夠寫一個接口www.123.com/server.php,由這個接口在後端去調用www.456.com/server.php並拿到返回值,而後再返回給index.html,這就是一個代理的模式。至關於繞過了瀏覽器端,天然就不存在跨域問題。

4.瀏覽器請求一個url頁面到顯示完成,這個過程發生了什麼 簡單得講:

瀏覽器根據請求的URL交給DNS域名解析,找到真實IP,向服務器發起請求;

服務器交給後臺處理完成後返回數據,瀏覽器接收文件(HTML、JS、CSS、圖象等);

瀏覽器對加載到的資源(HTML、JS、CSS等)進行語法解析,創建相應的內部數據結構(如HTML的DOM);

載入解析到的資源文件,渲染頁面,完成。

詳細得說:

  一、當發送一個URL請求時,無論這個URL是Web頁面的URL仍是Web頁面上每一個資源的URL,瀏覽器會開啓一個線程來處理這個請求,對URL 分析判斷若是是 http 協議就按照 Web 方式來處理;

二、調用瀏覽器內核中的對應方法,好比 WebView 中的 loadUrl 方法;

三、在遠程DNS服務器上啓動一個DNS查詢,這能使瀏覽器得到請求對應的IP地址。經過DNS解析獲取網址的IP地址,設置 UA 等信息發出第二個GET請求;

四、進行HTTP協議會話,客戶端發送報頭(請求報頭):瀏覽器與遠程Web服務器經過TCP三次握手協商來創建一個TCP/IP鏈接。該握手包括一個同步報文,一個同步-應答報文和一個應答報文,這三個報文在 瀏覽器和服務器之間傳遞。該握手首先由客戶端嘗試創建起通訊,然後服務器應答並接受客戶端的請求,最後由客戶端發出該請求已經被接受的報文。

五、進入到web服務器上的 WebServer,如 Apache、Tomcat、Node.JS 等服務器;

六、進入部署好的後端應用,如PHP、Java、JavaScript、Python 等,找到對應的請求處理;

七、處理結束回饋報頭,此處若是瀏覽器訪問過,緩存上有對應資源,會與服務器最後修改時間對比,一致則返回304;

八、瀏覽器開始下載html文檔(響應報頭,狀態碼200),同時使用緩存;

九、文檔樹創建,根據標記請求所需指定MIME類型的文件(好比css、js),同時設置了cookie;

十、瀏覽器會解析HTML生成DOM Tree,其次會根據CSS生成CSSRule Tree,而javascript又能夠根據DOMAPI操做DOM,執行事件綁定等,頁面顯示完成。

(轉自:www.cnblogs.com/calamus/p/5…)

5.冒泡排序算法 解析:1.比較相鄰的兩個元素,若是前一個比後一個大,則交換位置。

   2.第一輪的時候最後一個元素應該是最大的一個。

   3.按照步驟一的方法進行相鄰兩個元素的比較,這個時候因爲最後一個元素已是最大的了,因此最後一個元素不用比較。

性能 時間複雜度: 平均時間複雜度O(nn) 、最好狀況O(n)、最差狀況O(nn)  空間複雜度: O(1)  穩定性:穩定

時間複雜度指的是一個算法執行所耗費的時間  空間複雜度指運行完一個程序所需內存的大小  穩定指,若是a=b,a在b的前面,排序後a仍然在b的前面  不穩定指,若是a=b,a在b的前面,排序後可能會交換位置

let arr = [6,4,1,2,5];

let len = arr.length;

for(let i = 0;i < len; i++){

for(let j = 0;j < len-i-1;j++){

if(arr[j] > arr[j+1]){

let temp = arr[j];

arr[j] = arr[j+1];

arr[j+1] = temp;

}

}

}
複製代碼

如下代碼是我的的習慣寫法,每次都找到當前的最小元素放在開始位置:

for(var i = 0;i < len-1;i++){

for(var j = i + 1; j < len; j++){

if(arr[i] > arr[j]){

var temp = arr[i];

arr[i] = arr[j];

arr[j] = temp;

}

}

}
複製代碼

6.全局做用域,局部做用域 預編譯發生在函數執行的前一刻

預編譯 四部曲:

1.建立AO對象

2.找形參和變量聲明,將變量和形參名做爲AO屬性名,值爲undefined

3.將實參值和形參統一

4.在函數體裏面找函數聲明,值賦予函數體

先生成GO後生成AO

 

var a = 10;

function f(){

var b = 2 * a;

var a =20;

var c = a + 1;

console.log(b);//NaN

console.log(c);//21

}

f();
複製代碼

7.JavaScript中的數據類型 js中有六種數據類型,包括五種基本數據類型(Number,String,Boolean,Undefined,Null,ES6新增Symbol,ES10新增bigint),

和一種複雜數據類型(Object)。

typeof   123   //Number

typeof   'abc'  //String

typeof    true       //Boolean

typeof    undefined   //Undefined

typeof    null        //Object

typeof    { }           //Object

typeof    [ ]           //Object

typeof    console.log()       //Function

null類型進行typeof操做符後,結果是object,緣由在於,null類型被當作一個空對象引用。

三大引用類型:Object,Array,Function

判斷是是否是數組:

arr.constructor === Array    //true

arr instanceof Array            //true

Object.prototype.toString.call(arr)==="[object Array]"    //true

8.Ajax的過程和原理 1.獲取ajax異步對象

IE4~IE12 : 使用new ActiveXObject("microsoft.xmlhttp");

非IE : 使用new XMLHttpRequest();

2.ajax.open(method,url);

method是提交方式  有 get和post兩種

url是提交路徑

3.ajax.send()

4.ajax.onreadystatechange 這是一個監聽函數

包括五中狀態碼:

0—ajax異步對象建立完畢,可是還未發送

1—ajax已經調用了open()方法,可是還未調用send()方法

2—已經調用send(),可是還未到達服務器端

3—表示請求已經到達服務端,正在服務端的處理,可是還未響應返回

4—ajax已經徹底接收了服務器的響應信息,可是狀態碼未必是正確的

狀態碼有:

200:正確

404/500:錯誤

ps:a.每一個瀏覽器的0,1,2,3這四種狀態顯示的不同,可是4這個狀態碼每

個瀏覽器都有,因此咱們只須要使用4便可

b.  0.1.2.3.4是ajax中的響應碼,200/404/500是web中的狀態碼

5.ajax.readyState == 4

6.ajax.status == 200;

7.獲取值  ajax.requestText或者ajax.requestXML

(測試見:www.w3school.com.cn/tiy/t.asp?f…

function getData(){

var xmlhttp;

if(window.XMLhttpRequest){

xmlhttp = new XMLhttpRequest();

}else{

xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

}

xmlhttp.open("post","http://localhost:8080/api",true);//true異步

xmlhttp.send();

xmlhttp.onreadystatechange = function(){

         if(xmlhttp.readyState == 4 && xmlhttp.status == 200){

         console.log(xmlhttp.responseText);

        }

    }

}
複製代碼

9.call apply bind區別 call和apply功能:改變this的指向,區別:傳參列表不一樣

call須要把實參按照形參的個數傳進去

apply須要傳一個arguments

注意這裏apply()的第一個參數是null,在非嚴格模式下,第一個參數爲null或者undefined時會自動替換爲指向全局對象

bind()的做用與call()和apply()同樣,都是能夠改變函數運行時上下文,區別是call()和apply()在調用函數以後會當即執行,而bind()方法調用並改變函數運行時上下文後,返回一個新的函數,供咱們須要時再調用。

10.this指針問題 1.函數預編譯過程 this —> window

預編譯 arguments在AO裏(函數中使用嚴格模式,this --> undefined )

2.全局做用域裏 this —> window

3.call/apply 能夠改變函數運行時this指向

4.obj.func();   func()裏面的this指向obj

var num = 1;

var o = {

num:2,

print:function(){

this.num = 3;

(function(){

console.log(this.num); //1

})();

console.log(this.num);//3

}

}

o.print();
複製代碼

javascript經典面試題整理

一.類型轉換

var a = false + 1;

console.log(a); //1

 

var b = false == 1;

console.log(b);//false

 

if(typeof(a) && (-true) + (+undefined) + ''){

console.log('經過了');

}

// typeof(a) --> 'undefined'

// -true --> -1 +undefined --> NaN

// -1 + NaN-->NaN NaN + '' --> 'NaN'

 

if(1+5*'3' === 16){

console.log('經過了');

}

 

console.log(!!' ' + !!'' + !!false ||'未經過');//1

 

window.a || (window.a = '1');

//()優先級高,先給a賦值,而後進行判斷,window.a=='1',爲true返回
複製代碼

二.

var fn = (

function test1(){

return '1';

},

function test2(){

return '2';

}

)();

console.log(typeof(fn));//string

 

var a = 10;

if(function b(){}){//不是false,因此爲true

a += typeof b;//(function b(){})函數聲明被()包含生成表達式,b被忽略

}

console.log(a);//'10undefined'
複製代碼

三.

var name = 'ddd';

name += 10;

var type = typeof name;

//若是想要輸出string var type = new String(typeof name);

if(type.length === 6){

type.text = 'string';

}

console.log(type.text);//undefined

 

var x = 1,

y = z = 0;

function add(n){

return n = n + 1;

}

y = add(x);

function add(n){//預編譯,將前面的add覆蓋

return n = n + 3;

}

z = add(x);

console.log(x,y,z);//1,4,4


 

function test(x,y,a){

a = 10;

console.log(arguments[2]);//10 映射關係

arguments[1] = 9;

console.log(y);//9

}

test(1,2,3);
複製代碼

四.

var name = '222';

var a = {

name:'111',

say:function(){

console.log(this.name);

}

}

var fun = a.say;

//var fun = fuunction(){console.log(this.name)} this指向window

fun();//222

a.say();//111 對象裏面的方法,this指向a

var b = {

name:'333',

say:function(fun){

fun();

}

}

b.say(a.say);//222 this指向window

b.say=a.say;

// b.say=fuunction(){console.log(this.name)}

b.say();//333

 

function Foo(){

getName = function(){//未通過var的變量會提高到全局,會把以前的getName覆蓋

console.log(1);

}

return this;

}

Foo.getName = function(){

console.log(2);

}

Foo.prototype.getName = function(){

console.log(3);

}

var getName = function(){

console.log(4);

}

function getName(){

console.log(5);

}

Foo.getName();//2

getName();//4

Foo().getName();//1

getName();//1

new Foo.getName();//2 .運算優先級高於new

new Foo().getName();//3 new Foo()先執行

new new Foo().getName();//3
複製代碼
相關文章
相關標籤/搜索