前端面試資料整理
建立物件的方式
(1)使用new關鍵字
var start = new Object;
(2)使用花括號
var start = {};
建立類
ES6之前使用function關鍵字模擬:function Person(){};
ES6中類的建立方式:class Person{}
非同步傳輸實現方式:
(1)ajax
(2)iframe(加上target)實現
JavaScript 中應該用 “==” 還是 “===”
絕大多數場合應該使用 === ,只有檢測 null/undefined 的時候可以使用 x == null
javascript的typeof返回哪些資料型別
Object number function boolean underfind
例舉3種強制型別轉換和2種隱式型別轉換?
強制(parseInt,parseFloat,number)
隱式(== – ===)
split() join() 的區別
前者是切割成陣列的形式,後者是將陣列轉換成字串
陣列方法pop() push() unshift() shift()
Push()尾部新增 pop()尾部刪除
Unshift()頭部新增 shift()頭部刪除
slice
(1)slice() 方法可從已有的陣列中返回選定的元素。
(2)slice()方法可提取字串的某個部分,並以新的字串返回被提取的部分。
注意: slice() 方法不會改變原始陣列。
sort
sort() 方法用於對陣列的元素進行排序。按字母順序值排序;
call和apply的區別
apply:應用某一物件的一個方法,用另一個物件替換當前物件。
call:呼叫一個物件的一個方法,以另一個物件替換當前物件。
apply:最多隻能有兩個引數——新this物件和一個數組 argArray。
call:則是直接的引數列表,主要用在js物件各方法互相呼叫的時候,使當前this例項指標保持一致,或在特殊情況下需要改變this指標。如果沒有提供 thisObj 引數,那麼 Global 物件被用作 thisObj。
apply和call功能一樣,只是傳入的引數列表形式不同:
apply的寫法:func.apply(func1,[var1,var2,var3])
call的寫法:func.call(func1,var1,var2,var3)
substring和substr的區別
var v1 = 'Hello World';
//如果只是寫一個引數,兩者的作用都是一樣的:就是擷取字串當前下標以後直到字串最後的字串片段。
console.log(v1.substring(1)); //ello World
console.log(v1.substr(1)); //ello World
console.log('**********************************');
// 當寫第二個引數的時候,兩者就會有完全不同的含義;
// substring(a,b)
// 第二個引數是擷取到字串最終的下標(實際擷取位置是1-7)
console.log(v1.substring(1,8)); //ello Wo
// substr(a,b)
// 第二個引數是擷取字串的長度(實際擷取8個字元長度值)
console.log(v1.substr(1,8)); //ello Wor
事件委託是什麼
利用事件冒泡的原理,自己所觸發的事件,讓他的父元素代替執行!
Javascript的事件流模型都有什麼?
(1).冒泡型事件:指事件按照從最精確的物件到最不精確的物件的順序逐一觸發
(2).捕獲型事件:它與冒泡型事件相反,指事件按照從最不精確到最精確的物件的順序逐一觸發
JS物件與JSON格式的互相轉換
①JSON的解析(json資料轉換成JS物件):
var myObject=JSON.parse(myJSONtext);
②JSON的序列化(JS物件轉換成JSON資料):
var myJSONtext=JSON.stringify(myObject);
列舉瀏覽器物件模型BOM裡常用的至少4個物件,並列舉window物件的常用方法至少5個
物件:Window location screen history navigator
方法:Alert() confirm() prompt() open() close() setinterval() settimeout()
documen.write和 innerHTML 的區別?
document.write 只能重繪整個頁面;innerHTML 可以重繪頁面的一部分
閉包是什麼,有什麼特性,對頁面有什麼影響
閉包就是能夠讀取其他函式內部的區域性變數的函式,或者定義在一個函式內部的函式。
閉包的好處:
(1)不增加額外的全域性變數;
(2)執行過程中所有變數都在匿名函式內部
閉包的壞處:
(1)記憶體消耗大,會影響網頁的效能
(2)會改變父函式內部變數的值
如何阻止事件冒泡和預設事件
阻止事件冒泡:w3c的方法是e.stopPropagation(),IE則是使用e.cancelBubble = true;
阻止預設事件:w3c的方法是e.preventDefault(),IE則是使用return false;
瀏覽器渲染頁面的過程
1、使用者輸入URL地址
2、瀏覽器解析URL解析出主機名
3、瀏覽器將主機名轉換成伺服器ip地址(瀏覽器先查詢本地DNS快取列表 沒有的話 再向瀏覽器預設的DNS伺服器傳送查詢請求 同時快取)
4、瀏覽器將埠號從URL中解析出來
5、瀏覽器建立一條與目標Web伺服器的TCP連線(5、6、7三次握手)
6、瀏覽器向伺服器傳送一條HTTP請求報文
7、伺服器向瀏覽器返回一條HTTP響應報文
8、關閉連線 瀏覽器解析文件
HTTP狀態碼知道哪些?
狀態程式碼有三位數字組成,第一個數字定義了響應的類別,共分五種類別:
1xx:指示資訊–表示請求已接收,繼續處理
2xx:成功–表示請求已被成功接收、理解、接受
3xx:重定向–要完成請求必須進行更進一步的操作
4xx:客戶端錯誤–請求有語法錯誤或請求無法實現
5xx:伺服器端錯誤–伺服器未能實現合法的請求
200 OK //客戶端請求成功
400 Bad Request //客戶端請求有語法錯誤,不能被伺服器所理解
401 Unauthorized //請求未經授權,這個狀態程式碼必須和WWW-Authenticate報頭域一起使用
403 Forbidden //伺服器收到請求,但是拒絕提供服務
404 Not Found //請求資源不存在,eg:輸入了錯誤的URL
500 Internal Server Error //伺服器發生不可預期的錯誤
503 Server Unavailable //伺服器當前不能處理客戶端的請求,一段時間後可能恢復正常
JS的原型和原型鏈
(1)原型和原型鏈是JS實現繼承的一種模型;
(2)原型鏈的形成依靠 * _proto_ *而不是prototype
(3)在js中每一個物件都可以看成是一個原型物件,通過proto可以把所有原型物件串聯成一條原型鏈;
cookies、localStorage、sessionStorage的理解
localStorage:長期儲存資料。瀏覽器關閉不丟失;
sessionStorage:儲存的資料在瀏覽器關閉後刪除;
cookies:儲存的資料在瀏覽器和伺服器之間傳遞,資料是加密的;儲存資料大小是4k;
localStorage、sessionStorage儲存的資料在本地,儲存資料大小是5M;
作用域
指對某一屬性(變數)或者方法(函式)具有訪問許可權的程式碼空間,在JS中作用域在函式中進行維護;
this在js中(當前物件)是一個依賴於使用它的執行環境中被解析的關鍵字;
input輸入框提示資訊
<input type="text" placeholder="請輸入資訊"/>
<input type="text" placeholder="請輸入資訊" onfocus="if(value=='請輸入資訊'){value=''}" onblur="if(value==''){value='請輸入資訊'}"/>
第一種情況只有IE10以上版本才會提示請輸入資訊,第二種placeholder+onfocus+onblur可以相容到IE7
HTML中href、src區別
<link href="reset.css" rel=”stylesheet“/>
<script src="script.js"></script>
src用於替換當前元素;href用於在當前文件和引用資源之間建立聯絡
js內建物件:
Data、Math、Array、String、Number、Boolean、function
JQuery中的選擇器
JQuery中的選擇器分為:基本選擇器、層次選擇器、過濾選擇器、屬性過濾選擇器、表單選擇器
基本選擇器:
- ID選擇器:$(ID)
- Class選擇器:$(className)
- 萬用字元選擇器:$(“*”)
層次選擇器
- $(“body div”)
- $(“body > div”)
- $(“body + div”)
- $(“body ~ div”)
過濾選擇器
- $(“div:first”) $(“div:last”)
- $(“div:even”) $(“div:odd”)
- $(“div:eq(3)”) $(“div:gt(3)”) $(“div:lt(3)”)
jQuery有兩種用法($和jquery)使用上有什麼區別呢?
這兩種用法沒什麼區別,只是別名而已,用 $ 要比jQuery簡短一些、
方便一些,另外其他的前端框架也都用到$符號,如果想不跟其他框架衝突,
建議使用jQuery方式。
還有種方法就是換一個新的縮寫:
1、呼叫jquery的noConflict函式
JQuery.noConflict();//讓jquery放棄對$的使用權,
交給其他js框架使用
$和$()的區別:
$可以呼叫那些不需要操作物件的方法(像Java程式碼中的靜態方法,不用宣告物件就可以操作),如$.prototype、$.post()、$.get()、$.ajax()等;如果是給某個物件賦值(注意,這裡有操作物件),就需要用$('#abc').val('123')的方式,因為像val()等方法中會用到$(this)去操作當前物件。
children()
該方法用來獲取子元素的集合
prev()
獲得匹配元素集合中每個元素緊鄰的前一個同胞元素,通過選擇器進行篩選是可選的
siblings()
獲得匹配集合中每個元素的同輩元素,通過選擇器進行篩選是可選的
parent()、
parent() 獲得當前匹配元素集合中每個元素的父元素,使用選擇器進行篩選是可選的。
parents() 獲得當前匹配元素集合中每個元素的祖先元素,使用選擇器進行篩選是可選的。
closest()
closest() 方法獲得匹配選擇器的第一個祖先元素,從當前元素開始沿 DOM 樹向上。
ajax
ajax的優缺點:
優點:
- 不需要外掛支援
- 優秀的使用者體驗
- 提高web的效能
- 減輕伺服器和頻寬的負擔
缺點:
- 瀏覽器對XMLHttpRequest 物件的支援度不好
- 破壞瀏覽器前進後退按鈕的正常功能
- 開發和除錯工具的缺乏
設計模式
總體來說設計模式分為三大類:
建立型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
結構型模式,共七種:介面卡模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、直譯器模式。
23中設計模式中沒有MVC的原因
MVC屬於架構模式,是觀察者模式、策略模式、組合模式三種設計模式的演變
link和@important的區別
- link無相容性,支援使用jsvascript改變模式,而@important不可以
- 內聯樣式與@important相比較,@important的優先順序更高
- 匯入樣式時,link會直接載入,而@important會等頁面載入完成才載入樣式
一、IE6雙倍邊距bug
當頁面上的元素使用float浮動時,不管是向左還是向右浮動;只要該元素帶有margin畫素都會使該值乘以2,例如“margin-left:10px” 在IE6中,該值就會被解析為20px。想要解決這個BUG就需要在該元素中加入display:inline 或 display:block 明確其元素型別即可解決雙倍邊距的BUG
二、IE6中3畫素問題及解決辦法
當元素使用float浮動後,元素與相鄰的元素之間會產生3px的間隙。詭異的是如果右側的容器沒設定高度時3px的間隙在相鄰容器的內部,當設定高度後又跑到容器的相反側了。要解決這類BUG的話,需要使佈局在同一行的元素都加上float浮動。
三、IE6中奇數寬高的BUG
IE6中奇數的高寬顯示大小與偶數高寬顯示大小存在一定的不同。其中要問題是出在奇數高寬上。要解決此類問題,只需要儘量將外部定位的div高寬寫成偶數即可。
四、IE6中圖片連結的下方有間隙
IE6中圖片的下方會存在一定的間隙,尤其在圖片垂直挨著圖片的時候,即可看到這樣的間隙。要解決此類問題,需要將img標籤定義為display:block 或定義vertical-align對應的屬性。也可以為img對應的樣式寫入font-size:0
五、IE6下空元素的高度BUG
如果一個元素中沒有任何內容,當在樣式中為這個元素設定了0-19px之間的高度時。此元素的高度始終為19px。
解決的方法有四種:
1.在元素的css中加入:overflow:hidden
2.在元素中插入html註釋:<!– >
3.在元素中插入html的空白符:
4.在元素的css中加入:font-size:0
六、重複文字的BUG
在某些比較複雜的排版中,有時候浮動元素的最後一些字元會出現在clear清除元素的下面。
解決方法如下:
1.確保元素都帶有display:inline
2.在最後一個元素上使用“margin-right:-3px
3.為浮動元素的最後一個條目加上條件註釋,<!–[if !IE]>xxx<![endif]–>
4.在容器的最後元素使用一個空白的div,為這個div指定不超過容器的寬度。
七、IE6中 z-index失效
具體BUG為,元素的父級元素設定的z-index為1,那麼其子級元素再設定z-index時會失效,其層級會繼承父級元素的設定,造成某些層級調整上的BUG。詳細解釋可以閱讀IE6中部分情況下z-index無效的原因,以及解決辦法
實際上IE6中,很多BUG的解決方法都可以使用display:inline、font-size:0、float解決。因此我們在書寫程式碼時要記住,一旦使用了float浮動,就為元素增加一個display:inline樣式,可以有效的避免浮動造成的樣式錯亂問題。使用空DIV時,為了避免其高度影響佈局美觀,也可以為其加上font-size:0 這樣就很容易避免一些相容上的問題。
css reset的作用是重置瀏覽器的css預設屬性
css Sprite的作用是把一堆小圖片整合到一張大圖片上,減少伺服器對圖片的請求次數,減輕負擔
移動端如何畫出1px
- 使用css設定border為0.5px,js檢車是否支援0.5px
- 直接用圖片實現
- 偽元素+transform實現:before或者after重做border,並將transform的scale值減小一半
- 設定meta標籤
js中的垃圾回收機制—GC
Javascript中的GC垃圾回收機制(GC:Garbage Collecation)
標記清除
js中最常用的垃圾回收方式就是標記清除。當變數進入環境時,就將這個變數標記為“進入環境”。而當變數離開環境時,則將其標記為“離開環境”。對標記為“離開環境”的變數進行排除釋放記憶體引用計數
引用計數的含義是跟蹤記錄每個值被引用的次數。當聲明瞭一個變數並將一個引用型別值賦給該變數時,則這個值的引用次數就是1。如果同一個值又被賦給另一個變數,則該值的引用次數加1。相反,如果包含對這個值引用的變數又取得了另外一個值,則這個值的引用次數減1。當這個值的引用次數變成0時,則說明沒有辦法再訪問這個值了,因而就可以將其佔用的記憶體空間回收回來。這樣,當垃圾回收器下次再執行時,它就會釋放那些引用次數為0的值所佔用的記憶體。
JS事件輪詢
一、為什麼JavaScript是單執行緒?
javascript語言的一大特點就是單執行緒,也就是說,同一個時間只能做一件事。那麼,為什麼JavaScript不能有多個執行緒呢?這樣能提高效率啊。
JavaScript的單執行緒,與它的用途有關。作為瀏覽器指令碼語言,JavaScript的主要用途是與使用者互動,以及操作DOM。這決定了它只能是單執行緒,否則會帶來很複雜的同步問題。比如,假定JavaScript同時有兩個執行緒,一個執行緒在某個DOM節點上新增內容,另一個執行緒刪除了這個節點,這時瀏覽器應該以哪個執行緒為準?
所以,為了避免複雜性,從一誕生,JavaScript就是單執行緒,這已經成了這門語言的核心特徵,將來也不會改變。
為了利用多核CPU的計算能力,HTML5提出Web Worker標準,允許JavaScript指令碼建立多個執行緒,但是子執行緒完全受主執行緒控制,且不得操作DOM。所以,這個新標準並沒有改變JavaScript單執行緒的本質。
二、任務佇列
單執行緒就意味著,所有任務需要排隊,前一個任務結束,才會執行後一個任務。如果前一個任務耗時很長,後一個任務就不得不一直等著。
如果排隊是因為計算量大,CPU忙不過來,倒也算了,但是很多時候CPU是閒著的,因為IO裝置(輸入輸出裝置)很慢(比如Ajax操作從網路讀取資料),不得不等著結果出來,再往下執行。
JavaScript語言的設計者意識到,這時主執行緒完全可以不管IO裝置,掛起處於等待中的任務,先執行排在後面的任務。等到IO裝置返回了結果,再回過頭,把掛起的任務繼續執行下去。
於是,所有任務可以分成兩種,一種是同步任務(synchronous),另一種是非同步任務(asynchronous)。同步任務指的是,在主執行緒上排隊執行的任務,只有前一個任務執行完畢,才能執行後一個任務;非同步任務指的是,不進入主執行緒、而進入”任務佇列”(task queue)的任務,只有”任務佇列”通知主執行緒,某個非同步任務可以執行了,該任務才會進入主執行緒執行。
具體來說,非同步執行的執行機制如下。(同步執行也是如此,因為它可以被視為沒有非同步任務的非同步執行。)
(1)所有同步任務都在主執行緒上執行,形成一個執行棧(execution context stack)。
(2)主執行緒之外,還存在一個”任務佇列”(task queue)。只要非同步任務有了執行結果,就在”任務佇列”之中放置一個事件。
(3)一旦”執行棧”中的所有同步任務執行完畢,系統就會讀取”任務佇列”,看看裡面有哪些事件。那些對應的非同步任務,於是結束等待狀態,進入執行棧,開始執行。
(4)主執行緒不斷重複上面的第三步。只要主執行緒空了,就會去讀取”任務佇列”,這就是JavaScript的執行機制。這個過程會不斷重複。
三、事件和回撥函式
“任務佇列”是一個事件的佇列(也可以理解成訊息的佇列),IO裝置完成一項任務,就在”任務佇列”中新增一個事件,表示相關的非同步任務可以進入”執行棧”了。主執行緒讀取”任務佇列”,就是讀取裡面有哪些事件。
“任務佇列”中的事件,除了IO裝置的事件以外,還包括一些使用者產生的事件(比如滑鼠點選、頁面滾動等等)。只要指定過回撥函式,這些事件發生時就會進入”任務佇列”,等待主執行緒讀取。
所謂”回撥函式”(callback),就是那些會被主執行緒掛起來的程式碼。非同步任務必須指定回撥函式,當主執行緒開始執行非同步任務,就是執行對應的回撥函式。
“任務佇列”是一個先進先出的資料結構,排在前面的事件,優先被主執行緒讀取。主執行緒的讀取過程基本上是自動的,只要執行棧一清空,”任務佇列”上第一位的事件就自動進入主執行緒。但是,由於存在後文提到的”定時器”功能,主執行緒首先要檢查一下執行時間,某些事件只有到了規定的時間,才能返回主執行緒。
四、Event Loop
主執行緒從”任務佇列”中讀取事件,這個過程是迴圈不斷的,所以整個的這種執行機制又稱為Event Loop(事件迴圈)。
五、定時器
除了放置非同步任務的事件,”任務佇列”還可以放置定時事件,即指定某些程式碼在多少時間之後執行。這叫做”定時器”(timer)功能,也就是定時執行的程式碼。
定時器功能主要由setTimeout()和setInterval()這兩個函式來完成,它們的內部執行機制完全一樣,區別在於前者指定的程式碼是一次性執行,後者則為反覆執行。
判斷一個單詞是否是迴文?
迴文是指把相同的詞彙或句子,在下文中調換位置或顛倒過來,產生首尾迴環的情趣,叫做迴文,也叫回環。比如 mamam redivider
function checkPalindrom(str) {
return str == str.split('').reverse().join('');
}
reverse() 方法用於顛倒陣列中元素的順序。
去掉一組整型陣列重複的值
比如輸入: [1,13,24,11,11,14,1,2]
輸出: [1,13,24,11,14,2]
需要去掉重複的11 和 1 這兩個元素。
let unique = function(arr) {
let hashTable = {};
let data = [];
for(let i=0,l=arr.length;i<l;i++) {
if(!hashTable[arr[i]]) {
hashTable[arr[i]] = true;
data.push(arr[i]);
}
}
return data
}
module.exports = unique;
ES6的陣列去重方式
利用展開運算子和Set成員的唯一性
let arr = [1, 2, 3, 2, 1];
function unique(arr){
return [...new Set(arr)];
}
console.log(unique(arr)) // [1, 2, 3]
獲取淘寶首頁共用了多少種標籤:
new Set([...document.querySelectorAll("*")].map(v=>v.nodeName)).size
統計一個字串出現最多的字母
輸入 : afjghdfraaaasdenas
輸出 : a
function findMaxDuplicateChar(str) {
if(str.length == 1) {
return str;
}
let charObj = {};
for(let i=0;i<str.length;i++) {
if(!charObj[str.charAt(i)]) {
charObj[str.charAt(i)] = 1;
}else{
charObj[str.charAt(i)] += 1;
}
}
let maxChar = '',
maxValue = 1;
for(var k in charObj) {
if(charObj[k] >= maxValue) {
maxChar = k;
maxValue = charObj[k];
}
}
return maxChar;
}
module.exports = findMaxDuplicateChar;
排序演算法
氣泡排序
function bubbleSort(arr) {
for(let i = 0,l=arr.length;i<l-1;i++) {
for(let j = i+1;j<l;j++) {
if(arr[i]>arr[j]) {
let tem = arr[i];
arr[i] = arr[j];
arr[j] = tem;
}
}
}
return arr;
}
module.exports = bubbleSort;
快速排序
function quickSort(arr) {
if(arr.length<=1) {
return arr;
}
let leftArr = [];
let rightArr = [];
let q = arr[0];
for(let i = 1,l=arr.length; i<l; i++) {
if(arr[i]>q) {
rightArr.push(arr[i]);
}else{
leftArr.push(arr[i]);
}
}
return [].concat(quickSort(leftArr),[q],quickSort(rightArr));
}
module.exports = quickSort;
找出下列正陣列的最大差值比如:
輸入 [10,5,11,7,8,9]
輸出 6
function getMaxProfit(arr) {
var minPrice = arr[0];
var maxProfit = 0;
for (var i = 0; i < arr.length; i++) {
var currentPrice = arr[i];
minPrice = Math.min(minPrice, currentPrice);
var potentialProfit = currentPrice - minPrice;
maxProfit = Math.max(maxProfit, potentialProfit);
}
return maxProfit;
}
webpack打包AMD、CMD、Common、UMD理解
webpack可以實現的功能:可以打包 AMD、CMD、Common、css\、coffee、json、Image 等均可打包,也可以打包自定義字尾的檔案,如:.vue、.jsx 等,都可以通過loaders載入器進行處理打包。
webpack特性:
- 將js、css等檔案視為一個模組,將外部或者第三方檔案也視為一個模組
- 實現按需載入,是瀏覽器能夠在最短時間開啟專案
- 適合大型專案操作
AMD/CMD/CommonJs是JS模組化開發的標準,目前對應的實現是RequireJs/SeaJs/nodeJs.
CommonJs主要針對服務端,AMD/CMD主要針對瀏覽器端,所以最容易混淆的是AMD/CMD
CommonJS
CommonJS 載入模組是同步的,所以只有載入完成才能執行後面的操作。
CommonJS定義的模組分為:{模組引用(require)} {模組定義(exports)} {模組標識(module)}
CommonJs 是伺服器端模組的規範,Node.js採用了這個規範。
根據CommonJS規範,一個單獨的檔案就是一個模組。載入模組使用require方法,該方法讀取一個檔案並執行,最後返回檔案內部的exports物件。
AMD((Asynchromous Module Definition)
AMD 是 RequireJS 在推廣過程中對模組定義的規範化產出
AMD非同步載入模組。它的模組支援物件 函式 構造器 字串 JSON等各種型別的模組。
CMD
CMD是SeaJS 在推廣過程中對模組定義的規範化產出
AMD/CMD區別
很多人說requireJS是非同步載入模組,SeaJS是同步載入模組,這麼理解實際上是不準確的,其實載入模組都是非同步的,只不過AMD依賴前置,js可以方便知道依賴模組是誰,立即載入,而CMD就近依賴,需要使用把模組變為字串解析一遍才知道依賴了那些模組,這也是很多人詬病CMD的一點,犧牲效能來帶來開發的便利性,實際上解析模組用的時間短到可以忽略。
- AMD是預載入,在並行載入js檔案同時,還會解析執行該模組(因為還需要執行,所以在載入某個模組前,這個模組的依賴模組需要先載入完成);而CMD是懶載入,雖然會一開始就並行載入js檔案,但是不會執行,而是在需要的時候才執行。
- AMD優點:載入快速,尤其遇到多個大檔案,因為並行解析,所以同一時間可以解析多個檔案。
AMD缺點:並行載入,非同步處理,載入順序不一定,可能會造成一些困擾,甚至為程式埋下大坑。 - CMD優點:因為只有在使用的時候才會解析執行js檔案,因此,每個JS檔案的執行順序在程式碼中是有體現的,是可控的。
CMD缺點:執行等待時間會疊加。因為每個檔案執行時是同步執行(序列執行),因此時間是所有檔案解析執行時間之和,尤其在檔案較多較大時,這種缺點尤為明顯。
UMD
UMD是AMD和CommonJS的糅合
AMD模組以瀏覽器第一的原則發展,非同步載入模組。
CommonJS模組以伺服器第一原則發展,選擇同步載入,它的模組無需包裝(unwrapped modules)。
這迫使人們又想出另一個更通用的模式UMD (Universal Module Definition)。希望解決跨平臺的解決方案。
UMD先判斷是否支援Node.js的模組(exports)是否存在,存在則使用Node.js模組模式。
在判斷是否支援AMD(define是否存在),存在則使用AMD方式載入模組。
web前端效能優化
轉載:http://blog.csdn.net/mahoking/article/details/51472697
一、瀏覽器訪問優化
1、減少http請求,合理設定 HTTP快取
2、使用瀏覽器快取
3、啟用壓縮
4、CSS Sprites:合併 CSS圖片,減少請求數的又一個好辦法。
5、LazyLoad Images(圖片懶載入)
6、CSS放在頁面最上部,javascript放在頁面最下面
7、非同步請求Callback(就是將一些行為樣式提取出來,慢慢的載入資訊的內容)
8、減少cookie傳輸
9、Javascript程式碼優化
10、CSS選擇符優化
11、CDN加速
12、反向代理:傳統代理伺服器位於瀏覽器一側,代理瀏覽器將http請求傳送到網際網路上,而反向代理伺服器位於網站機房一側,代理網站web伺服器接收http請求。
前端js圖片壓縮
FileReader()
toDataURL()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>js壓縮圖片</title>
<script src="jquery.js"></script>
</head>
<body>
<input type="file" name="file" id="file">
<div id="container"></div>
<script>
/*圖片地址
https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E9%AB%98%E6%B8%85%E7%BE%8E%E5%A5%B3%20%E4%B8%9D%E8%A2%9C%E5%B7%A8%E4%B9%B3&step_word=&hs=0&pn=1&spn=0&di=57234189540&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=2&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=-1&cs=3589338782%2C536437810&os=3988412231%2C488396405&simid=3515890414%2C233897128&adpicid=0&lpn=0&ln=1389&fr=&fmq=1490709487003_R&fm=result&ic=0&s=undefined&se=&sme=&tab=0&width=&height=&face=undefined&ist=&jit=&cg=&bdtype=0&oriquery=&objurl=http%3A%2F%2Fwww.bz55.com%2Fuploads%2Fallimg%2F150416%2F139-1504161AK9.jpg&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bkzcc_z%26e3Bv54AzdH3F4jtgektzitAzdH3F8l9c9_z%26e3Bip4s&gsm=0&rpstart=0&rpnum=0
*/
$(function(){
$("#file").on("change",function(){
var file=this.files[0];
photoCompress(file,50,$("#container")[0])
});
})
/*
三個引數
file:一個是檔案(型別是圖片格式),
w:一個是檔案壓縮的後寬度,寬度越小,位元組越小
objDiv:一個是容器或者回調函式
photoCompress()
*/
function photoCompress(file,w,objDiv){
var ready=new FileReader();
/*開始讀取指定的Blob物件或File物件中的內容. 當讀取操作完成時,readyState屬性的值會成為DONE,如果設定了onloadend事件處理程式,則呼叫之.同時,result屬性中將包含一個data: URL格式的字串以表示所讀取檔案的內容.*/
ready.readAsDataURL(file);
ready.onload=function(){
var re=this.result;
canvasDataURL(re,w,objDiv)
}
}
function canvasDataURL(re,w,objDiv){
var newImg=new Image();
newImg.src=re;
var imgWidth,imgHeight,offsetX=0,offsetY=0;
newImg.onload=function(){
var img=document.createElement("img");
img.src=newImg.src;
imgWidth=img.width;
imgHeight=img.height;
var canvas=document.createElement("canvas");
canvas.width=w;
canvas.height=w;
var ctx=canvas.getContext("2d");
ctx.clearRect(0,0,w,w);
if(imgWidth>imgHeight){
imgWidth=w*imgWidth/imgHeight;
imgHeight=w;
offsetX=-Math.round((imgWidth-w)/2);
}else{
imgHeight=w*imgHeight/imgWidth;
imgWidth=w;
offsetY=-Math.round((imgHeight-w)/2);
}
ctx.drawImage(img,offsetX,offsetY,imgWidth,imgHeight);
var base64=canvas.toDataURL("image/jpeg",0.7);
if(typeof objDiv == "object"){
objDiv.appendChild(canvas);
}else if(typeof objDiv=="function"){
objDiv(base64);
}
}
}
</script>
</body>
</html>
photoCompress()
傳進引數就可以實現壓縮了,這是上傳圖片的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>js壓縮圖片</title>
<script src="jquery.js"></script>
</head>
<body>
<input type="file" name="file" id="file">
<div id="container"></div>
<script>
/*跨域是無法做的*/
$(function(){
var newImg=new Image();
newImg.src="./timg.jpg";
newImg.onload=function(){
var currentImg=document.createElement("img");
currentImg.src=newImg.src;
photoCompress(currentImg,50,$("#container")[0])
}
})
/*
三個引數
file:一個是檔案(型別是圖片格式),
w:一個是檔案壓縮的後寬度,寬度越小,位元組越小
objDiv:一個是容器或者回調函式
photoCompress()
*/
function photoCompress(file,w,objDiv){
if(file.tagName.toLocaleLowerCase()=="img"){
canvasDataURL(file.src,w,objDiv);
return false;
}
var ready=new FileReader();
/*開始讀取指定的Blob物件或File物件中的內容. 當讀取操作完成時,readyState屬性的值會成為DONE,如果設定了onloadend事件處理程式,則呼叫之.同時,result屬性中將包含一個data: URL格式的字串以表示所讀取檔案的內容.*/
ready.readAsDataURL(file);
ready.onload=function(){
var re=this.result;
canvasDataURL(re,w,objDiv)
}
}
function canvasDataURL(re,w,objDiv){
var newImg=new Image();
newImg.src=re;
var imgWidth,imgHeight,offsetX=0,offsetY=0;
newImg.onload=function(){
var img=document.createElement("img");
img.src=newImg.src;
imgWidth=img.width;
imgHeight=img.height;
var canvas=document.createElement("canvas");
canvas.width=w;
canvas.height=w;
var ctx=canvas.getContext("2d");
ctx.clearRect(0,0,w,w);
if(imgWidth>imgHeight){
imgWidth=w*imgWidth/imgHeight;
imgHeight=w;
offsetX=-Math.round((imgWidth-w)/2);
}else{
imgHeight=w*imgHeight/imgWidth;
imgWidth=w;
offsetY=-Math.round((imgHeight-w)/2);
}
ctx.drawImage(img,offsetX,offsetY,imgWidth,imgHeight);
var base64=canvas.toDataURL("image/jpeg",0.7);
if(typeof objDiv == "object"){
objDiv.appendChild(canvas);
}else if(typeof objDiv=="function"){
objDiv(base64);
}
}
}
</script>
</body>
</html>
前端跨域知識總結
產生跨域的原因
1、瀏覽器限制
2、傳送xhr請求
3、跨域:只要協議、域名、埠有任何一個不同,都被當作是不同的域。
URL | 說明 | 是否允許通訊 |
---|---|---|
http://www.a.com/a.js http://www.a.com/b.js |
同一域名下 | 允許 |
http://www.a.com/lab/a.js http://www.a.com/script/b.js |
同一域名下不同資料夾 | 允許 |
http://www.a.com:8000/a.js http://www.a.com/b.js |
同一域名,不同埠 | 不允許 |
http://www.a.com/a.js https://www.a.com/b.js |
同一域名,不同協議 | 不允許 |
http://www.a.com/a.js http://70.32.92.74/b.js |
域名和域名對應ip | 不允許 |
http://www.a.com/a.js http://script.a.com/b.js |
主域相同,子域不同 | 不允許 |
http://www.a.com/a.js http://a.com/b.js |
同一域名,不同二級域名(同上) | 不允許(cookie這種情況下也不允許訪問) |
http://www.cnblogs.com/a.js http://www.a.com/b.js |
不同域名 | 不允許 |
特別注意兩點:
第一,如果是協議和埠造成的跨域問題“前臺”是無能為力的,
第二:在跨域問題上,域僅僅是通過“URL的首部”來識別而不會去嘗試判斷相同的ip地址對應著兩個域或兩個域是否在同一個ip上。
“URL的首部”指window.location.protocol +window.location.host,也可以理解為“Domains, protocols and ports must match”。
- document.domain + iframe (只有在主域相同的時候才能使用該方法)
- jsonp:動態建立script
- location.hash + iframe
- window.name + iframe
- postMessage(HTML5中的XMLHttpRequest Level 2中的API)
- CORS
- web sockets
跨域解決辦法之jsonp:
jsonp傳送的不是xhr請求,一般ajax請求(xhr)返回的是json物件,而jsonp返回的是script程式碼
jsonp的弊端:
1、伺服器需要改動程式碼支援
2、只支援Get
3、傳送的不是xhr請求