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();
複製代碼
一.類型轉換
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
複製代碼