0%

FreeCodeCamp-JavaScript习题解答记录

本人所有解答并非最优或最简洁的解法,大部分步骤可以压缩或省略,写出来只为便于理解。

所有解答均有详细注释。

Reverse a String

翻转字符串

  • 描述:
  • 先把字符串转化成数组,再借助数组的.reverse()方法翻转数组顺序,最后把数组转化成字符串
  • 解答:
1
2
3
4
5
6
7
function reverseString(str) {
//把字符串用split方法转化成数组并翻转,得到["o","l","l","e","h"]
var arr = str.split("").reverse();
//把数组用join方法拼接,得到新字符串"olleh"
return arr.join("");
}
reverseString("hello"); //"olleh"

Factorialize a Number

计算一个整数的阶乘

  • 描述:
  • 如果用字母n来代表一个整数,阶乘代表着所有小于或等于n的整数的乘积
    阶乘通常简写成n!
    例如: 5! = 1 * 2 * 3 * 4 * 5 = 120
  • 解答:
  • 根据阶乘定义,负数违法,01的阶乘等于1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function factorialize(num) {
if (num < 0) { //参数小于0
return false; //返回假
}
else { //参数大于等于0
if (num <= 1) { //如果参数等于0或1,则返回1
return 1;
}
else { //如果参数大于1,则返回参数的阶乘
for (i = num - 1; i >= 1; i--) { //1️⃣ num=5 i=4 i>=1(true) num=5*4=20
num *= i; //2️⃣ num=20 i=3 i>=1(true) num=20*3=60
} //3️⃣ num=60 i=2 i>=1(true) num=600*2=120
//4️⃣ num=120 i=1 i>=1(true) num=120*1=120
return num; //5️⃣ num=120 i=0 i>=1(fasle) num=120
}
}
}
factorialize(5); //120

Check for Palindromes

检查回文字符串

  • 描述:
  • 如果给定的字符串是回文,返回true,反之,返回false
    如果一个字符串忽略标点符号、大小写和空格,正着读和反着读一模一样,那么这个字符串就是palindrome(回文)
    注意你需要去掉字符串多余的标点符号和空格,然后把字符串转化成小写来验证此字符串是否为回文
    函数参数的值可以为racecarRaceCarrace CAR
  • 解答:
1
2
3
4
5
6
7
8
9
10
11
12
function palindrome(str) {
var regexp = /[^A-Za-z0-9]/g; //设置正则表达式:所有非字母和数字(全局)
str = str.replace(regexp, "").toLowerCase(); //匹配正则表达式,将参数中所有非字母和数字替换为空(""),并将所有字母小写
var verStr = str.split("").reverse().join(""); //将参数中的所有字符分割并翻转后重新拼接成新的字符串
if (verStr == str) { //对比原字符串和翻转后的字符串,如果相等返回true
return true;
}
else { //不相等则返回false
return false;
}
}
palindrome("0_0 (: /-\ :) 0-0"); // 返回true (正则表达式处理后字符串得到"0000",翻转后得到"0000","0000"=="0000")

Find the Longest Word in a String

找出最长单词

  • 描述:
  • 在句子中找出最长的单词,并返回它的长度。
    函数的返回值应该是一个数字。
  • 解答:
1
2
3
4
5
6
7
8
function findTheLongestWord(str) {
var arr = str.split(" "); //按空格分割字符串存入数组
arr.sort(function (a, b) { //用.sort()方法对数组内元素进行排序
return b.length - a.length; //将数组内元素按长度降序
});
return arr[0].length; //返回数组内第一个元素的长度
}
findTheLongestWord("The quick brown fox jumped over the lazy dog"); //6:"jumped"

Title Case a Sentence

句中单词首字母大写

  • 描述:
  • 确保字符串的每个单词首字母都大写,其余部分小写。
    theof这样的连接符同理。
  • 解答:
1
2
3
4
5
6
7
8
9
10
11
function titleCase(str) {
var arr = str.toLowerCase().split(" "); //将字符串所有单词小写并按空格分割存入数组
var newArr = []; //定义新数组用来存放首字母大写后的单词
for (i = 0; i < arr.length; i++) { //遍历数组中的每个元素
var fristCharacter = arr[i][0]; //定义首字母(此定义没有必要,此处只为视图清晰和便于理解)
var titleCaseWord = arr[i].replace(fristCharacter, fristCharacter.toUpperCase()); //将所有单词首字母大写
newArr.push(titleCaseWord); //将首字母大写后的单词用.push()方法添加进新数组
}
return newArr.join(" "); //用.join()方法将新数组中的单词按空格拼接成新字符串
}
titleCase("I'm a little tea pot"); //"I'm A Little Tea Pot"

Return Largest Numbers in Arrays

