3

I have just started learning Javascript and I have a specific question about a specific piece of code below. It is part of the lycanthrope's log in chapter 4 of Eloquent Javascript. Because of the specificity of my question I haven't included all the other code associated with this problem for I believe it isn't necessary to answer my question.

Please do let me know if this is considered 'bad practice' and I will make sure to ammend this and/or future posts to show more background.

In the code below the second line shows a return. So far I have learned that indexOf returns a positive number or zero if and only if it finds an occurence of whatever is passed in it. If no occurence is found it returns -1.

In this case it is followed by != -1, which I understand to mean "not equal to minus 1". That is clear to me.

What I do not completely understand is what the actual return in line 2 ends up being. Does it return a Boolean value of either true or false? Or does it return he actual index where the 'event' is found?

Further on, in the first if-statement, we see the hasEvent variable again. I read this statement as "If hasEvent(event, entry) is true then add 1 to the index.

Am I 'reading' this right and is the return in the second line indeed a Boolean?

function hasEvent (event, entry) {
  return entry.events.indexOf(event) != -1;
}

function tableFor (event, journal) {
 var table = [0, 0, 0, 0];
 for (var i=0; i < journal.length; i++) {
  var entry = journal[i] , index = 0;
  if (hasEvent(event, entry)) index += 1;
  if (entry.squirrel) index += 2;
  table [index] += 1;
}
 return table;
}

Thank you for your help and please tell me if I should have stated this question differently! I am trying to make sure I understand things before I move on!

Ronny Blom
  • 149
  • 2
  • 6

4 Answers4

8

The != operator always has a boolean result.

A return statement followed by an expression returns the value of the expression, so the returned value of that function will be either true or false.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • And better to use `!==` and `===`. – Tushar Jun 24 '16 at 13:51
  • @Tushar in this case it makes no difference, because `.indexOf()` will always return a number. – Pointy Jun 24 '16 at 13:52
  • Thank you for that explanation. So then logically the first if statement indeed causes 1 to be added when the hasEvent value comes back as true? – Ronny Blom Jun 24 '16 at 14:13
  • Right. In the expression context where the function is *called*, the value will be whatever was returned. That'll be either `true` or `false`. If it's `true`, then the statement body of the `if` will execute. – Pointy Jun 24 '16 at 14:20
6

Yep. Using ===, ==, !, !==, !=, >, >=, < or <= results in a boolean expression, which would return a boolean from hasEvent.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
1

Comparison operators all evaluate to a boolean value.

More to the point, what this code is specifically doing is abstracting a comparison behind a function name. Any operation or set of operations which results in a value can be placed in a function which returns that value. Doing so is a common refactoring to make code more readable and understandable, as the name of the function can impart intuitive meaning on the operation being performed.

So instead of something like this:

if (a == b) {

}

you can have this:

if (someCondition(a, b)) {

}

So you can give a meaningful name to the operation (more meaningful than someCondition of course). As long as that function returns the same value as the code it replaces, logically there is no difference.

David
  • 208,112
  • 36
  • 198
  • 279
1

Explanation

By default, the indexOf function returns the index location of the substring.

A bitwise shortcut can be used with indexOf as well as other functions:

  • ~ (bitwise not operator):
    • This works similar to ~x => -(x+1)

Simply checking against this value (for example using an if statement) yields true for non-zero values and false for zero.

If you need the actual boolean value instead, you can use the following: !!~. Here, the double exclamation !! is non-inverted boolean representation. Combining both essentially flips the result of indexOf, then converts it to boolean representation.

A better explanation of ~ can be found here. A better explanation of !! can be found here

Example

let s = 'abc'

/*
console.log(~s.indexOf('a'))  // -1
console.log(~s.indexOf('b'))  // -2
console.log(~s.indexOf('d'))  //  0

console.log(!~s.indexOf('a')) // false
console.log(!~s.indexOf('b')) // false
console.log(!~s.indexOf('d')) // true

console.log(!!s.indexOf('a')) // false
console.log(!!s.indexOf('b')) // true
console.log(!!s.indexOf('d')) // true

console.log(~~s.indexOf('a')) // 0
console.log(~~s.indexOf('b')) // 1
console.log(~~s.indexOf('d')) // -1
*/

// This one works
console.log(!!~s.indexOf('a'))  // true: 0 => -1 => false => true
console.log(!!~s.indexOf('b'))  // true: 1 => -2 => false => true
console.log(!!~s.indexOf('d'))  // false: -1 => 0 => true => false
ctwheels
  • 21,901
  • 9
  • 42
  • 77