Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

Sorry, you do not have permission to ask a question, You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please type your username.

Please type your E-Mail.

Please choose an appropriate title for the post.

Please choose the appropriate section so your post can be easily searched.

Please choose suitable Keywords Ex: post, video.

Browse

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Navigation

  • Home
  • About Us
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • About Us
  • Contact Us
Home/ Questions/Q 8649

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Latest Questions

Author
  • 60k
Author
Asked: November 28, 20242024-11-28T03:05:07+00:00 2024-11-28T03:05:07+00:00

JavaScript In Depth – isFinite & IsNaN Functions

  • 60k

Javascript is not a language for the unwary – Kobby Owen

Just before you stop reading, I know what you are thinking! “Who would read an article about these simple functions ?. These are basic functions every beginner of Javascript can quickly master, and easily learn to use. There is no need for an article about this!”. While this is true, their behavior may be somewhat surprising, especially when dealing with non-number arguments. Learning more about their implementation will give you an in-depth knowledge of JavaScript and its core implementation.

If you can answer the following questions, then you may stop reading this article. If not, I suggest you keep reading, since you will learn a lot from studying these functions and their implementation.

  1. Why is isNaN(new Date()) false and isNaN(Date()) true
  2. Why is isFinite(null) true and isFinite(undefined) false
  3. Why is isFinite(" ") true and isFinite("a") false
  4. Why is isNaN("Infinity") true and isNaN("infinity") false
  5. Under what conditions do isNaN and isFinite throw a TypeError
  6. What is the value of isNaN(" 23 "), isNaN(23), isNaN(" 23." ), isNaN("12 .")

isFinite function determines if the passed argument is finite value. It checks if its argument is not NaN, or negative infinity or positive positive infinity.

isNaN on the other hand determines whether the argument passed is a NaN or not. This function is necessary because of the nature of NaN. NaN is the only floating point value that does not compare to itself. This behavior is so true that, ECMAScript documentation suggests that one of the reliable ways to check for NaN is the expression(x === x), which returns false only if x is a NaN.
Mostly, to determine if a number is okay to be used in arithmetic operation without few surprises, you should find yourself using isFinite more than isNaN, since isFinite checks for NaN values and goes on to check for infinite values. In cases where infinite values are legitimately allowed to participate in operations, isNaN will be the best function to use.

Implementation Details

The first thing isNaN and isFinite function does is to try to convert its argument to a Number. This conversion is done using an ECMAScript internal function which is not exposed to the developer. It is this internal function that forms the core of these two functions, and is therefore worth studying. For the purpose of the article, lets call this function ToNumber function. This function is used a lot in ECMAScript behind the scenes. Understanding how it works, will give you a lot of understanding about the results of most operations in JavaScript. In an attempt to explain this internal function, we will use many helper functions and explain other internal methods used in ECMAScript that helps the ToNumber function to perform its conversion. I will use to top down approach to explain the implementation of this function.

ToNumber Internal Function

ToNumber function takes a single argument, which is the argument to convert. To convert the argument, it takes the following step.

  1. If the argument is undefined, it returns NaN
  2. If the argument is null , it returns 0
  3. If the argument is a number, it returns it
  4. If the argument is a BigInt , throw a TypeError
  5. If the argument is a Symbol, throw a TypeError
  6. If the argument is a String, call another internal method(StringToNumber)
  7. If the argument is an Object, call another internal method(ToPrimitive) and pass its result through ToNumber function again.

NB. Step 7 involves 2 steps, it calls a helper function to convert the object to a primitive value, preferably a number, and call the ToNumber function recursively on its return value. The astute reader may reason at this point that this can cause an infinite recursion. That is not the case, because ECMAScript makes sure the return of ToPrimitive is not another object.

Now lets look at the two helper functions used by ToNumber to aid the conversion of its argument.

StringToNumber Internal Function

