一、使用base_64編碼圖片或SVG圖片代替原始的png與jpeg圖片,再像素要求不高的狀況下使用jpeg圖片代替png圖片vue
二、圖片懶加載,在頁面上的未可視區域能夠添加一個滾動條事件,判斷圖片位置與瀏覽器頂端 的距離與頁面的距離,若是前者小於後者,優先加載。jquery
- 原生JavaScript實現圖片的懶加載
- jQuery插件 jquery.lazy
- vue中使用 vue-lazyload
- mint-ui 插件內置懶加載組件
複製代碼
三、圖片的預加載,若是爲幻燈片、相冊等,可使用圖片預加載技術,將當前展現圖片的前一張和後一張優先 下載。初始化的時候得到圖片的src以後爲每個元素提早添加圖片的地址路徑。保證再第二張圖片顯示的時候已經加載到頁面當中瀏覽器
實現方法:循環圖片數據,實例化對象的方式建立圖片元素 new image() 動態綁定每個image的src屬性,並追加到DOM流中
複製代碼
JS 中分爲七種內置類型,七種內置類型又分爲兩大類型:基本類型和對象(Object)。bash
基本類型有六種: null,undefined,boolean,number,string,symbol。閉包
對象(Object)是引用類型,在使用過程當中會遇到淺拷貝和深拷貝的問題。app
let a = { name: 'FE' }
let b = a
b.name = 'EF'
console.log(a.name) // EF
複製代碼
typeof 對於基本類型,除了 null 均可以顯示正確的類型模塊化
想得到一個變量的正確類型,能夠經過 Object.prototype.toString.call(xx)函數
- 新生成了一個對象
- 連接到原型
- 綁定this
- 返回新對象
複製代碼
function create() {
// 建立一個空的對象
let obj = new Object()
// 得到構造函數
let Con = [].shift.call(arguments)
// 連接到原型
obj.__proto__ = Con.prototype
// 綁定 this,執行構造函數
let result = Con.apply(obj, arguments)
// 確保 new 出來的是個對象
return typeof result === 'object' ? result : obj
}
複製代碼
判斷對象屬於某一個類,回去查找對象的constructor的prototype
複製代碼
function foo() {
console.log(this.a)
}
var a = 1
foo()
var obj = {
a: 2,
foo: foo
}
obj.foo()
複製代碼
以上二者狀況 this
只依賴於調用函數前的對象,優先級是第二個狀況大於第一個狀況優化
如下狀況是優先級最高的,this
只會綁定在 c
上,不會被任何方式修改 this
指向ui
var c = new foo()
c.a = 3
console.log(c.a)
複製代碼
還有種就是利用 call,apply,bind 改變 this,這個優先級僅次於 new
function a() {
return () => {
return () => {
console.log(this)
}
}
}
console.log(a()()())
複製代碼
箭頭函數實際上是沒有 this 的,這個函數中的 this 只取決於他外面的第一個不是箭頭函數的函數的 this。在這個例子中,由於調用 a 符合前面代碼中的第一個狀況,因此 this 是 window。而且 this 一旦綁定了上下文,就不會被任何代碼改變
一、做用域
種類:JS中有三種做用域,全局做用域,函數做用域,ES6新推出塊級做用域
概念:一個變量的可訪問規則,再函數建立的時候就已經定義好做用域,整個的JS文件執行有一個最外層的全局做用域(window)
使用: 本做用域內部的全部變量均可已再本做用域內部訪問,外部沒法訪問。內部可訪問上級做用域變量,本做用於內部所用使用var聲明的變量會有一個做用域提高的過程,let與const聲明的變量沒有變量提高
二、做用域鏈
一個變量的訪問規則的鏈式操做
能夠把它理解成包含自身變量對象和上級變量對象的列表,經過 [[Scope]] 屬性查找上級變量
當訪問一個變量的時候,先在本做用域內部進行查找,若是沒有去上級做用域進行查找,直到全局做用域window下面,都沒有,返回undefined
一、特色:
內層做用域能夠訪問外層做用域的變量
閉包就是可以讀取其餘函數內部變量的函數
函數 A 返回了一個函數 B,而且函數 B 中使用了函數 A 的變量,函數 B 就被稱爲閉包。
閉包函數引用的變量是存儲在堆上的,因此說,當閉包函數彈出調用棧以後,閉包返回的函數依然能調用到閉包函數的變量
二、優勢:
使用閉包能夠造成獨立的空間,延長變量的生命週期,保存中間狀態值
能夠封裝一些私有變量,外部沒法進行直接訪問(例如用戶登錄狀態計數器)建立當即執行函數(閉包)實現JS模塊化封裝
解決var聲明的循環語句變量沒法長久保存的問題
三、缺點:
濫用閉包函數會形成內存泄露,由於閉包中引用到的包裹函數中定義的變量都 永遠不會被釋放,因此咱們應該在必要的時候,及時釋放這個閉包函數,將再也不使用的閉包引用設置爲null;
因爲函數內部的變量都被保存在內存中, 會致使內存消耗大;
四、相關代碼:
for ( var i=1; i<=5; i++) {
setTimeout( function timer() {
console.log( i );
}, i*1000 );
}
// 每次循環都會輸出 5 沒法保存變量
複製代碼
for (var i = 1; i <= 5; i++) {
(function(j) {
setTimeout(function timer() {
console.log(j);
}, j * 1000);
})(i);
}
// 建立當即執行函數,造成閉包,保存每一次循環的變量
複製代碼
// 解決下列調用打印每次都是5的問題
var arr = []
for (var i = 0; i < 5; i++) {
arr.push(function() { console.log(i) })
}
// 使用閉包的方式
for (var i = 0; i < 5; i++) {
(function(i) {
arr.push(function() {
console.log(i)
})
})(i)
}
// 使用ES6的let建立塊級做用域
for (let i = 0; i < 5; i++) {
arr.push(function() {
console.log(i)
})
}
// 使用setTimeout的第三個參數
for (let i = 0; i < 5; i++) {
setTimeout(function() {
arr.push(function() {
console.log(i)
})
}, 0,i)
}
複製代碼