You could simplify the code a bit and return null if there's no more than one iteration to check the prefix. Also you could add an extra check for empty or 1 word arrays, otherwise your code would fail.
function prefix(words) {
if(words.length < 2 || words[0] === '') { // extra check for 0 or 1 words
return words[0] || null;
}
let i = 0;
while (true) {
const c = words[0][i];
for (let j = 1; j < words.length; j++) {
if (c != words[j][i]) {
return i ? words[0].slice(0, i) : null;
}
}
i++; // this will happen when at least 1 character is common
}
}
console.log(prefix([]));
console.log(prefix(['']));
console.log(prefix(['', '']));
console.log(prefix(['flower', '']));
console.log(prefix(['flower']));
console.log(prefix(["flower", "flowers", "floyd", "flow", "floor"]))
console.log(prefix(["flower", "flowers", "floyd", "flow", "sunflower", "floor"]))
And a benchmark:

<script benchmark data-count="10000000">
const words = ["flower", "flowers", "floyd", "flow", "floor"];
// @benchmark museum/tom
function prefix(words) {
for (let i = 0; i < words[0].length; i++) {
const char = words[0][i];
for (let j = 1; j < words.length; j++) {
// first letter unequal
if (i === 0 && words[j][i] !== char) {
return null;
}
if (i === words[j].length || words[j][i] !== char) {
return words[0].substring(0, i);
}
}
}
// No common prefix found
return null;
}
// @run
prefix(words);
// @benchmark Alexander
function prefix2(words) {
if(words.length < 2 || words[0] === '') { // extra check for 0 or 1 words
return words[0] || null;
}
let i = 0;
while (true) {
const c = words[0][i];
for (let j = 1; j < words.length; j++) {
if (c != words[j][i]) {
return i ? words[0].slice(0, i) : null;
}
}
i++;
}
}
// @run
prefix2(words);
</script>
<script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>
Answer from Alexander Nenashev on Stack OverflowYou could simplify the code a bit and return null if there's no more than one iteration to check the prefix. Also you could add an extra check for empty or 1 word arrays, otherwise your code would fail.
function prefix(words) {
if(words.length < 2 || words[0] === '') { // extra check for 0 or 1 words
return words[0] || null;
}
let i = 0;
while (true) {
const c = words[0][i];
for (let j = 1; j < words.length; j++) {
if (c != words[j][i]) {
return i ? words[0].slice(0, i) : null;
}
}
i++; // this will happen when at least 1 character is common
}
}
console.log(prefix([]));
console.log(prefix(['']));
console.log(prefix(['', '']));
console.log(prefix(['flower', '']));
console.log(prefix(['flower']));
console.log(prefix(["flower", "flowers", "floyd", "flow", "floor"]))
console.log(prefix(["flower", "flowers", "floyd", "flow", "sunflower", "floor"]))
And a benchmark:

