进阶练习:手写JavaScript数组多个方法的底层实现

2021/10/18 20:11:45

本文主要是介绍进阶练习:手写JavaScript数组多个方法的底层实现,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

进阶练习:手写JavaScript数组多个方法的底层实现

先了解一下push方法的底层实现:
下面是ECMA的英文相关解释
When the push method is called with zero or more arguments
the following
steps are taken:
1.Let O be ? To0bject(this value).2.Let len be ? LengthOfArrayLike(O).
3.Let argCount be the number of elements in items.
4. If len + argCount > 2453- 1, throw a TypeError exception.5. For each element E of items, do
a.Perform ? Set(0,!ToString(F(len)), E, true).b. Set len to len + 1.
5. Perform ? Set(0, “length”, F(len), true).7.Return F(len).
下面我们将上述的英文转化成代码

Array.prototype.push = function(...items){
let O = Object(this); // ecma中提到的先转换为对象let len = this. length >>>0;
let argCount = items.length >>> O;//2453-1为JS能表示的最大正整数if (len + argCount > 2** 53- 1){
throw new TypeError("The number of array is over the max
value)
}
for(let i= 0; i<argCount; i++){O[len +i] = items[i];
}
let newLength = len + argCount;O.length = newLength;
return newLength;}

你会发现有些变量再进行无符号位移,你可以自己研究一下
pop的底层实现
下面是ECMA的英文注解:
When the pop method is called, the following steps are taken:1. Let O be ? ToObject(this value).
6. Let len be ? LengthOfArrayLike(O).3. If len = 0, then
Perform ? Set(0, “length”,+OF, true).Return undefined.
7. Else,
Assert: len > 0.
Let newLen be F(len - 1).
Let index be ! ToString(newLen).Let element be ? Get(0, index).
Perform ? DeletePropertyOrThrow(0, index).Perform ? Set(0, “length”, newLen, true).Return element.
下面我们将上述内容转化为代码实现:

Array. prototype.pop = function(){let O = Object(this);
let len = this.length >>> 0;if (len === 0){
0.length = 0;return undefined;}
len --,
let value = O[len];delete O[len];0.length = len;return value;}

map方法的底层实现
下面依然是ECMA的标准解释
When the map method is called with one or two arguments, the following steps are taken:1.Let O be ? To0bject(this value).
2.Let len be ? LengthOfArrayLike(O).
3.If lsCallable(callbackfn) is false, throw a TypeError exception.4. Let A be ? ArraySpeciesCreate(0, len).
8. Let k be 0.
9. Repeat, while k< len,
a. Let Pk be ! ToString(F(k)).
b. Let kPresent be ? HasProperty(O, Pk).c. If kPresent is true, then
Let kValue be ? Get(0, Pk).
Let mappedValue be ? Call(callbackfn, thisArg, kValue,F(k), O 》).Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).d. Set k to k+1.
7.Return A.
下面我们将上述语言转化为代码:

Array.prototype.map = function(callbackFn, thisArg){if(this ===null || this === undefined){
throw new TypeError("Cannot read property 'map' of null");}
if (Object.prototype.toString.call(callbacktn) != ".ODJect runction] ) ithrow new TypeError(callbackfn + ' is not a function')
}
let O = Object(this);let T = thisArg;
let len = 0.length >>>0;let A = new Array(len);
for(let k = 0; k<len; k++){if(k in O){
if(k in O){
let kValue = O[k];
Ⅱ/依次传入this,当前项,当前索引,整个数组
let mappedValue = callbackfn.call(T, KValue,k, O);A[k] = mappedValue;
}
}
return A;}

需要注意一点:遍历类型的方法最后返回的都是一个新数组并不改变原有数组的值,切记
reduce的底层方法实现:
When the reduce method is called with one ortwo arguments, the followingsteps are taken:
1.Let O be ? ToObject(this value).
2.Let len be ? LengthOfArrayLike(O).
10. If lsCallable(callbackfn) is false, throw a TypeError exception.
11. If len =0 and initialValue is not present, throw a TypeError exception.5.Let k be 0.
6.Let accumulator be undefined.
7.If initialValue is present, thenSet accumulator to initialValue.
8. Else,
Let kPresent be false.
Repeat, while kPresent is false and k< len,Let Pk be ! ToString(F(k)).
Set kPresent to ? HasProperty(O, Pk).lf kPresent is true, then
Set accumulator to ? Get(O, Pk).Set k to k+1.
If kPresent is false, throw a TypeError exception.9.Repeat, while k<len,
Let Pk be ! ToString(F(k)).
Let kPresent be ? HasProperty(O, Pk).lf kPresent is true, then
将其转换为代码:

Array.prototype.reduce = function(callbackfn, initialValue){异常处理,和map类似
if (this === null || this === undefined) {
throw new TypeError("Cannot read property 'reduce' of null");}
//处理回调类型异常
if (Object.prototype.toString.call(callbackfn) != "[object Function]"){throw new TypeError(callbackfn + ' is not a function')
}
let O= Object(this);let len = 0.length >>>0;let k=0;
let accumulator = initialValue; // reduce方法第二个参数作为累加器的初始值if (accumulator === undefined){//初始值不传的处理
for(; k<len ; k++){
if(k in O){
accumulator = O[k];k++;
break;}
}
throw new Error('Each element of the array is empty');}
for(;k<len; k++){
if(k in o){
//注意reduce的核心累加器
accumulator = callbackfn.call(undefined,accumulator,o[k],o);
}
}
return accumulator;

默认初始值不传的特殊处理
累计器以及callbackfn的处理逻辑
上述文章如果有问题或者想问问题或者想交流技术或者想和作者闲聊可以+QQ:2029788643



这篇关于进阶练习:手写JavaScript数组多个方法的底层实现的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程