StringToNumber function simply parses its string argument and converts it to a number. One important thing to note about this function is the kind of input the parser accepts. The parser allows for optional white-space before and after the main string decimal characters. Any invalid character present in the argument, no matter where it is, will cause the parser to return NaN, and consequently the function too. Invalid characters include any character that is not part of the set [+ – E e .]. These valid non decimal characters are however allowed to appear only once. Making it appear twice will cause the function to return NaN. The function however recognizes the “Infinity” and returns the mathematical representation of it. An optional + or – is allowed before the decimal characters. They should however be the first non white-space character, if it exists in the sequence except it is being used before an E or e. An empty string, or a string full of white-space will cause the function to return the number 0. The following examples demonstrates the use of the function.

 function StringToNumber( argument ){     /** implementation code **/ }  StringToNumber(" 23") // 23 StringToNumber(" 23 ") // 23 StringToNumber("+23.5") // 23.5  StringToNumber("+ 23.5") // NaN ( space after the plus sign) StringToNumber("-23.5") // -23.5  StringToNumber("23.2.3") // NaN StringToNumber("23ab") //NaN StringToNumber("Infinity") // Infinity  StringToNumber("-Infinity") // -Infinity StringToNumber("+Infinity") // Infinity  StringToNumber("ab") //NaN StringToNumber("NaN")  /**NaN ( not because the phrase NaN can be parsed , but because the characters N a N cannot be represented as a number) **/  StringToNumber("23E-14") //23E-14 StringToNumber("23E -14") //NaN ( space after E. )  
Enter fullscreen mode Exit fullscreen mode

ToPrimitive Internal Function

The last function to examine before we can proceed is ToPrimitive method. This method takes an input and converts it to a primitive type, basically a number or a string. The function also takes an optional argument called hint. The hint argument can either be [default, number or string]. When the function is called, it first checks if the input is an object. If it is and it defines a Symbol.toPrimitive method, it is called on the object while passing “number” as a hint to the function. If the method returns an object ( null not included ), a TypeError is thrown, otherwise its value is returned. If the object does not define its Symbol.ToPrimitive, it looks for two methods on the object, ie toString and valueOf. If the hint is a number, valueOf is called first, else toString is called first, and the other is called next. When the function to be called first is resolved, it is checked if it exists on the object or any of its bases, if it exists, and its return value when called is not an object, it returns it results. The second function, which is based on the value passed to the hint argument is called next. Its value is returned if is is not an object. If both methods returns an object, a TypeError is thrown by the function.

