最近看了一篇文章为:Mastering Hard Parts of JavaScript
里面主要包含以下部分:
- Callbacks & Higher order functions Closure
- scope and executioncontext
- JavaScript & the event loop
- Classes & Prototypes (OOP)
这篇文章列举了很多例子进行练习,有助于我进行学习。
我把这篇文章中我觉得很不错的例子列举出来,然后附上我自己的答案和自己的一些理解。
也欢迎大家一起思考,不要一开始看答案,先尝试自己去写,然后就会发现很多自己觉得很了解的知识点,其实都还有盲区,一点点尝试,一点点成长,每天一个小例子,真的会很开心哦~~。
另外要有其他的答案,欢迎评论区留言,(已完结)
下面开始正篇:
第一部分 Callbacks
Q1
写一个add函数,实现将数组中的值全部加2,其中加2的功能已经提供。
例如:console.log(add([1, 2, 3], addTwo)),输出结果应为[3,4,5]
function addTwo(num) {
return num + 2
}
function add (arr,callback) {
// 要写的代码
}
console.log(add([1, 2, 3], addTwo))
我的答案:
第一种:
function add(arr,callback) {
let newArr = []
for(let item of arr) {
newArr.push(callback(item))
}
return newArr
}
第一种方式使用了for…of…的用法,这里要注意for…of输出的是数组的值,for…in输出的数组的索引,并且输出的索引是字符串哦。
for(let item in arr) {
console.log(typeof item) //string,string,string
console.log(item) // 0,1,2
}
第二种:
function add(array, callback) {
const newArr = [];
array.forEach(item => {
newArr.push(callback(item));
});
return newArr;
}
第三种:
function add (arr,callback) {
let newArray = arr.map(item => callback(item))
return newArray
}
Q2
模拟累加器的功能,将数组的数值进行加和。注意:不可以直接使用reduce!
例如:数组为[4,1,3],输出的值为8
const nums = [4, 1, 3];
const add = function (a, b) {
return a + b;
}
function reduce() {
// 要写的代码
}
console.log(reduce(nums, add, 0))
console.log(reduce(nums, add))
我的答案:
function reduce(array,callback,initalValue) {
let accum //定义一个累加器
if(arguments.length > 2) {
//有初始值
accum = initalValue
} else {
//无初始值
accum = array[0]
array.shift() //数组第一个值为初始值,需要将第一个值排除
}
array.forEach(item => {
accum = callback(item,accum)
});
return accum
}
在这部分中我犯了两个错误:
- 我没有考虑到没有初始值的问题:其实
else{accum = array[0]}
的这部分代码也是看作者的答案才知道的。我们提供给别人一个函数功能时候,其实应该考虑全面,将多种情况都覆盖。另外,这个代码也还有问题,就是我没有加校验和报错,当其他人传一个参数,或者传入的参数不合规时,就会有问题。作为一个例子可以够用,但是作为要提供给其他人用的函数,就还有很多要完善的。 - 在我考虑了无初始值之后,添加了条件判断,但是我只考虑了
accum = array[0]
,却忘了将已经作为初始值的数排除,即没有加array.shift()
看着代码没有多少,但是要考虑的问题很多。
Q3
将多个数组中共有的数值提取出来。
例如:[5, 10, 15, 20], [15, 88, 1, 5, 7], [1, 10, 15, 5, 20],[5,12,1,15]); //输出结果为[5,15]
function intersection() {
//代码部分
}
console.log(intersection([5, 10, 15, 20], [15, 88, 1, 5, 7], [1, 10, 15, 5, 20],[5,12,1,15]))
我的答案:
function intersection(...arrays) {
let array = arrays.reduce((totalArray,currentArray) => {
return currentArray.filter(item => totalArray.includes(item))
})
return [...new Set(array)]
}
我的思考:
写这个答案时,我考虑用过map和filter结合的方式,不过后来发现循环好多啊,算了吧… 后来发现reduce和filter结合,真香~~,功能强大代码还少。
- 上一题模拟过reduce的简单用法,reduce里面用法有一项就是没有传入初始值时,取传入参数的第一个值。在这题中初始值就是
arrays[0]
。 - 在传参数时候,因为不知道参数有多少个,用的扩展运算符(…)
- 之前有一个版本的代码,如下:
function intersection(...arrays) {
return arrays.reduce((acc, array) => {
return array.filter((item) => acc.includes(item));
})
}
这个代码是可以实现题中的答案,但是当我们数组中有重复的数字,如console.log(intersection([5, 5,10, 15, 20], [15, 10, 1, 5, 7], [1, 10, 15, 5, 20],[5,12,1,15]))
,就会出现问题,因为没有去重。
Q4
返回一个数组,里面包含所有数组的元素,去除重复的元素
例如:[5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5],输出结果为[5, 10, 15, 88, 1, 7, 100]
function union() {
// 代码部分
}
console.log(union([5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5])) //[5, 10, 15, 88, 1, 7, 100]
我的答案:
第一种:
function union (...arrays) {
const flatArray = arrays.flat()
return [...new Set(flatArray)]
}
第二种:
function union(...arrays) {
return arrays.reduce((totalArray,currentArray) => {
let array = currentArray.filter(item => !totalArray.includes(item))
return totalArray.concat(array)
})
}
我的思考:
有了上一题的经验,这个功能实现就很容易
Q5
构造一个函数objOfMatches,它接受两个数组和一个回调。objOfMatches将构建一个对象并返回它。为了构建对象,objOfMatches将使用回调测试第一个数组的每个元素,以查看输出是否与第二个数组的相应元素(按索引)匹配。如果存在匹配项,则第一个数组中的元素将成为对象中的键,而第二个数组中的元素将成为对应的值。
例如:
function objOfMatches(array1, array2, callback) {
//代码部分
}
console.log(
objOfMatches(
[&