ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-10-18 19:02:33  阅读:127  来源: 互联网

标签:callbackfn 进阶 JavaScript len length let Let 手写 throw


进阶练习:手写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

标签:callbackfn,进阶,JavaScript,len,length,let,Let,手写,throw
来源: https://blog.csdn.net/sharp0016/article/details/120831656

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有