<script benchmark data-count="10000000">
const words = ["flower", "flowers", "floyd", "flow", "floor"];
// @benchmark museum/tom
function prefix(words) {
for (let i = 0; i < words[0].length; i++) {
const char = words[0][i];
for (let j = 1; j < words.length; j++) {
// first letter unequal
if (i === 0 && words[j][i] !== char) {
return null;
}
if (i === words[j].length || words[j][i] !== char) {
return words[0].substring(0, i);
}
}
}
// No common prefix found
return null;
}
// @run
prefix(words);
// @benchmark Alexander
function prefix2(words) {
if(words.length < 2 || words[0] === '') { // extra check for 0 or 1 words
return words[0] || null;
}
let i = 0;
while (true) {
const c = words[0][i];
for (let j = 1; j < words.length; j++) {
if (c != words[j][i]) {
return i ? words[0].slice(0, i) : null;
}
}
i++;
}
}
// @run
prefix2(words);
</script>
<script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>
Here's what's happening
In the case of ["flower", "flowers", "floyd", "flow", "sunflower", "floor"], the loop iterates through the characters of the first word and compares them to the other words.
When i reaches the length of the first word (i = 5), there is no exit condition for the outer loop, so it continues to the next iteration.
However, there's no corresponding character in the other words, so the inner loop conditions (i === words[j].length || words[j][i] !== char) are not met.
Since the loop completes without returning anything and all the words are not the same, the function ends without a return statement.
In JavaScript, when a function doesn't return anything, it returns undefined, and that's why you see nothing printed.
The fix for this is to add a return statement after the outer loop to handle the case where the loop completes without finding a common prefix.
function prefix(words) {
/* Check if words list is 0, since prefix will always be null
in this case */
if (words.length === 0) return null;
for (let i = 0; i < words[0].length; i++) {
const char = words[0][i];
for (let j = 1; j < words.length; j++) {
if (i === words[j].length || words[j][i] !== char) {
if (i === 0) return null;
return words[0].substring(0, i);
}
}
}
return null; // Add this line to handle the missing case
}
console.log(
prefix(['flower', 'flowers', 'floyd', 'flow', 'flinging', 'floor'])
); // output: null
console.log(
prefix(['triangle', 'trick', 'trivial', 'triceratops', 'tricycle']) // output: 'tri'
);
TL;DR
Assuming we only need to apply a straight forward modification, I would avoid too much syntactical sugar and just write it this way:
function divide(num1, num2) {
if (arguments.length < 2) {
return null;
}
return num1/num2;
}
If we want to make it simple and elegant, I would write it this way (requires ES6 features):
const divide = (...args) => args.length < 2 ? null : args[0] / args[1];
Explanation
Improvement steps in vanilla JS (ES5 and before)
- Using function arguments: this is simply an array like object that will magically appear inside your function, which contains the arguments you have passed to the function.
function divide(num1, num2) {
if (arguments.length < 2) {
return null;
}
return num1/num2;
}
While this is a great solution for the problem there are a downsides to it, if you wanted to switch to arrow function arguments object doesn't appear.
- **Using ternary operator**you can farther more reduce the code by using the ternary
?which is best suitable for simpleifstatements
function divide(num1,num2) {
return arguments.length < 2 ? null : num1 / num2;
}
Improvement steps in ES6
- Using spread (in this case it is actually called rest): the
...can be used to either collect items into an array known as rest, or expand an array known as spread.
function divide(...args) {
return args.length < 2 ? null : args[0] / args[1];
}
JavaScript will collect all the arguments passed to the function and put them into an array called args, I like this better since the reader can see where is args defined.
- using arrow function: there are many difference between arrow and normal function, but many prefer it since it is shorter, and since we have a one-liner function why not use it.
const divide = (...args) => args.length < 2 ? null : args[0] / args[1];
On a final note all the previous solutions has a downside that we are only checking for length of arguments but not contents of arguments, lets assume that someone sent undefined into one of the first two arguments, you'll have 2 arguments but one of them is kinda missing and you'll get NaN since number of arguments is 2.
function divide(num1, num2) {
if (num1 === undefined || num2 === undefined) {
return null;
}
return num1/num2;
}
Demo
function divide1(num1, num2) {
if (arguments.length < 2) {
return null;
}
return num1/num2;
}
function divide2(num1,num2) {
return arguments.length < 2 ? null : num1 / num2;
}
function divide3(...args) {
return args.length < 2 ? null : args[0] / args[1];
}
const divide4 = (...args) => args.length < 2 ? null : args[0] / args[1];
const test = (cb) => {
console.log("-------->" + cb.name)
console.log(cb());
console.log(cb(1));
console.log(cb(1, 2));
console.log(cb(1, undefined));
console.log(cb(1, null));
console.log(cb(1, 2, 3));
};
test(divide1);
test(divide2);
test(divide3);
test(divide4);
Peep this.
function divide(num1, num2) {
if(arguments.length < 2) return null;
return num1 / num2;
}
The arguments object is available in all (non-arrow) function and represents all the arguments passed into the function. It has a length property that tells you how many arguments there are.
Undefined typically refers to something which has not yet been assigned a value (yet). Null refers to something which definitively has no value. In that case, I would recommend returning a null. Note that a function with no specified return value implicitly returns undefined.
From the ECMAScript2015 spec
4.3.10 undefined value
primitive value used when a variable has not been assigned a value
4.3.12 null value
primitive value that represents the intentional absence of any object value
http://www.ecma-international.org/ecma-262/6.0/#sec-terms-and-definitions-undefined-type
Further reading:
When is null or undefined used in JavaScript?
I will give you my personal opinionated way of choosing between the two.
My simple question is: could the value, given another input/state/context be defined to something?
If the answer is yes then use null else use undefined. More generally any function returning an object should return null when the intended object does not exist. Because it could exist given another input/state/context.
null represents the absence of value for a given input/state/context. It implicitly means that the concept of the value itself exist in the context of your application but may be absent.
In your example the concept of a next card exists but the card itself may not exist. null should be used.
undefined implicitly represents the absence of meaning of that value in your application's context. For example, if I manipulate a user object with a given set of properties and I try to access the property pikatchu. The value of this property should be set to undefined because in my context it doesn't make any sense to have such a property.
Hey! What are your thoughts on explicit returning undefined in a function vs returning null, this in the absence of what you asked the function for.
Let's take these functions as an exampletype getUser = (id: string): User | undefined vs type getUser = (id: string): User | NULL
What are your thoughts on this? Good and bad etc
1 <= num <= 7 does not do what you think it does. In JavaScript, binary operators are evaluated from left to right. So 1 <= num <= 7 is really (1 <= num) <= 7, which is either true <= 7 or false <= 7 (depending on what num is). Either way, it will evaluate to true, but don’t ask me why, because you really shouldn’t compare booleans with numbers anyway. Since the condition is always true, the else branch is never executed, so you never get null.
I think what you want to write is:
if (1 <= num && num <= 7) {
...
} else {
...
}
Furthermore, remember that array indices start with 0. In your example, days[1] would be 'Tuesday', not 'Monday'.
I hope this answer helps you :)
const days = ['Monday', 'Tuesyday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
const returnDay = (num) => {
const day = num - 1;
if (days[day]) { // since you passing 0 there is no such element in the array at index -1,
//so if statement essentially evaluates to false and returning null right away;
return days[day];
}
return null;
};
console.log(returnDay(1)); // Monday
console.log(returnDay(7)); // Sunday
console.log(returnDay(4)); // Thursday
console.log(returnDay(0)); // null
Your example doesn't seem to need a loop. That and returning from the loop-delegate doesn't do anything for you.
You can test if a key appears in an object using the in operator.
function exampleFunction(param){
return param in exampleData ? exampleData[param] : null;
}
Given Crazy Train's comment, you need to capture the matching value so you can return it later:
function exampleFunction(param) {
var match = null;
$.each(exampleData, function (key, value) {
if (key == param) {
match = value;
return false; // to end the $.each early
}
});
return match;
}
You could make a "factory function" or "static factory method" instead:
Foo.CreateFoo = function() {
// not to confuse with Foo.prototype. ...
if (something) {
return null;
}
return new Foo();
};
// then instead of new Foo():
var obj = Foo.CreateFoo();
Same thing using the newer class syntax:
class Foo {
static CreateFoo() {
if (something) {
return null;
}
return new Foo();
}
}
The better solution would be to throw an error:
function klass(canvas_id) {
var canvas = document.getElementById( canvas_id );
if( ! ( canvas && canvas.getContext ) ) {
throw new Error('Not a canvas');
}
}
// later...
try {
var c = new klass("canvas_id");
} catch(E) {
// error caught
}
EDIT: Constructors can be "forced" to not return an instance:
function Foo() {
var canvas = ...;
if ('undefined' == '' + Foo.CANVAS_CHECK)
Foo.CANVAS_CHECK = ( canvas && canvas.getContext );
if (!Foo.CANVAS_CHECK)
return []; // the constructor will actually return an empty array
// passed; initialize instance here
}
// later on...
var foo;
if (!((foo = new Foo()) instanceof Foo)) {
// Failed. Canvas is unsupported.
}
// You happy now, am not i am? ;-)
The odd thing is, however, that if a "constructor" returns a number, string, true, false, etc., it actually does return an instance. The second solution only works when the constructor returns an empty array [] or an empty object {}.
My company uses files that are essentially merged XML files into one. I wrote a pretty basic parser and node object that contains the tag name, text, and child node objects. Recently I ran into an error where the file couldn't be found, and my function that searches for child nodes returned null (as it should). But it caused a runtime error, so I'm trying to figure out the best way to address issue. Should I return an empty object so that the code doesn't crash, or should I continue returning null and wrap it in a try/catch?