前端總結·基礎篇·JS(二)數組深拷貝、去重以及字符串反序和數組(Array)


前端總結系列

目錄

這是《前端總結·基礎篇·JS》系列的第二篇,主要總結一下JS數組的使用、技巧以及常用方法。


一、數組使用
	1.1 聲明數組
	1.2 訪問數組
	1.3 類型檢測
二、常用技巧
	2.1 數組去重
	2.2 數組深拷貝
	2.3 字符串反序
三、方法列表
	3.1 存取
	3.2 字符串
	3.3 修改
	3.4 ES5
	3.5 ES2015(ES6)
	3.6 ES2016

一、數組使用

數組不是基本數據類型,但是非常常用,所以提前總結。

基本數據類型是String,Number,Boolean,null,undefined。

  • Boolean只有兩個狀態,true/false
  • null一般是開發者定義
  • undefined是JS引擎拋出的異常,通常在發現調用未聲明的變量時拋出

1.1 聲明數組

數組用中括號括起來,不同的值用逗號隔開。數組內的值有字符串需要用單引號或者雙引號引起來。

var arr = []  // 聲明一個空數組
var arr = [3,6,8,9]  // 聲明一個包含值3,6,8,9的數組
var arr = new Array(3,6,8,9)  // 創建一個數組對象

1.2 訪問數組

下標訪問

數組的下標是從0開始的,最后一個值的下標是數組長度減去1。訪問數組可以直接訪問具體下標的一個值,也可以直接訪問整個數組的值。


var arr = [1,2,3,4]

console.log(arr)  // 直接訪問數組 |  [1, 2, 3, 4]
console.log(arr[0])  // 通過下標訪問 | 1
console.log(arr.length)  // 訪問數組的長度 | 4

遍歷訪問

如果需要逐個的訪問數組中的值,你需要對數組進行遍歷。可以用一般的for循環、for in或者ES6中的for of。


var arr = [1,2,3,4]

// for
for(var x = 0; x < arr.length; x++){
	console.log(arr[x])  // 通過下標訪問
}

// for in
for(x in arr){
	console.log(arr[x])  // 通過下標訪問
}

// for of (ES6)
for(x of arr){
	console.log(x)  // 不需要通過下標訪問
}

1.3 類型檢測

檢測一個對象有以下方法。更精確的檢測數組請見請見jwalden


* typeof []  // object
* [] instanceof Array  // false
* Array.isArray([])  // true | 通常用來檢測數組
	* Array.isArray(Array.prototype)  // true | 這是一個例外情況

二、常用技巧

2.1 數組合並

可以用concat/push合並。concat返回合並后的新數組,push保存在原數組里。

  • 感謝園友 @loveyatou 提醒。在push方法中把apply寫成了call,導致結果不符合預期。現已修正。 2017/03/17 13:45

  • PS:call和apply都是用來改變函數作用域的,用法基本一致,唯獨傳遞參數的方法不一致。call是逐個輸入,逗號隔開。apply是全部放在一個數組內。


var a = [1,2,3]
var b = [4,5,6]

// concat 方法

var c = a.concat(b)
console.log(c)  // [1, 2, 3, 4, 5, 6]

// push 方法

Array.prototype.push.apply(a,b)
console.log(a)  // [1, 2, 3, 4, 5, 6]

2.2 數組深拷貝

我們可以根據concat/slice方法返回新數組的特性來進行深拷貝,也可以直接用循環語句暴力深拷貝。

  • 把數組賦值給一個變量,只是復制了一個指向數組的指針(又叫引用)
  • 當我們改變原數組的值,新數組的值也跟着改變
  • 為了避免這樣,你需要對數組進行深拷貝

// 深拷貝前

var arr = [1,2,3,4]
var newArr = arr  // 把原數組賦值給新數組

arr.pop()  // 刪除原數組的一個值
console.log(arr)  // 測試原數組的值 [1, 2, 3]
console.log(newArr)  // 測試新數組的值 [1, 2, 3]

// 深拷貝后

var arr = [1,2,3,4]
var newArrCopy = arr.concat()  // 開始深拷貝,此處也可以使用arr.slice()

arr.pop()  // 刪除原數組的一個值
console.log(arr)  // 測試原數組的值 [1, 2, 3]
console.log(newArrCopy)  // 測試新數組的值 [1, 2, 3, 4]

// 暴力深拷貝

var arr = [1,2,3,4]
var newArr = []  // 為了使用數組的push方法,一定要定義數據類型為數組
for (var x = 0; x < arr.length; x++){
	newArr.push(arr[x])  // 用循環逐個把值保存在新數組內
}

arr.pop()  // 刪除原數組的一個值
console.log(arr)  // 測試原數組的值 [1, 2, 3]
console.log(newArr)  // 測試新數組的值 [1, 2, 3, 4]

2.3 數組去重

排序后去重,更多請見腳本之家


var newArr = arr.sort()  // 排好序再比較
var newArrSaved = [newArr[0]]  // 初始化為數組,用來存儲最后的數據
for(var i =2;i<arr.length;i++){  // 從第二個開始
	if(newArr[i]!==newArr[i-1])  // 判斷當前值和上一個值是否一致
	newArrSaved.push(newArr[i])  // 不一致則存在newArrSaved
}

2.4 字符串反序

首先將字符串序列化成數組,通過數組方法對數組反序,最后把數組轉換成字符串。


'I See U.'.split('').reverse().join('')  // ".U eeS I"

三、方法列表

ES5和ES6部分就當作參考手冊吧,有時間再琢磨一下應用場景。

以下實例在此基礎上進行


arr = [1,2,3,4]

3.1 存取

push在尾部添加,pop從尾部刪除。