找出多个数组中的最大数

  • 描述:
  • 右边大数组中包含了4个小数组,分别找到每个小数组中的最大值,然后把它们串联起来,形成一个新数组。
    提示:你可以用for循环来迭代数组,并通过arr[i]的方式来访问数组的每个元素。
  • 解答:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function largestOfFour(arr) {
var largestNumArr = []; //定义新数组用来存放每个小数组中的最大值
for (i = 0; i < arr.length; i++) { //遍历参数中的每个元素
var newArr = arr[i].sort(function (a, b) {
return b - a; //对每个小数组中的元素用.sort()方法进行降序排列
});
largestNumArr[i] = newArr[0]; //设置新数组的每一项为原数组中每个小数组的最大值
}
return largestNumArr; //返回新数组 [5,27,39,1001]
}
largestOfFour([
[4, 5, 1, 3],
[13, 27, 18, 26],
[32, 35, 37, 39],
[1000, 1001, 857, 1]
]);

Confirm the Ending

检查字符串结尾

  • 描述:
  • 判断一个字符串str是否以指定的字符串target结尾。
    如果是,返回true如果不是,返回false
  • 解答:
1
2
3
4
5
6
7
8
9
10
11
function confirmEnding(str, target) {
var lastCharacterLength = target.length; //定义需匹配结尾长度为所给参数长度(此定义没有必要,此处只为视图清晰和便于理解)
//用.substr()方法从str.length-lastCharacterLength位置开始,获取lastCharacterLength个字符
//例:字符串长度为11(asifadeaway),需匹配结尾长度为4(away),则从字符串第7(11-4)位"a"开始获取四个字符(包含开始位置的字符)"away"
if (str.substr(-lastCharacterLength, lastCharacterLength) == target) { //判断获取到的字符和所给参数是否相同
return true; //相同返回真
} else {
return false; //不相同返回假
}
}
confirmEnding("asifadeaway", "away"); //返回true:"away"=="away"

Repeat a string repeat a string

重复输出字符串

  • 描述:
  • 重复一个指定的字符串num次,如果num是一个负数则返回一个空字符串
  • 解答:
1
2
3
4
5
6
7
8
9
10
11
12
function repeat(str, num) {
if (num > 0) { //判断所给次数是否是正数
var repeatedStr = ""; //定义重复后的字符串为空
for (i = num; i > 0; i--) { //设置重复次数为所给次数
repeatedStr += str; //拼接原字符串num次
}
return repeatedStr; //返回重复后的字符串
} else { //是负数则返回空字符串
return "";
}
}
repeat("Qian", 3); //"QianQianQian"

Truncate a string

截断字符串

  • 描述:
  • 如果字符串的长度比指定的参数num长,则把多余的部分用...来表示。
    切记,插入到字符串尾部的三个点号也会计入字符串的长度。
    但是,如果指定的参数num小于或等于3,则添加的三个点号不会计入字符串的长度。
  • 解答:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function truncate(str, num) {
var strLength = str.length; //定义字符串长度(此定义没有必要,此处只为视图清晰和便于理解)
if (strLength > num) { //判断字符串长度是否大于所给长度
if (num > 0 && num <= 3) { //若所给长度大于0且小于等于3
str = str.slice(0, num) + "..."; //从第一个字符开始取num个字符并和"..."拼接成新字符串
return str; //返回新字符串
} else if (num > 3) { //若所给长度大于3,则三个点号也会计入字符串的长度
str = str.slice(0, num - 3) + "..."; //从第一个字符开始取num-3个字符并和"..."拼接成新字符串
return str; //返回新字符串
} else { //若所给长度小于0
return false; //返回假
}
} else { //若字符串长度小于所给长度则返回原字符串
return str;
}
}
truncate("Pour a little out for the ones who passed away.", 20); //"Pour a little out..."

Chunky Monkey

分割数组

  • 描述:
  • 把一个数组arr按照指定的数组大小size分割成若干个数组块。
    例如:chunk([1,2,3,4],2)=[[1,2],[3,4]];chunk([1,2,3,4,5],2)=[[1,2],[3,4],[5]]
  • 解答:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function chunk(arr, size) {
var newArr = []; //定义新数组用来存放分割后的数组
for (i = 0; i < arr.length; i += size) { //遍历所给数组的每个元素
var slicedArr = arr.slice(i, i + size); //定义用.slice()方法从原数组中每次提取的新数组(此定义没有必要,此处只为视图清晰和便于理解)
//1️⃣ i=0 i<4(true) slicedArr=arr.slice(0,2) => ["a","i"]
//2️⃣ i=0+2=2 i<4(true) slicedArr=arr.slice(2,4) => ["f","a"]
//3️⃣ i=0+2+2=4 i<4(false) 跳出循环
newArr.push(slicedArr); //将提取的数组添加进定义的新数组
//1️⃣ newArr=[["a","i"]]
//2️⃣ newArr=[["a","i"],["f","a"]]
}
return newArr;
}
chunk(["a", "i", "f", "a"], 2); //[["a","i"],["f","a"]]

