Most Important JavaScript Lessons From the Last Two Weeks
Ryan Bassett
Over the last two weeks, I have been practicing JavaScript by solving challenges on Codewars. Many of my solutions worked, but I often solved problems using longer loops and multiple conditions before realizing that JavaScript already had methods that could express the same logic more clearly.
Two methods that stood out to me were:
.some().sort()
Learning these methods showed me that improving as a programmer is not only about getting the correct answer. It is also about learning how to make code shorter, clearer, and easier to understand.
What I Learned From Solving Codewars Kata
Before learning more about array methods, I often approached challenges by manually building the entire solution.
My usual process involved:
- Creating an empty array.
- Writing one or more
forloops. - Comparing values with several
ifandelse ifstatements. - Adding values to a new array with
.push(),.unshift(), or.splice(). - Keeping track of additional variables, indexes, or flags.
This approach helped me understand how the logic worked internally. Even when my solution was longer than necessary, writing it manually taught me how values move through a loop and how conditions control a program.
However, I also learned that many JavaScript array methods already contain common looping behavior.
Lesson One: Using .some()
The .some() method checks whether at least one element in an array passes a test.
The general syntax is:
array.some((element) => {
return condition;
});The method returns a Boolean value:
trueor:
falseFor example:
const numbers = [2, 4, 7, 10];
const hasOddNumber = numbers.some((number) => {
return number % 2 !== 0;
});
console.log(hasOddNumber);
// true
The result is true because the array contains at least one odd number: 7.
Understanding the Callback Parameter
In this example:
numbers.some((number) => {
return number % 2 !== 0;
});the variable number is created as a parameter of the callback function.
JavaScript passes each array element into number, one at a time:
First test:
number = 2
2 % 2 !== 0
falseSecond test:
number = 4
4 % 2 !== 0
falseThird test:
number = 7
7 % 2 !== 0
trueAs soon as .some() finds a result that is true, it can stop checking and return:
trueHow I Used .some() in a Codewars Solution
One Codewars challenge required determining whether two characters had at least one possible replacement letter in common.
Each character could be changed to the letter immediately before or after it in the alphabet.
For example:
d → c or eA helper function returned the possible choices:
function getChoices(letter) {
const alphabet = "abcdefghijklmnopqrstuvwxyz";
const index = alphabet.indexOf(letter);
if (letter === "a") {
return ["b"];
}
if (letter === "z") {
return ["y"];
}
return [
alphabet[index - 1],
alphabet[index + 1]
];
}The following code checked whether at least one value from leftChoices also appeared in rightChoices:
const hasMatchingChoice = leftChoices.some((letter) =>
rightChoices.includes(letter)
);At first, this line was difficult for me to understand because letter was not declared elsewhere in the main function.
I learned that:
(letter) =>creates the callback parameter.
The .some() method supplies each value from leftChoices to that parameter.
For example:
const leftChoices = ["c", "e"];
const rightChoices = ["e", "g"];JavaScript effectively checks:
Is "c" included in ["e", "g"]?
falseThen:
Is "e" included in ["e", "g"]?
trueBecause one matching value exists, .some() returns:
trueThe important lesson was that I did not need to manually write another loop to compare every value.
My Longer Approach Versus .some()
A longer solution might look like this:
let hasMatchingChoice = false;
for (let i = 0; i < leftChoices.length; i++) {
if (rightChoices.includes(leftChoices[i])) {
hasMatchingChoice = true;
break;
}
}The shorter version is:
const hasMatchingChoice = leftChoices.some((letter) =>
rightChoices.includes(letter)
);Both approaches perform similar work.
The longer version helped me understand the process, while the .some() version communicates the purpose more directly:
Does at least one left-side choice exist in the right-side choices?
Lesson Two: Using .sort()
Another Codewars challenge required arranging student names according to two rules:
- Longer names should appear first.
- Names of equal length should appear in reverse alphabetical order.
My original approach involved:
- Sorting the names alphabetically.
- Reversing the array.
- Finding the longest name.
- Creating a new array.
- Looping repeatedly through the original array.
- Adding names according to their lengths.
- Tracking the current target length.
The longer approach helped me understand the sorting rules, but JavaScript’s .sort() method could handle both conditions with one comparison function.
The shorter solution was:
function lineupStudents(students) {
return students
.trim()
.split(/\s+/)
.sort((a, b) =>
b.length - a.length ||
b.localeCompare(a)
);
}Understanding the .sort() Comparison Function
The comparison function receives two values:
(a, b) => {
// Compare a and b
}JavaScript uses the returned number to decide their order.
The general rules are:
Negative number:
a comes before bPositive number:
b comes before aZero:
a and b are considered equal according to this comparisonFor example:
const numbers = [5, 2, 10, 1];
numbers.sort((a, b) => a - b);
console.log(numbers);The result is:
[1, 2, 5, 10]For descending order:
numbers.sort((a, b) => b - a);The result is:
[10, 5, 2, 1]Sorting Names by Length
The first part of the Codewars comparison was:
b.length - a.lengthThis sorts longer names before shorter names.
For example:
const names = [
"Ryan",
"Alexander",
"Sam"
];
names.sort((a, b) =>
b.length - a.length
);
console.log(names);The result is:
[
"Alexander",
"Ryan",
"Sam"
]The comparison uses the difference between the lengths.
If:
a = "Ryan";
b = "Alexander";then:
b.length - a.lengthbecomes:
9 - 4which returns:
5Because the result is positive, b is placed before a.
Understanding the || Operator in the Sort Function
The complete comparison was:
b.length - a.length ||
b.localeCompare(a)The logical OR operator, ||, allows the second sorting rule to run when the first comparison returns 0.
If two names have different lengths:
b.length - a.lengthreturns a nonzero number, and JavaScript uses that result.
For example:
8 - 5 = 3Because 3 is truthy, JavaScript stops evaluating the expression and uses 3 as the comparison result.
If two names have the same length:
b.length - a.lengthreturns:
0Because 0 is falsy, JavaScript continues to the expression after ||:
b.localeCompare(a)This applies the second sorting rule.
The expression:
b.length - a.length ||
b.localeCompare(a)can be thought of as:
Sort by length first. If the lengths are equal, sort in reverse alphabetical order.
Understanding b.localeCompare(a)
The .localeCompare() method compares strings alphabetically.
Normally:
a.localeCompare(b)can be used to sort strings in ascending alphabetical order:
a → zReversing the comparison:
b.localeCompare(a)sorts the strings in descending alphabetical order:
z → aFor names of equal length, this produces the reverse alphabetical ordering required by the challenge.
For example:
const names = [
"xxa",
"xxc",
"xxb"
];
names.sort((a, b) =>
b.localeCompare(a)
);
console.log(names);The result is:
[
"xxc",
"xxb",
"xxa"
]The Complete Short Solution
The final solution can be written as:
function lineupStudents(students) {
return students
.trim()
.split(/\s+/)
.sort((a, b) =>
b.length - a.length ||
b.localeCompare(a)
);
}Each method has a separate purpose.
.trim()
.trim()removes extra whitespace from the beginning and end of the string.
.split(/\s+/)
.split(/\s+/)turns the string into an array.
The regular expression:
\s+means:
\smatches whitespace.+means one or more occurrences.
This allows the solution to handle one or more spaces between names.
.sort()
.sort(...)sorts the names using the challenge’s two rules.
b.length - a.length
b.length - a.lengthplaces longer names before shorter names.
b.localeCompare(a)
b.localeCompare(a)places names of equal length in reverse alphabetical order.
Why Writing the Long Solution Was Still Valuable
My longer solutions were not wasted work.
By manually using loops, conditions, indexes, .push(), .unshift(), and .splice(), I learned more about what JavaScript was doing behind methods such as .some() and .sort().
The shorter solutions became easier to understand because I had already worked through the underlying logic.
I learned that there are two useful stages when solving programming challenges:
- Write a solution that I understand and that produces the correct result.
- Review the solution and look for built-in methods that express the same logic more clearly.
The goal is not always to write the shortest possible code. Code should also be readable and understandable.
A one-line solution is not automatically better if it is difficult to understand. However, built-in methods can often communicate the purpose of the code more clearly once I understand how they work.
My Main Takeaways
The most important JavaScript lessons I learned during the last two weeks were:
.some()checks whether at least one array element passes a condition.- The callback parameter in
.some()receives each array element automatically. .some()can replace a manual loop when I only need to know whether one match exists..some()returns a Boolean value:trueorfalse..sort()can use a comparison function to define custom ordering rules.b.length - a.lengthsorts strings from longest to shortest.b.localeCompare(a)sorts strings in reverse alphabetical order.- The
||operator can connect a primary sorting rule with a secondary sorting rule. - Longer solutions can be useful for learning how an algorithm works.
- After finding a working solution, refactoring can make the code more concise and expressive.
Conclusion
Practicing Codewars challenges has helped me understand not only how to solve programming problems, but also how to recognize patterns that JavaScript’s built-in methods already handle.
My original solutions used more loops, conditions, variables, and manual array operations. Learning .some() and .sort() showed me how those same ideas could be expressed with less code while still remaining readable.
One of my most important lessons was that writing a longer solution is not necessarily a bad way to learn. Building the logic manually helped me understand what the shorter methods were doing internally.
As I continue learning JavaScript, I want to focus on understanding both approaches: how to build the logic manually and how to recognize when a built-in method can simplify it.