最近參與了公司的 Vue + ElementUI 後臺管理系統開發,目前項目告一段落,正好作一個總結。javascript
本文件分三部分進行,其一是 JavaScript 部分,其二是 Vue 部分,最後是 ElementUI 部分。java
在 C#,Java 等面向對象的高級語言中,能夠直接經過 '='
賦值操做符複製一個對象,若是想定義一個指向對象的代理要用到指針定義,然而 Js 早期出於性能的考慮,默認將 '='
賦值操做符用於定義一個指向對象的指針。數組
var a = { prop: 'val' }
var b = a
a.prop = 'nothing'
console.log(b.prop) // 'nothing'複製代碼
不管怎樣 「複製」,新對象老是指向原始對象,原始對象發生改變,新對象也天然改變。如何複製對象呢?咱們知道,對象能夠互相嵌套,即對象屬性能夠是另外一個對象,那麼經過普通的循環遍從來複制原對象的屬性到一個新對象中是沒法確保二者保持一致的,所以這種複製也被稱做 「淺拷貝」。相對的經過遞歸遍從來複制對象的方式也被稱做 「深拷貝」。函數
// 淺拷貝
function extendCopy(p) {
var c = {};
for (var i in p) {
c[i] = p[i];
}
c.uber = p;
return c;
}複製代碼
// 深拷貝
function deepCopy(p, c) {
var c = c || {};
for (var i in p) {
if (typeof p[i] === 'object') {
c[i] = (p[i].constructor === Array) ? [] : {};
deepCopy(p[i], c[i]); // 遞歸調用
} else {
c[i] = p[i];
}
}
return c;
}複製代碼
固然,能夠在項目中引入函數庫(如 utils.js
)來方便的引用這些擴展函數,不過咱們不得不想有沒有更簡潔的方式來實現呢?答案是確定的。性能
// utils.js
export const extendCopy(p) {...}
export const deepCopy(p, c) {...}複製代碼
// page.js
import {extendCopy, deepCopy} from utils.js
a = {...}
b = extendCopy(a)複製代碼
通常還能夠經過以下方式解決:ui
stringify
和 parse
方法組合使用的方式實現。// 勉強也算一句話解決了,問題在於性能不理想。
var a = {}
var b = JSON.parse(JSON.stringify(a))複製代碼
// 這種方式的缺點在於要以字面量的形式定義一個原始對象做爲模板。
a = function() {
return { prop:"123" }
}
b = a()
d = a()
b === d // false複製代碼
Object.assign()
方法來複制。// 簡潔明瞭,性能良好的解決方案
var a = {}
var b = Object.assign({},a)複製代碼
經過上面的例子,咱們不可貴出一個結論:使用 Object.assign()
方法複製一個對象是比較理想的解決方案。spa
早期的 Js 標準中並無實現相似 array.contains(item)
的方法,所以只能經過元素在集合中的索引判斷。(感謝 XiaozhongLiu 的提醒,ES7中已加入 Array.includes()
方法。)代理
// 傳統寫法
var isSelected = function(row) {
return (selection || []).indexOf(row) > -1;
}
// ES7寫法,簡潔了許多
isSelected = selection.includes(row)複製代碼
首先 null 的類型是對象,若是在控制檯輸入 typeof null
會返回 "object"
,事實上咱們要檢測一個非空數組,就要先排除 null
值的可能。指針
var isObject = function(obj) {
return obj !== null && typeof obj === 'object'
}複製代碼
這裏用到了數組的 filter
方法,此方法具備如下特色:code
filter
執行時會對數組中的每個元素執行一遍回調函數。filter
的返回值爲一個新數組,其成員爲原數組中返回值爲 true
的元素。var users = allUsers.filter((user) => user.loged === true)複製代碼
在 Js 中兩個空對象進行比較會有什麼結果呢?
var a = {}
a === {} // false複製代碼
在 Js 中對 object
類型的數據應用 「等於」 操做符時,比較的是兩個變量是否指向同一個引用,也就是說在內存中是否爲同一個地址。
而咱們期待的結果是比較兩個對象在邏輯上是否具備相同的屬性,空對象是一個特例,它們不具備任何屬性。
if (Object.keys(search).length !== 0) {
args = Object.assign({}, args, search)
}複製代碼
這裏用到 Object.keys()
方法,獲取對象鍵的集合並判斷其長度是否爲 0
便可。
for (let i = 0, let j = delIds.length - 1; i < j; i++) {
allItems.splice(delIds[i], 0)
}複製代碼
如上,根據索引來循環刪除原始數組中的元素是否可行呢?若是咱們執行這段代碼是沒法獲得預期結果的。緣由在於,當前面的元素被刪除時,後面元素的索引起生了變化,繼續用刪除前的索引就沒法定位正確的元素,解決的方法有兩種:
for (let i = delIds.length - 1; i > 0; i--) {
allItems.splice(delIds[i], 0)
}複製代碼
delItems.forEach ((item) => {
allItems.splice(allItems.indexOf(item), 0)
})複製代碼
(未完待續...)