2019 前端面試題總結 及 答案


一)vue router 跳轉方式

1.this.$router.push() 

跳轉到不同的url,但這個方法會向history棧添加一個記錄,點擊后退會返回到上一個頁面。

  1.  this.$ router.push({path: '/home/sort/detail',query:{id: 'abc'}})     
     獲取參數 {{this.$ route.query.userId}}
  2.  this.$ router.push({name: 'detail',params:{id: 'abc'}})
    獲取參數:{{this.$ route.params.userId}}

ps:

query和params 的區別:

1.用法上

query要用path來引入,params要用name來引入:eg

this.$router.push({
   name:"detail",
   params:{
    name:'nameValue',
    code:10011
 }
});

2.展示上的

  query更加類似於我們ajax中get傳參,params則類似於post,說的再簡單一點,前者在瀏覽器地址欄中顯示參數,后者則不顯示

2.this.$router.replace()

同樣是跳轉到指定的url,但是這個方法不會向history里面添加新的記錄,點擊返回,會跳轉到上上一個頁面。上一個記錄是不存在的。

3.this.$router.go(n)

相對於當前頁面向前或向后跳轉多少個頁面,類似 window.history.go(n)。n可為正數可為負數。正數返回上一個頁面

4.聲明式

1) 根據路由路徑(/home/sort/detail)跳轉 <router-link :to="{path: '/home/sort/detail', query:{id: 'abc'}}">點擊查看子頁面</router-link>

2) 根據路由名稱(detail)跳轉 <router-link :to="{name: 'detail', params:{id: 'abc'}}">點擊查看子頁面</router-link>    :to="" 可以實現綁定動態的 路由 和 參數

 

二)Cookie和localStorage、sessionStorage的區別

名稱 cookie localStorage sessionStorage
相同點 都可以用來在瀏覽器端存儲數據,都是字符串的鍵值對
數據聲明周期 一般由服務器生成,可設置失效時間;若在瀏覽器生成,默認關閉瀏覽器之后失效 除非被清除,否則永久有效 僅對當前對話有效,關閉當前頁面或者瀏覽器后被清除
存儲大小 4kb 一般5mb
與服務端通信 每次都會攜帶在http請求頭中,如果使用cookie保存過多,性能不太好 僅在客戶端存儲,不參與服務端通信
用途 一般由服務器生成,來標識用戶身份 勇於瀏覽器端緩存數據

三)數組相關

參考文章數組相關https://www.cnblogs.com/jiajiamiao/p/11641574.html

四)let var const 的區別

1:var  全局變量,存在變量提升,在聲明前取值為undefined 會掛載在window上 如:
var a = 1;
console.log(a,window.a) // 1 1
2:let 聲明局部變量,只在塊級作用域內有效
console.log(b); // 報錯:b在初始化之前不能接收
let b = 10;
var a = [];

for (var i = 0; i < 10; i++) {  
    a[i] = function () { 
       console.log(i);  
    };
}
a[2]();    //10

var b = []; 
for (let k = 0; k < 10; k++) {  
    b[k] = function () { 
        console.log(k);  
    };
}
b[2]();     //2
3:const 聲名的是常量,一經聲明不可改變。但是引用類型的對象和數組可以改變:
const person = {
     name : 'jony',
     sex : '男'
 }
 person.name = '九九'
 
 console.log(person.name)   //九九

ps//因為對象是引用類型的,person中保存的僅是對象的指針,這就意味着,const僅保證指針不發生改變,修改對象的屬性不會改變對象的指針,所以是被允許的。也就是說const定義的引用類型只要指針不發生改變,其他的不論如何改變都是允許的。

五)vue的常用指令有哪些?

 

