1.为什么要手写代码?
我们在日常开发过程中,往往都是取出来直接用,从来不思考代码的底层实现逻辑,但当我开始研究一些底层的东西的时候,才开始理解了JavaScript每个方法和函数的底层实现思路,我认为这可以很好的提高我们的代码水平和逻辑思维。
2.手写实现数组方法
2.1 push
push 从后面添加元素 返回push完以后数组的长度
2.1.1 基本使用
let arr = [1, 2];
console.log(arr.push(1, 2, 3)); // 5
console.log(arr); // [1,2,1,2,3]
2.1.2 手写实现
数组方法在数组的原型对象上
Array.prototype.myPush = function () {
for (let i = 0; i < arguments.length; i++) {
// this就是调用该方法的数组arr,
// 数组当前最后一项的索引为 this.length - 1,再往后面加索引就为this.length
this(this.length) = arguments[i]
}
return this.length
};
调用测试
正常打印
console.log(arr.myPush(1, 2, 3)); // 5
console.log(arr); // [1,2,1,2,3]
2.2 pop
删除数组的最后一位元素,返回被删除的那个元素。此方法更改数组的长度。
2.2.1 基本使用
let arr = [1, 2, 3];
console.log(arr.pop()); // 3
console.log(arr); // [1,2]
2.2.2 手写实现
Array.prototype.myPop = function () {
let result = this[this.length - 1];
this.length = this.length - 1;
return result;
};
console.log(arr.myPop()); // 3
console.log(arr); // [1,2]
2.3 shift
从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
2.3.1 基本使用
let arr = [1, 2, 3];
console.log(arr.shift()); // 1
console.log(arr); // [2,3]
2.3.2 手写实现
Array.prototype.myShift = function () {
let result = this[0];
for (let i = 0; i < this.length; i++) {
// 后面的元素依次赋给前一项
// 因为数组的第一个元素已经删除
this[i] = this[i + 1];
}
// 改变数组长度
this.length--;
// 返回被删除的元素
return result;
};
console.log(arr.myShift()); // 1
console.log(arr); // [2,3]
2.4 unshift
将一个或多个元素添加到数组的开头,并返回该数组的新长度。
2.4.1 基本使用
let arr = [1, 2, 3];
console.log(arr.unshift(4, 5)); // 5
console.log(arr); // [4,4,1,2,3]
2.4.2 手写实现
Array.prototype.myUnshift = function () {
// 最终数组的长度sum = 原数组长度 + unshift传入的参数的个数
let sum = this.length + arguments.length;
for (let i = sum; i > 0; i--) {
// 如果还没往后遍历到传入的参数的时候
// 原数组的值依次往向后赋值
if (i > arguments.length) {
this[i - 1] = this[i - 1 - arguments.length];
} else {
this[i - 1] = arguments[i - 1];
}
}
return sum;
};
console.log(arr.myUnshift(4, 5)); // 5
console.log(arr); // [4,5,1,2,3]
2.5 splice
2.5.1 基本使用
splice() 方法用于添加或删除数组中的元素。会改变原始数组。
语法:
array.splice(index,howmany,item1,.....,itemX)
第一个参数index:必需。规定从何处添加/删除元素。
第二个参数howmany:可选。规定应该删除多少元素。必须是数字,但可以是 “0”。
后续参数:可选。要添加到数组的新元素
使用示例
不传入参数,不进行操作,返回[],原数组不发生改变
let arr = [1, 2, 3, 4];
console.log(arr.splice()); // []
console.log(arr); // [1, 2, 3, 4]
传入一个参数index 删除索引1后面的元素,原数组发生改变
let arr = [1, 2, 3, 4];
console.log(arr.splice(1)); // [2,3,4]
console.log(arr); // [1]
传入两个参数index howmany,从索引0开始删除 2 个元素
let arr1 = [1, 2, 3, 4];
console.log(arr1.splice(0, 2)); // [1,2]
console.log(arr1); // [3,4]
传入三个参数 index howmany 其他参数,从索引0开始删除2个元素,并用后面的参数替换。
let arr2 = [1, 2, 3, 4];
console.log(arr2.splice(0, 2, 5, 6)); // [1,2]
console.log(arr2); // [5,6,3,4]
2.5.2 手写实现
Array.prototype.mySplice = function (index, num, ...args) {
let newArr = [];
let returnArr = [];
// 如果没有传入参数,直接返回空数组
if (index == undefined || num == 0) return [];
if (index < 0) index = index + this.length;
// 如果没有传入截取数组的长度,自己手动计算
if (!num) {
// 这里是将num转换为索引值,方便后续的遍历
num = this.length - index + 1;
} else if (num > 0) {
num = num + index;
}
// 遍历index之前的数组,赋给newArr
for (let i = 0; i < index; i++) {
newArr.push(this[i]);
}
// 遍历我们要删除的数组范围
for (; index < num; index++) {
returnArr.push(this[index]);
}
// 如果传入其他参数,就传入的参数添加进去
if (args.length > 0) {
newArr.push(...args);
}
// 遍历num后面的数组,赋给newArr
for (let i = num; i < this.length; i++) {
newArr.push(this[i]);
}
// newArr 是我们想要的原数组的值
for (let i = 0; i < newArr.length; i++) {
this[i] = newArr[i];
}
// 截取长度
this.length = newArr.length;
return returnArr;
};
console.log(arr.mySplice());
console.log(arr.mySplice(1)); // [2,3,4]
console.log(arr); // [1]
let arr1 = [1, 2, 3, 4];
console.log(arr1.mySplice(0, 0)); // [1,2]
console.log(arr1); // [3,4]
let arr2 = [1, 2, 3, 4];
console.log(arr2.mySplice(0, 2, 5, 6)); // [1,2]
console.log(arr2); // [5,6,3,4]
2.6 fill
2.6.1 基本使用
fill() 方法用于将一个固定值替换数组的元素。
语法:
array.fill(value, start, end)
第一个参数value:必需。填充的值。
第二个参数start:可选。开始填充位置。
第三个参数end:可选。停止填充位置 (默认为 array.length)
使用示例
let arr = [1, 2, 3, 4];
console.log(arr.fill(4));
console.log(arr); // [4, 4, 4, 4]
arr.fill(5, 0, 2);
console.log(arr); // [5, 5, 4, 4]
console.dir(Array.prototype);
2.6.2 手写实现
Array.prototype.myFill = function (value, start = 0, end = this.length) {
if (start && start < 0) start = this.length + start;
if (end && end < 0) end = this.length + end;
for (; start < end; start++) {
this[start] = value;
}
return this;
};
console.log(arr.fill(4));
console.log(arr); // [4, 4, 4, 4]
arr.fill(5, 0, 2);
console.log(arr); // [5, 5, 4, 4]
2.7 reverse
2.7.1 基本使用
reverse() 方法用于反转数组中元素的顺序。
let arr = [1, 2, 3, 4, 5];
arr.reverse();
console.log(arr); // [5, 4, 3, 2, 1]
2.7.2 手写实现
Array.prototype.myReverse = function () {
let len = this.length - 1;
for (let i = 0; i < Math.floor(this.length / 2); i++) {
// 交换这两个元素位置
let temp = arr[i];
arr[i] = arr[len];
arr[len--] = temp;
}
return this;
};
arr.myReverse();
console.log(arr); // [5, 4, 3, 2, 1]
2.8 sort
2.8.1 基本使用
sort() 方法用于对数组的元素进行排序。
排序顺序可以是字母或数字,并按升序或降序。
默认排序顺序为按字母升序。
这种方法会改变原始数组!
这里只是实现了对数字的排序,大家有具体的思路可以评论区讨论
使用实例
let arr = [1, 3, 2, 4];
arr.sort((a, b) => b - a);
console.log(arr); // [4,3,2,1]
2.8.2 手写实现
利用冒泡排序进行重构。
Array.prototype.mySort = function (callback) {
// 使用了冒泡排序
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) {
let temp = this[j];
this[j] = this[j + 1];
this[j + 1] = temp;
}
}
return this;
}
};
arr.mySort((a, b) => a - b);
console.log(arr);
2.9 copyWithin
2.9.1 基本使用
copyWithin() 方法用于从数组的指定位置拷贝元素到数组的另一个指定位置中。
语法:
array.copyWithin(target, start, end)
第一个参数target:必需。复制到指定目标索引位置。
第二个参数start:可选。元素复制的起始位置。默认起始位置为0
第三个参数end:可选。停止复制的索引位置 (默认为 array.length)。如果为负值,表示倒数。文章来源:https://www.toymoban.com/news/detail-503028.html
使用示例:
复制数组的前面两个元素到第三和第四个位置上:文章来源地址https://www.toymoban.com/news/detail-503028.html
let arr = [1, 2, 3, 4, 5];
arr.copyWithin(2, 0, 2);
console.log(arr); // [1, 2, 1, 2, 5]
2.9.2 手写实现
Array.prototype.myCopyWithin = function (target, start = 0, end = this.length) {
let newArr = [];
if (target < 0) target = this.length + target;
if (start < 0) start = this.length + start;
if (end < 0) end = this.length + end;
for (let i = start; i < end; i++) {
newArr.push(this[i]);
}
let arrLength = newArr.length;
let k = 0;
// 同时判断赋值的区间和待拷贝数组的长度的大小
let len = arrLength < this.length - target ? target + arrLength : this.length;
for (; target < len; target++) {
console.log(newArr[k]);
this[target] = newArr[k++];
}
return this;
};
欢迎大家在讨论学习,感谢大家支持 |
到了这里,关于JavaScript 手写代码 第五期(重写数组方法一)-可以改变原数组的方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!