陣列常用方法的簡單封裝
首先回顧有關原型的三句話:
把每個函式當做物件時,有一個屬性prototype,其值是一個物件;
每個prototype都有一個constructor屬性,指向prototype屬性所在建構函式;
每個物件都有一個__proto__
屬性,指向所屬類的原型。
陣列基本操作方法
以下方法均改變原陣列,需要運算元組的 length 屬性
Push
- 返回值:新陣列的長度
- 思路:陣列的長度等於
arguments[i]
Array.prototype.myPush = function () {
for (let i = 0; i < arguments.length; i++) {
this[this.length] = arguments[i];
}
return this.length;
};
Pop
- 返回值:刪除的項(如果空陣列,返回 undefined)
- 思路:讓陣列長度 -1
Array.prototype.myPop = function () {
return this.length==0?undefined:(this[this.length - 1],this.length--);
};
Shift
- 返回值:刪除的項
- 思路:讓陣列前一個值
this[i]
等於後一個值this[i + 1]
,之後把陣列長度 -1
Array.prototype.myShift = function () {
if (this.length == 0) {
return;
}
let del = this[0];
for (let i = 0; i < this.length; i++) {
this[i] = this[i + 1];
}
this.length--;
return del;
};
Unshift
- 返回值:新陣列的長度
- 思路:讓陣列後一個值
this[i]
等於前 n(n=arguments.length
)個值this[i - arguments.length]
,之後把前 n 個值填為arguments[i]
Array.prototype.myUnshift = function () {
this.length += arguments.length;
for (let i = this.length - 1; i >= 0; i--) {
if (i >= arguments.length) {
this[i] = this[i - arguments.length];
} else {
this[i] = arguments[i];
}
}
return this.length;
};
- ES6 方法實現能簡單一些。其實就是拼接陣列,之後把拼接的陣列一項一項賦值給原陣列
Array.prototype.myUnshift = function (...arg) {
var newArr = [...arg, ...this];
for (let i = 0; i < newArr.length; i++) {
this[i] = newArr[i];
}
return this.length;
};
陣列操作方法
以下方法除splice(改變原陣列)均不改變原陣列
splice(特殊)
因為 push 實現比較簡單,這裡用到了 push 方法,能簡寫一兩行
-
返回值:刪除的項(陣列)
-
思路:按引數數量分別進行判定
- 引數小於等於1個,從 start 開始新增到新陣列,並把新增那項刪除(陣列長度也減少)
- 引數大於1個,先進行刪除(跟上一步相同)再把陣列分成三份,左邊+中間被替換的項+右邊,合併陣列
注意:
- 第一個引數為負數:如果轉換為正數,大於陣列長度,直接轉換為0;小於等於陣列長度,需加上陣列長度
- 第二個引數:如果小於0,直接轉換為0
- 第三個引數起:要新增的項
Array.prototype.mySplice = function (start, del) {
let arr = [];
if (start < 0) {
start = -start > this.length ? 0 : this.length + start;
}
if (arguments.length <= 1) {
for (let i = start; i < this.length; i++) {
arr.push(this[i]);
}
this.length = start;
} else {
del = del < 0 ? 0 : del;
// 刪除陣列這一步
for (let i = 0; i < del; i++) {
arr.push(this[start + i]);
this[start + i] = this[start + i + del];
}
this.length -= del;
let lArr = [];
for (let i = 0; i < start; i++) {
lArr.push(this[i]);
}
for (let i = 0; i < arguments.length - 2; i++) {
lArr.push(arguments[i + 2]);
}
for (let i = start; i < this.length; i++) {
lArr.push(this[i]);
}
for (let i = 0; i < lArr.length; i++) {
this[i] = lArr[i];
}
}
return arr;
};
- 刪除陣列那一步,我第一時間想到的是冒泡(把刪除項一次一次冒到最後一位),最後出來的程式碼是下面這樣(非常麻煩)
let that = del;
for (let i = that; i > 0; i++) {
if (that <= 0) {
break;
}
for (let j = start; j < this.length - 1; j++) {
[this[j], this[j + 1]] = [this[j + 1], this[j]];
}
arr.push(this[this.length - 1]);
this.length--;
that--;
}
- 大可不必這樣,把刪除項的下一位(不刪除)往前挪一個一個覆蓋要刪除的項即可
for (let i = 0; i < del; i++) {
arr.push(this[start + i]);
this[start + i] = this[start + i + del];
}
this.length -= del;
concat
- 返回值:拼接後的新陣列
- 思路:如果引數是陣列需遍歷後一個一個新增到新陣列
Array.prototype.myConcat = function () {
let arr = [];
for (let i = 0; i < this.length; i++) {
arr[i] = this[i];
}
for (let i = 0; i < arguments.length; i++) {
const el = arguments[i];
if (Array.isArray(el)) {
for (let i = 0; i < el.length; i++) {
arr[arr.length] = el[i];
}
} else {
arr[arr.length] = el;
}
}
return arr;
};
slice
- 返回值:複製後的新陣列
- 思路:如果傳參是負數索引,需對其長度進行判定。如果大於陣列長度,將其改為0;小於陣列長度,將其改為
arr.length+(負數索引)
Array.prototype.mySlice = function (start = 0, end = this.length) {
var arr = [];
if (start < 0) {
start = -start > this.length ? 0 : this.length + start;
}
if (end < 0) {
end = -end > this.length ? 0 : this.length + end;
}
for (let i = start; i < end; i++) {
arr.push(this[i]);
}
return arr;
};
flat
- 返回值:扁平後的新陣列
- 思路:遞迴(下面實現沒有加上可以指定遞迴深度的引數,類似
arr.flat(Infinity)
)
Array.prototype.myFlat = function () {
let arr = [];
fn(this);
function fn(ary) {
for (let i = 0; i < ary.length; i++) {
const item = ary[i];
if (Array.isArray(item)) {
fn(item);
} else {
arr.push(item);
}
}
}
return arr;
};
Array.prototype.myFlat = function () {
return this.toString().split(",").map((item) => Number(item));
};
陣列重排方法
reverse
- 返回值:倒序後的陣列
- 思路:第n個數和倒數第n個數兩兩對換
Array.prototype.myReverse = function () {
for (let i = 0, j = this.length - 1; j > i; i++, j--) {
var temp = this[i];
this[i] = this[j];
this[j] = temp;
}
return this;
};
sort
- 返回值:排序後的陣列
- 思路:不傳參的時候,兩兩比較 String(xxx) 的值;傳參的時候判斷
callBack(a-b)
是否大於 0 即可
Array.prototype.mySort = function (callBack) {
if (this.length <= 1) {
return this;
}
if (typeof callBack === "function") {
for (let i = 0; i < this.length - 1; i++) {
for (let j = 0; j < this.length - 1 - i; j++) {
if (callBack(this[j], this[j + 1]) > 0) {
[this[j], this[j + 1]] = [this[j + 1], this[j]];
}
}
}
} else if (typeof callBack === "undefined") {
for (let i = 0; i < this.length - 1; i++) {
for (let j = 0; j < this.length - 1 - i; j++) {
if (String(this[j]) > String(this[j + 1])) {
[this[j], this[j + 1]] = [this[j + 1], this[j]];
}
}
}
} else {
return "引數異常";
}
return this;
};
陣列位置方法
以下方法均不改變原陣列
indexOf
- 返回值:索引/-1
- 思路:遍歷陣列,第二個引數是從哪個索引開始。如果不傳參,從頭查到尾部
Array.prototype.myIndexOf = function (val, index = 0) {
if (index < 0) {
index = -index > this.length ? 0 : index + this.length;
}
for (let i = index; i < this.length; i++) {
if (this[i] === val) {
return i;
}
}
return -1;
};
lastIndexOf
- 返回值:索引/-1
- 思路:遍歷陣列,第二個引數是到哪個索引結束(從0開始到這個索引結束)。如果不傳參,從頭查到尾部
Array.prototype.myLastIndexOf = function (val, index = this.length) {
if (index < 0) {
index = -index >= this.length ? 0 : index + this.length;
}
for (let i = index; i >= 0; i--) {
if (this[i] === val) {
return i;
}
}
return -1;
};
includes
- 返回值:true/false
- 思路:遍歷陣列
Array.prototype.myIncludes = function (val) {
for (let i = 0; i < this.length; i++) {
if (this[i] === val) {
return true;
}
}
return false;
};
陣列迭代方法
以下方法均不改變原陣列
forEach
回撥函式內部 this 一般指向 window
- 返回值:undefined
- 思路:遍歷陣列
Array.prototype.myForEach = function (callBack) {
for (let i = 0; i < this.length; i++) {
let index = i, item = this[i];
callBack(item, index);
}
};
map
- 返回值:對映後的新陣列
- 思路:遍歷陣列,把陣列每以項經過運算後賦值給新陣列
Array.prototype.myMap = function (callBack) {
let arr = [];
for (let i = 0; i < this.length; i++) {
let index = i, item = this[i];
arr[i] = callBack(item, index);
}
return arr;
};
reduce
- 返回值:函式累計處理的結果
- 思路:initial 返回值在陣列的每次迭代中被記住,最後成為最終的結果值
Array.prototype.myReduce = function (callBack, initial) {
if (typeof callBack !== "function") throw new TypeError("callBack must be function");
let i = 0;
if (typeof initial === "undefined") {
initial = this[0];
i = 1;
}
for (; i < this.length; i++) {
initial = callBack(initial, this[i], i)
}
return initial;
};
相關文章
- 專案常用JS方法封裝(四) [ 陣列相關處理 ]JS封裝陣列
- 陣列的常用方法陣列
- 陣列常用的方法陣列
- 陣列常用方法陣列
- 常用陣列方法陣列
- 陣列方法的封裝/程式碼的複用加強陣列封裝
- js常用陣列方法JS陣列
- 常用陣列方法梳理陣列
- 陣列常用物件方法陣列物件
- javascript陣列常用方法JavaScript陣列
- 前端封裝成json資料和json陣列的方法前端封裝JSON陣列
- JDBC常用方法封裝JDBC封裝
- web前端常用的封裝方法Web前端封裝
- IQueryable的簡單封裝封裝
- Retrofit的簡單封裝封裝
- JavaScript 陣列 常用方法(二)JavaScript陣列
- 陣列常用方法補充陣列
- 簡單介紹js 陣列 fill() 填充方法JS陣列
- 陣列中常用的方法總結陣列
- 小程式wx.request()方法簡單封裝封裝
- 【陣列】1608. 特殊陣列的特徵值(簡單)陣列特徵
- JavaScript陣列 幾個常用方法JavaScript陣列
- js陣列常用方法總結JS陣列
- 字串和陣列常用方法整理字串陣列
- JS中字串和陣列的常用方法JS字串陣列
- 常用的幾個陣列方法與數學方法陣列
- Fetch API 簡單封裝API封裝
- BaseActivity與BaseFragment的簡單封裝Fragment封裝
- 一個簡單的 Amqp 封裝MQ封裝
- 【陣列】1394. 找出陣列中的幸運數(簡單)陣列
- Rust中將陣列轉為集合型別的簡單方法Rust陣列型別
- 你不知道的簡單陣列拷貝方法全解陣列
- JS 陣列中常用方法總結JS陣列
- js中陣列常用方法總結JS陣列
- 工作中常用的字串和陣列方法字串陣列
- javascript 陣列(array) 常用的方法集錦(上)JavaScript陣列
- 開發時候常用的js方法封裝JS封裝
- 構建最簡單陣列陣列