v-for 循環 ps:如果list是對象,還有value,key屬性,如v-for="(value,key,index) in list";
v-for 中key必須為唯一的 作用是:主要是為了高效的更新虛擬DOM v
-bind 綁定屬性 簡寫: v-bind:屬性名="常量 || 變量名" v-on 綁定時間 簡寫@ v-on:click = "方法名 || 直接改變 vue 內部變量" 雙向綁定:v-model 所謂的雙向綁定,就是你在視圖層里面改變了值,vue里面對應的值也會改變。只能給具備value屬性的元素進行雙向數據綁定。 v-html 插入HMTL v-text 插入文本 條件渲染: v-if v-show v-show 本質就是標簽display設置為none,控制隱藏 v-if 是動態的向DOM樹內添加或者刪除DOM元素 從性能上來說: v-show只編譯一次,后面其實就是控制css,而v-if不停的銷毀和創建,故v-show性能更好一點

 

六)Ajax請求原理解析

1:創建XMLHttpRequest對象

var xhr;
if(XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}

2:准備請求

xhr.open(method,url,async);
method:get   post
url:請求地址
async:true異步 false同步

3:發送請求

xhr.send();
get :xhr.open("GET",url,true);
xhr.send(null);

post:
xhr.open("POST",url,true);
xhr.setRequestHeder("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");   //規定表頭
xhr.send("name="+userName+"&age="+userAge);//參數

4:處理響應

xhr.onreadystatechange = function(){
  if(xhr.readyState == 4 && xhr.status == 200){
    console.log(“響應成功成功”,xhr.responseText);
  }
}

七)get和post請求的區別

 

八)從輸入url到頁面加載完成發生了什么?——前端角度

1、瀏覽器的地址欄輸入URL並按下回車。
2、瀏覽器查找當前URL的DNS緩存記錄。
3、DNS解析URL對應的IP。
4、根據IP建立TCP連接(三次握手)。
5、HTTP發起請求。
6、服務器處理請求,瀏覽器接收HTTP響應。
7、渲染頁面,構建DOM樹。
8、關閉TCP連接(四次揮手)

參考博客:https://www.cnblogs.com/daijinxue/p/6640153.html

 九)http和https的區別

Http:超文本傳輸協議(Http,HyperText Transfer Protocol)是互聯網上應用最為廣泛的一種網絡協議。設計Http最初的目的是為了提供一種發布和接收HTML頁面的方法。它可以使瀏覽器更加高效。Http協議是以明文方式發送信息的,如果黑客截取了Web瀏覽器和服務器之間的傳輸報文,就可以直接獲得其中的信息。

Https:是以安全為目標的Http通道,是Http的安全版。Https的安全基礎是SSL。SSL協議位於TCP/IP協議與各種應用層協議之間,為數據通訊提供安全支持。SSL協議可分為兩層:SSL記錄協議(SSL Record Protocol),它建立在可靠的傳輸協議(如TCP)之上,為高層協議提供數據封裝、壓縮、加密等基本功能的支持。SSL握手協議(SSL Handshake Protocol),它建立在SSL記錄協議之上,用於在實際的數據傳輸開始前,通訊雙方進行身份認證、協商加密算法、交換加密密鑰等。

HTTP與HTTPS的區別

1、HTTP是超文本傳輸協議,信息是明文傳輸,HTTPS是具有安全性的SSL加密傳輸協議。

2、HTTPS協議需要ca申請證書,一般免費證書少,因而需要一定費用。

3、HTTP和HTTPS使用的是完全不同的連接方式,用的端口也不一樣。前者是80,后者是443。

4、HTTP連接是無狀態的,HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,安全性高於HTTP協議。

https的優點

盡管HTTPS並非絕對安全,掌握根證書的機構、掌握加密算法的組織同樣可以進行中間人形式的攻擊,但HTTPS仍是現行架構下最安全的解決方案,主要有以下幾個好處:

1)使用HTTPS協議可認證用戶和服務器,確保數據發送到正確的客戶機和服務器;

2)HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,要比http協議安全,可防止數據在傳輸過程中不被竊取、改變,確保數據的完整性。

3)HTTPS是現行架構下最安全的解決方案,雖然不是絕對安全,但它大幅增加了中間人攻擊的成本。