尾存取


push(element1, ..., elementN) 
	* arr.push(8)  // [1, 2, 3, 4, 5]
pop()
	* arr.pop()  // [1, 2, 3, 4]

首存取

unshift在首部添加,shift從首部刪除。


unshift(element1, ..., elementN)
	* arr.unshift(5)  // [5, 1, 2, 3, 4]

shift
	* arr.shift()  // [1, 2, 3, 4]

3.2 轉換

字符串

join默認以逗號分隔連接的字符串,傳入參數可以進行自定義分割方式。


toString()
	* arr.toString()  // "1,2,3,4"
toLocalString()
	* arr.toLocalString()  // 和上面的效果一致,此方法僅在特殊語言中需要
join(separator)
	* arr.join()  // "1,2,3,4"
	* arr.join('')  // "1234"
	* arr.join('-')  // "1-2-3-4"

3.3 修改

排序

reverse把數組顛倒,sort對數組排序。sort默認按照unicode排序,傳入function(a,b)可以自定義排序。更多請見MDN(內有對象按屬性值排序的方法)


reverse()
	* arr.reverse()  // [4, 3, 2, 1]
sort()
	* arr.sort()  // [1, 2, 3, 4] 這個已經排好了序,所以不變

連接

concat連接數組,並返回一個新的數組。


concat(value1[, value2[, ...[, valueN]]])
	arr.concat(9)  // [1, 2, 3, 4, 9]

切割

切割比上面的稍微復雜點

  • slice為提取元素,splice為刪除指定范圍元素並添加新元素。slice的第二個參數,是結束的位置標記,不會包括在返回值內。

  • slice的返回值是提取元素組成的新數組。splice的返回值是刪除元素組成的新數組,原始元素被修改。

  • slice在IE<9下使用時,會出現一些問題,需要使用膩子腳本。詳見MDN


slice(begin,end)
	* arr.slice(1,3)  // [2, 3]
splice(start, deleteCount, item1, item2, ...)
	* arr.splice(1,3,5)  // [2, 3, 4] 返回值
	* console.log(arr)  // [1, 5]  原始元素被修改

3.4 ES5

需要精確檢測數組請見jwalden


數組檢查

Array.isArray(obj)  // 檢查是否為數組,返回值為true/false,兼容IE9+
	* Array.isArray([1,2,3])  // true
	* Array.isArray('123')  // false
	* Array.isArray(Array.prototype)  // true
arr.every(callback[, thisArg])
	* function isNotZero(element, index, array){return element!==0}
	* arr.every(isNotZero)  // true
arr.map(callback[, thisArg])  // 每個值都調用一次函數並且返回新數組
	* function twice(element, index, array){return element*element}
	* arr.map(twice)  // [1, 4, 9, 16]
arr.reduce(callback,[initialValue])  // 將多維數組轉為一維數組
arr.some(callback[, thisArg])  // 測試元素是否通過指定測試
arr.indexOf(searchElement[, fromIndex = 0])  // 返回滿足條件的第一個索引,不存在返回-1
	* arr.indexOf(3)  // 2
arr.lastIndexOf(searchElement[, fromIndex = arr.length - 1])  // 由后向前查找
arr.forEach(callback[, thisArg])  // 對數組每個元素執行一次函數

3.5 ES2015(ES6)


Array.of(element0[, element1[, ...[, elementN]]])  // 創建新數組
	* Array.of(3)  // [3]
	* Array(3)  // [undefined × 3]
	* Array.of([1,2,3])  // [Array[3]]
	* Array([1,2,3])  // [Array[3]]

Array.from(arrayLike[, mapFn[, thisArg]])  // 從類數組對象或可遍歷對象中創建數組
	* Array.from('berg')  // ["b", "e", "r", "g"]

arr.copyWithin(target, start, end)  // 選定數組值,在一定范圍內全部粘貼選定值
	* arr.copyWithin(1,2,3)  // [1, 3, 3, 4]

arr.entries()  // 返回新的數組迭代器(一定得復制給變量再迭代)
	* var newArr = arr.entries()
	* newArr.next().value  // [0, 1]
	* newArr.next().value  // [1, 2]
	* newArr.next().value  // [2, 3]
	* newArr.next().value  // [3, 4]

arr.keys()  // 返回新的數組迭代器

arr.fill(value, start, end)  // 用指定值填充一定范圍數組
	* arr.fill(0,1,3)  // [1, 0, 0, 4]

arr.filter(callback[, thisArg])  // 將滿足條件的元素返回成新數組
	* function isNotZero(element){return element!==0}
	* arr.filter(isNotZero)  // [1, 2, 3, 4]

arr.find(callback[, thisArg])  // 返回滿足條件的第一個值,不存在返回undefined
	* function isNotZero(element){return element!==0}
	* arr.find(isNotZero)  // 1

arr.findIndex(callback[, thisArg])  // 返回滿足條件的第一個元素的索引
	* function isNotZero(element){return element!==0}
	* arr.findIndex(isNotZero)  // 0

3.6 ES2016


arr.includes(searchElement, fromIndex)  // 判斷數組是否包含指定值,返回true/false
	arr.includes(2)  // true

總結

  • 上一周一直在忙活Note這個小項目,現在已經上線了。以后會逐步增大項目復雜度。並且嘗試用Vue和RN來分別對項目進行重構,后端則逐步接入Node.js和mongoDB。兼容性支持IE9及以上,根據IE7/8訪客基數決定是否兼容。
  • 接下來的時間就安心的總結JS和更博客吧。關於Note開發過程中遇到的問題,以及解決方案,等整理好了再發出來。

文章主要參考的站點

ES5

前端兼容性方案


免責聲明!

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



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