Slasher Flick

截断数组

  • 描述:
  • 返回一个数组被截断n个元素后还剩余的元素,截断从索引0开始。
  • 解答:
  • 用.splice()方法截取数组,此方法会改变原数组
1
2
3
4
5
function slasher(arr, howMany) {
arr.splice(0, howMany); //从原数组第[0]位元素开始,删除howMany个元素(包含开始位元素)
return arr; //从[0]1开始删除2个元素(包含[0]1),因为会改变原数组,所以原数组变为[3]
}
slasher([1, 2, 3], 2); //[3]

Falsy Bouncer

过滤数组假值

  • 描述:
  • 删除数组中的所有假值。
    JavaScript中,假值有falsenull0""undefinedNaN
  • 解答:
1
2
3
4
function bouncer(arr) {
return arr.filter(Boolean); //返回数组中所有为true的元素
}
bouncer([1, null, NaN, 2, undefined]); //[1,2]

Seek and Destroy

摧毁数组

  • 描述:
  • 实现一个destroyer()函数,第一个参数是待摧毁的数组,其余的参数是待摧毁的值。
  • 解答:
1
2
3
4
5
6
function destroyer(arr) {
var arr_arg = arguments//定义新数组用来存放传入的所有参数
for (var i = 1; i < arr_arg.length; i++) { arr = arr.filter(function (val) { return arr_arg[i] !== val; }); }
return arr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3); //[1,1]

Where do I belong

数组排序并找出元素索引

  • 描述:
  • 先给数组排序,然后找到指定的值在数组的位置,最后返回位置对应的索引。
    举例:where([1,2,3,4], 1.5) 应该返回1。因为1.5插入到数组[1,2,3,4]后变成[1,1.5,2,3,4],而1.5对应的索引值就是1。同理:where([20,3,5],19)应该返回2。因为数组会先排序为[3,5,20],19插入到数组[3,5,20]后变成[3,5,19,20],而19对应的索引值就是2。
  • 解答:
1
2
3
4
5
6
7
8
9
10
function where(arr, num) {
arr.push(num); //将所给数字添加进所给数组
for (i = 0; i < arr.length; i++) { //遍历数组所有元素
arr.sort(function (a, b) {
return a - b; //对数组内所有数字用.sort()方法降序排序
});
}
return arr.indexOf(num); //返回所给数字在数组中的索引值
}
where([40, 60], 50); //1

Caesars Cipher

凯撒密码

  • 描述:
  • 下面我们来介绍风靡全球的凯撒密码Caesar cipher,又叫移位密码。
    移位密码也就是密码中的字母会按照指定的数量来做移位。
    一个常见的案例就是ROT13密码,字母会移位13个位置。由'A' ↔ 'N''B' ↔ 'O',以此类推。
    写一个ROT13函数,实现输入加密字符串,输出解密字符串。
    所有的字母都是大写,不要转化任何非字母形式的字符(例如:空格,标点符号),遇到这些特殊字符,跳过它们。
  • 解答:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function rot13(str) {
var arr = str.toUpperCase().split(''); //把所给加密字符串全部大写后按字符分割存入新数组
for (var i = 0; i < arr.length; i++) { //遍历数组
var charCodeA = arr[i].charCodeAt(0); //定义charCodeA为加密字符串的所有字符的Unicode编码
var charCodeB = charCodeA - 13; //定义charCodeB为输入的加密字符串Unicode编码-13后得到的解密字符串Unicode编码
if (charCodeA >= 65 && charCodeA <= 90) { //判断字符是不是字母(A[65]-Z[90])
if (charCodeB < 65) { //若解密后字符串Unicode编码超出字母的编码表
arr[i] = String.fromCharCode(charCodeA + 13);
//例1️⃣:某字母?[?]加密后为A[65],则解密为?[65-13]此时超出字母表13位,则从Z[90]开始减去13位(需保留第13位字母) => ?[(90-13)+1]=A[65+13]=N[78]
//例2️⃣:某字母?[?]加密后为B[66],则解密为?[66-13]此时超出字母表12位,则从Z[90]开始减去12位(需保留第12位字母) => ?[(90-12)+1]=B[66+13]=O[79]
//由此可知,加密后为前13位的字母,解密可以直接表示为加密后的字符Unicode编码+13
} else { //若解密后字符串Unicode编码未超出字母的编码表,则直接向前位移(不包含开始位)13位即可
arr[i] = String.fromCharCode(charCodeB);
}
} else { //不转化任何非字母形式的字符
arr[i] = arr[i];
}
str = arr.join(""); //拼接数组元素得到解密后的的字符串
}
return str;
}
rot13("NF V SNQRNJNL..."); //AS I FADEAWAY...