4)谷歌曾在2014年8月份調整搜索引擎算法,並稱“比起同等HTTP網站,采用HTTPS加密的網站在搜索結果中的排名將會更高”。

Https的缺點

1)Https協議握手階段比較費時,會使頁面的加載時間延長近。

2)Https連接緩存不如Http高效,會增加數據開銷,甚至已有的安全措施也會因此而受到影響;

3)SSL證書通常需要綁定IP,不能在同一IP上綁定多個域名,IPv4資源不可能支撐這個消耗。

4)Https協議的加密范圍也比較有限。最關鍵的,SSL證書的信用鏈體系並不安全,特別是在某些國家可以控制CA根證書的情況下,中間人攻擊一樣可行。

十)json和xml數據的區別

1,數據體積方面:xml是重量級的,json是輕量級的,傳遞的速度更快些。。

2,數據傳輸方面:xml在傳輸過程中比較占帶寬,json占帶寬少,易於壓縮。

3,數據交互方面:json與javascript的交互更加方便,更容易解析處理,更好的進行數據交互

4,數據描述方面:json對數據的描述性比xml較差

5,xml和json都用在項目交互下,xml多用於做配置文件,json用於數據交互。

十一)svg和canvas的區別

cancas:

   通過js來繪制2D圖形  逐像素渲染的    canvas中,一旦圖形被繪制完成,他就不會繼續得到瀏覽器的關注,如果他的位置變化,那么就需要重新來繪制圖形,其中包括任何或者已經被圖形覆蓋的對象。

svg:

      svg是xml描述的2D圖形    svg是基於xml的,也就是svg dom中的每個元素都是可用的,可以為某個元素附加js事件處理器。     在svg中,每個被繪制的圖像均視為對象,如果svg對象的屬性變化,那么瀏覽器可以自行重現圖形。

區別:

canvas       

  a:依賴分辨率

  b:不支持事件處理器

  c:  弱的文本渲染能力

  d:能夠以.jpg或者.png格式保存結果圖像

  e:最適合圖像密集型的游戲,其中的很多對象會被頻繁的繪制

svg

  a:不依賴分辨率

  b: 支持事件處理器

  c: 最適合帶有大型渲染區域的應用程序(谷歌地圖)

  d: 復雜度高會減慢渲染速度

  e:不適合游戲應用

十二)不知寬高的盒子如何居中

 1 <div class="warp"><div class="box"></div></div>
 2 
 3 1)display:flex
 4 .warp{display:flex;   justify-content:center;  align-item:center;}
 5 
 6 2).warp{position:relative;}
 7 .box{position:absolute; left:50%; right:50%;  transform:translate(-50%,-50%)}
 8 
 9 3).warp{position:relative;}
10 .box{position:absolute; left:0; right:0; top:0; bottom:0; 
11  margin:auto;}
12 
13 4).warp{display:table;}
14 .box{display:table-cell; text-align:center; vertical-align:middle; }

十三)computed和watch的區別

computed

計算結果並返回,只有當被計算的屬性發生改變時才會觸發(即:計算屬性的結果會被緩存,除非依賴的響應屬性變化才會重新及孫)

watch

 監聽某一個值,當被監聽的值發生變化時,執行相關操作。(與computed的區別是,watch更加適用於監聽某一個值得變化,並做對應操作,比如請求后太接口等。而computed適用於計算已有的值並返回結果。)

監聽簡單數據類型:

 

data(){
      return{
        'first':2
      }
    },
    watch:{
      first(){
        console.log(this.first)
      }
    },

 

監聽復雜數據類型

 

data(){
      return{ 'first':{ second:0 } } }, watch:{ secondChange:{ handler(oldVal,newVal){ console.log(oldVal) console.log(newVal) }, deep:true } },

 

十四)vue的生命周期