If you did not understand these functions, here are their implementation in JavaScript( note JavaScript). In a real ECMAScript implementation, these functions are probably implemented in C/C++.

 function StringToNumber( argument ){     const res = argument.trim()     // return 0 for empty string after stripping space characters     if ( res.length === 0 ) return 0     return Number(res) }  function OrdinaryToPrimitive( input, hint){     let methodNames = []     if ( hint === "string" )         methodNames = ["toString", "toValueOf"]     else          methodNames = ["valueOf", "toString"]      for ( const name of methodNames) {         if ( typeof name === "function" ){             const res = input[name]()             if ( typeof res !== 'object' || res === null)                  return res          }     }     throw TypeError }  function ToPrimitive( input, hint){      if ( typeof input === "object" ){         if ( input[Symbol.toPrimitive] !== undefined ){             if ( hint === undefined ) hint = 'default'             const res = input[Symbol.toPrimitive]( hint )             if ( typeof res !== 'object' || res === null)                  return res              throw TypeError          }         else{             if ( hint === undefined ) hint = "number"             return OrdinaryToPrimitive(input, hint)         }     }     return input     }  function ToNumber( argument ) {      switch( typeof argument) {         case 'undefined' :              return NaN         case 'number' :              return argument          case 'bigint': case 'symbol':              throw TypeError          case 'string' :              return StringToNumber(argument)         case 'object':{             if (argument === null )                  return 0             const hint = "number"             const primitive = ToPrimitive(argument, hint)             return ToNumber(primitive)           }     } }   
Enter fullscreen mode Exit fullscreen mode

There are a few things to note here. ToPrimitive delegates to another method called OrdinaryToPrimitive if the input provided does not defined Symbol.toPrimitive method.

isNaN and isFinite

Now that we understand these internal functions. Let us go back to our functions.
isNaN first converts its argument to a number using the ToNumber method and checks for NaN. If the result of that conversion is a NaN, true is return otherwise false is returned.
isFinite also first converts its argument to a number using the same ToNumber method. If then proceeds to check if the result of that conversion is not a NaN or -Infinity or Infinity.
There is nothing interesting about these functions apart from the internal method that it calls to convert its argument before checking it. ToNumber internal methods are used by a lot of JavaScript functions including parseInt to convert its radix argument., All functions defined on the global Math object calls the function on its arguments before it starts processing the result, it is used by Date.UTC to convert it parameters into acceptable values and almost all the setter methods on the Date object ( example setHours, setMonth, setYear) and almost all methods and functions that operates with numbers. Understanding how this internal method works will save you from opening your jaws wide while you stare at the screen trying to understand the return values of some functions. Try to take a moment to go through this internal method one more time. Now let us answer the five questions at the beginning of the article, which you should be able to answer if you paid enough attention to it.

Question 1

Why is isNaN(new Date()) false and isNaN(Date()) true

Answer

The result of new Date() is an object. When that object is passed to isNaN as an argument, ToPrimitive is called to convert it to a primitive value, preferably a number. This ends up calling valueOf method on the object and returning its results, which is a number. This number is then checked for NaN , which is ultimately false. The result of Date() on the other hand is a string that represents the current time. This string is passed to StringToNumber internal method by ToNumber. The result is a string that cannot be parsed into a number, thus returning NaN. isNaN proceeds to check the result of this conversion and finds that its NaN and ultimately return true

Question 2

Why is isFinite(null) true and isFinite(undefined) false

Answer

ToNumber converts null to 0 and undefined to NaN, thus the return values of isFinite when called with these two values

Question 3

Why is isFinite(" ") true and isFinite("a") false

Answer

Both arguments are strings, so ToNumber calls StringToNumber internal method on them. Empty strings after trimming white spaces causes the method to return 0. Thus the first isFinite call is the result of checking if 0 is a finite number, which it is. “a” on the other hand returns NaN when converted.

Question 4

Why is isNaN("Infinity") true and isNaN("infinity") false

Answer

StringToNumber recognizes the string “Infinity” , “-Infinity”, “-Infinity”. It rightly returns Infinity and the result is checked whether its NaN, which ends up being false. Infinity is not NaN.
“infinity” on the other hand is not recognized, neither can it be parsed as a number. It returns NaN as a result of the conversion.

Question 5.

Under what conditions do isNaN and isFinite throw a TypeError

Answer

If their argument in either a BigInt, Symbol or they defined toString and valueOf which both returns an object instead of a primitive value like a string or a number

Question 6.

What is the value of isNaN(" 23 "), isNaN(23), isNaN(" 23." ), isNaN("12 .")

Answer

isNaN(" 23 ") is false
isNaN("23.") is false
isNaN("12 .") is true

javascriptnodewebdev
  • 0 0 Answers
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

Sidebar

Ask A Question

Stats

  • Questions 4k
  • Answers 0
  • Best Answers 0
  • Users 2k
  • Popular
  • Answers
  • Author

    ES6 - A beginners guide - Template Literals

    • 0 Answers
  • Author

    Understanding Higher Order Functions in JavaScript.

    • 0 Answers
  • Author

    Build a custom video chat app with Daily and Vue.js

    • 0 Answers

Top Members

Samantha Carter

Samantha Carter

  • 0 Questions
  • 20 Points
Begginer
Ella Lewis

Ella Lewis

  • 0 Questions
  • 20 Points
Begginer
Isaac Anderson

Isaac Anderson

  • 0 Questions
  • 20 Points
Begginer

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore, ask, and connect. Join our vibrant Q&A community today!

About Us

  • About Us
  • Contact Us
  • All Users

Legal Stuff

  • Terms of Use
  • Privacy Policy
  • Cookie Policy

Help

  • Knowledge Base
  • Support

Follow

© 2022 Querify Question. All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.