Vue 實例有一個完整的生命周期,也就是從開始創建、初始化數據、編譯模板、掛載Dom→渲染、更新→渲染、卸載等一系列過程,我們稱這是 Vue 的生命周期。通俗說就是 Vue 實例從創建到銷毀的過程,就是生命周期。

beforeCreate: vue元素的掛載元素el和數據都為undefined,還未初始化;

 

 

created:vue實例的數據對象data有了,el還沒有;

beforeMount:vue實例的$el和data都初始化了,但是還掛載在之前的虛擬dom節點上,data.message還未替換;

mounted:vue實例掛載完成,data.message成功渲染。

更新前后:data變化時會觸發beforeUpdateupdated方法;

銷毀前后:beforeDestorydestoryed,在執行destoryed方法后,對data的改變不會觸發周期函數,說明vue實例已經解除了事件監聽以及dom綁定,但是dom結構依然存在;

vue生命周期的作用:

他的生命周期中有多個事件鈎子,讓我們控制整個vue實例的過程時更容易形成良好的邏輯。

生命周期鈎子的一些使用方法:

beforeCreate:loading事件,在加載實例時觸發。

created:初始化完成事件,異步請求。

mounted:掛載元素,獲取dom節點

uptaded:對數據統一處理

beforeDestory:確認事件停止。

nextTick:更新數據后立即操作dom。

十五)vuex如何實現按需加載配合webpack配置

webpack中提供了require.ensure()來實現按需加載。以前引入路由是通過import 這樣的方式引入,改為const定義的方式進行引入。

        不進行頁面按需加載引入方式:import  home   from '../../common/home.vue'

        進行頁面按需加載的引入方式:const  home = r => require.ensure( [], () => r (require('../../common/home.vue')))

十六)vue-router有哪幾種導航守衛

1》全局守衛

a:router.beforeEach 全局前置守衛,進入路由之前

b:router.beforResolve 全局解析守衛,在beforeRouterEnter調用之后調用

c:router.afterEach 全局后置鈎子,進入路由之后

 

//main.js  入口文件
import router from ’./router‘
router.beforeEach(to,from,next)=>{
    next();
}

router.beforeResolve(to,from,next)=>{
    next();
}

router.afterEach(to,from)=>{
    console.log('全局后置鈎子')
}

 

2》路由獨享守衛

如果不想全局配置守衛的話,可以為某些路由單獨配置守衛

 

{
    path: '/home',
    name: 'home',
    component: Home,
    beforeEnter(to, from, next) {
        if (window.localStorage.getItem("id")) {
            next()
        } else {
            next({ name: "login" })
        }
    }
}

 

 

 

3》路由組件內的守衛

 

beforeRouteEnter 進入路由前, 在路由獨享守衛后調用 不能 獲取組件實例 this,組件實例還沒被創建

 

beforeRouteUpdate (2.2) 路由復用同一個組件時, 在當前路由改變,但是該組件被復用時調用 可以訪問組件實例 this

 

beforeRouteLeave 離開當前路由時, 導航離開該組件的對應路由時調用,可以訪問組件實例 this

 

 

beforeRouteEnter(to, from, next) {
    // do someting
    // 在渲染該組件的對應路由被 confirm 前調用
},
beforeRouteUpdate(to, from, next) {
    // do someting
    // 在當前路由改變,但是依然渲染該組件是調用
},
beforeRouteLeave(to, from ,next) {
    // do someting
    // 導航離開該組件的對應路由時被調用
}

 十七)this--------參考https://github.com/koala-coding/goodBlog/blob/master/docs/javascript/this.md

默認綁定:

默認綁定是函數針對的獨立調用的時候,不帶任何修飾的函數引用進行調用,非嚴格模式下 this 指向全局對象(瀏覽器下指向 Window,Node.js 環境是 Global ),嚴格模式下,this 綁定到 undefined ,嚴格模式不允許this指向全局對象。

var  a = 'hello'

var obj =
 {
    a:'koala',
    foo: function(){
        console.log(this.a)    
    }
}

var  bar = obj.foo
bar()              
// 瀏覽器中輸出: "hello"

這段代碼, bar()就是默認綁定,函數調用的時候,前面沒有任何修飾調用,也可以用之前的 call函數調用形式理解,所以輸出結果是 hello

默認綁定的另一種情況

在函數中以函數作為參數傳遞,例如 setTimeOutsetInterval等,這些函數中傳遞的函數中的 this指向,在非嚴格模式指向的是全局對象。

var name='koala';
  var person2 ={
        name:'程序員成長指北',
      sayHi:sayHi
      }
  function sayHi() {
      console.log('Hello,',this.name);
    }
  setTimeout(function() {
      person2.sayHi();
  },200);
  // 輸出結果 Hello,koala

隱式綁定

判斷 this 隱式綁定的基本標准:函數調用的時候是否在上下文中調用,或者說是否某個對象調用函數

var name='koala';
  var person2 ={
        name:'程序員成長指北',
        sayHi:function{
       
console.log('Hello,',this.name);
}
}
  person2.sayHi(); // 瀏覽器中輸出: "程序員成長指北"
sayHi方法是作為對象的屬性調用的,那么此時 foo 方法執行時,this 指向person2對象。

隱式綁定的另一種情況

當有多層對象嵌套調用某個函數的時候,如 對象.對象.函數,this 指向的是最后一層對象。

var person2 ={
        name:'程序員成長指北',
      sayHi:sayHi
      }
  function sayHi() {
      console.log('Hello,',this.name);
    }
    var
  var person1 ={
    name:'koala',
    friend:person2
    }
  person1.friend.sayHi();  
// 輸出結果為 Hello, 程序員成長指北

顯式綁定

顯式綁定,通過函數call apply bind 可以修改函數this的指向。call 與 apply 方法都是掛載在 Function 原型下的方法,所有的函數都能使用。

call 和 apply 的區別

1,call和apply的第一個參數會綁定到函數體的this上,如果 不傳參數,例如 fun.call(),非嚴格模式,this默認還是綁定到全局對象

2.call函數接收的是一個參數列表,apply函數接收的是一個參數數組。

var person ={
  "name":"koala"
};
function changeJob(company,work){
    this.company = company;
    this.work    = work;
};
changeJob.call(person,'百度','程序員');
console.log(person.work);
// '程序員'
changeJob.apply(person,['百度', '測試']);
console.log(person.work);
//測試

call和apply的注意點

這兩個方法在調用的時候,如果我們傳入數字或者字符串,這兩個方法會把傳入的參數轉成對象類型。

var number = 1 , string = '程序員成長指北';
function getThisType(){
    var number = 3;
    console.log('this指向內容',this);
    console.log(typeof(this))
}
getThisType.call(number)
getThisType.apply(string)
 
// 輸出結果
// this指向內容 [Number: 1]
// object
// this指向內容 [String: '程序員成長指北']
// objec

bind函數      bind 方法 會創建一個新函數。當這個新函數被調用時,bind() 的第一個參數將作為它運行時的 this,之后的一序列參數將會在傳遞的實參前傳入作為它的參數。(定義內容來自於 MDN )

bind函數      bind 方法 會創建一個新函數。當這個新函數被調用時,bind() 的第一個參數將作為它運行時的 this,之后的一序列參數將會在傳遞的實參前傳入作為它的參數。(定義內容來自於 MDN )
var publicAccounts = {
  name:'測試11111',
  author:'hoster',
  subscribe:function(subscriber){
    console.log(subscriber+this.name)
  }

}
publicAccounts.subscribe('aa') 
//"aa 測試11111"

var subscribe1 = publicAccounts.subscribe.bind({name:'測試bbb',author:'持有者'},'bb')
subscribe1()//bb測試bbb

new 綁定

使用new調用函數的時候,會執行怎樣的流程:

1.創建一個空對象

2.將空對象的 proto 指向原對象的 prototype

3.執行構造函數中的代碼

4.返回這個新對象

function demo(name){
  this.name = name
}
var demoNew = new demo('妹妹');
console.log(demoNew);
console.log(demoNew.name)
//demo {name: "妹妹"}
//妹妹

new Demo('妹妹')的時候,會改變this指向,將 this指向指定到了studyDay對象。注意:如果創建新的對象,構造函數不傳值的話,新對象中的屬性不會有值,但是新的對象中會有這個屬性。

function demo(name){
  this.name = name
}
var demoNew = new demo();
console.log(demoNew);
console.log(demoNew.name)
// demo {name: undefined}
// undefined

手動實現一個new創建對象代碼(多種實現方式哦)

function New(func) {
    var res = {};
    if (func.prototype !== null) {
        res.__proto__ = func.prototype;
    }
    var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
    if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
        return ret;
    }
    return res;
}
var obj = New(A, 1, 2);
// equals to
var obj = new A(1, 2);

this綁定優先級

上面介紹了 this 的四種綁定規則,但是一段代碼有時候會同時應用多種規則,這時候 this 應該如何指向呢?其實它們也是有一個先后順序的,具體規則如下:

new綁定 > 顯式綁定 > 隱式綁定 > 默認綁定

箭頭函數表達式的語法比函數表達式更短,並且不綁定自己的this,arguments,super或 new.target。這些函數表達式最適合用於非方法函數(non-method functions),並且它們不能用作構造函數。

常規函數可以直接拿到 arguments 屬性,但是在箭頭函數中如果使用 arguments 屬性,拿到的是箭頭函數外層函數的 arguments 屬性

function constant() {
    return () => arguments[0]
}

let result = constant(1);
console.log(result()); // 1

箭頭函數中沒有自己的 this,箭頭函數中的 this 不能用 call()、apply()、bind() 這些方法改變 this 的指向,箭頭函數中的 this 直接指向的是調用函數的 上一層運行時

let a = 'kaola'

let obj = {
    a: '程序員成長指北',
    foo: () => {
        console.log(this.a)
    }
}

obj.foo()             // 輸出結果: "koala"
(function(){
    console.log('測試1111')
})()

(function(){
  console.log('ceshi2222')
}())

(()=>{
  console.log('測試33333')
})()

 十八)操作運算符的一些常見的題

console.log( 0=={})
//1 false

console.log(0 == false)
//1 true

console.log(NaN == NaN)
// false

console.log(null === null)
// true

console.log(undefined === undefined)
// true

var a
console.log(a == Object)
// false

console.log(0 === false)
// false

console.log(0 == false)
// true

console.log(1 == true)
//true

console.log(1 === true)
// false

console.log("" == false)
// true

console.log("" === false)
// false

console.log(undefined == null )
// true

console.log(undefined === null )
//false

null == 0
//false

['']==''
//true

[0]==0
//true
ps**值得一提的是,在全等運算中, NaN 與其他任何值相比,結果都是 false

 十八)經典面試題

//JS實現一個無限累加的add函數
add(1) //1
add(1)(2) //3
add(1)(2)(3) //6

 

function add(a) {
    function sum(b) { // 使用閉包
        a = a + b; // 累加
        return sum;
     }
     sum.toString = function() { // 重寫toString()方法
        return a;
    }
     return sum; // 返回一個函數
}

add(1); // 1
add(1)(2);  // 3
add(1)(2)(3);// 6

 十九)link和@inmport的區別

1》link是html的標簽,不僅可以加載css還可以定義Rss , rel連接屬性;@import是css的語法規則,只能引入樣式;
2》加載頁面時,link是同時加載的,@impor是頁面加載完后才加載
3》link沒有兼容性的問題,而@import只在較高版本的瀏覽器才可以識別
4》link可以通過js插入操作dom,@import 不可以!

二十)css寫一個三角形及0.5px的線

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>三角形及0.5px的線</title>
    <style>
    .box{
        width:0;
        height:0;
        border-color: transparent transparent red;
        border-width: 0 15px 15px;
        border-style: solid ; 
    }
    .line {
        position: relative;
    }
    .line:after {
        content: "";
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 1px;
        background-color: #000000;
        -webkit-transform: scaleY(.5);
        transform: scaleY(.5);
    }
    </style>

</head>

<body>
    <div class="box"></div>
    <div class="line"></div>
</body>
</html>

 二十一)vuex:Vue.js應用程序的狀態管理模式+庫。

1.state

保存vuex中的數據源,通過this.$store.state獲取

 

2.getters

用於監聽state中的值的變化,返回計算后的結果。getter的返回值會根據它的依賴被緩存起來

 

3.mutations

是修改store中的值得唯一方式

 

4.action 

官方建議提交一個actions,在actions中提交mutations再去修改狀態值。 this.$store.dispatch('add')

//this.$store.commit('add')

5.modules 模塊化

二十二)如何理解js中的原型鏈

1;每個構造函數都有一個原型對象

2;每個原型對象都有一個指向構造函數的指針

3;每個實例函數都有一個指向原型對象的指針。

4;查找方式是一層一層查找,直至頂層。Object.prototype

二十三)怎么理解js中的內存泄露

定義:程序不需要的內存,由於某些原因其不會返回到操作系統或者可用內存池中。   內存泄露會導致(運行緩慢 ,高延遲,崩潰)的問題

常見的導致內存泄露的原因有:

1;意外的全局變量

2;被遺忘的計時器或回調函數

3;脫離文檔的DOM的引用

4;閉包

 二十四)跨域問題

由於瀏覽器的同源策略會導致跨域,同源策略又分為

一:DOM同源策略:禁止對不同源頁面的DOM進行操作,主要是不同域名的ifram是限制互相訪問的

二:xmlHttpRequest同源策略:禁止使用XHR對象向不同源的服務器地址發起http請求,只要域名  協議  端口有一個不同都被當做不同的域之間的請求,即跨域請求

解決方式:

1.CORS跨域資源共享   后端需要設置Access--Control-Allow-Credentials:true

2.jsonp實現跨域:動態創建script,利用src屬性進行跨域

3. nginx代理跨域

4.nodejs中間件代理跨域

5WebSokect協跨域

6.window.name+ifram跨域

二十五)JS 實現千位分隔符

1:正則表達式和replace函數

function numFormat(num){
  var res=num.toString().replace(/\d+/, function(n){ // 先提取整數部分
       return n.replace(/(\d)(?=(\d{3})+$)/g,function($1){
          return $1+",";
        });
  })
  return res;
}

var a=1234567890123;
var b=123456.123456;
console.log(numFormat(a)); // "1,234,567,890,123"
console.log(numFormat(b)); // "123,456.123456"

 

2:js自帶函數toLocaleString()   //返回這個數字在特定語言環境下的表示字符串

var a=1234567894532;
var b=673439.4542;

console.log(a.toLocaleString());  // "1,234,567,894,532"
console.log(b.toLocaleString());  // "673,439.454"  (小數部分四舍五入了)

3:先轉字符串--》轉數組---》反轉---》三位加逗號----》反轉----》轉字符串-----》實現

function numFormat(num){
    num=num.toString().split(".");  // 分隔小數點
    var arr=num[0].split("").reverse();  // 轉換成字符數組並且倒序排列
    var res=[];
    for(var i=0,len=arr.length;i<len;i++){
      if(i%3===0&&i!==0){
         res.push(",");   // 添加分隔符
      }
      res.push(arr[i]);
    }
    res.reverse(); // 再次倒序成為正確的順序
    if(num[1]){  // 如果有小數的話添加小數部分
      res=res.join("").concat("."+num[1]);
    }else{
      res=res.join("");
    }
    return res;
}

var a=1234567894532;
var b=673439.4542;
console.log(numFormat(a)); // "1,234,567,894,532"
console.log(numFormat(b)); // "673,439.4542"

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM