Add caption |
Learn Code For Free
Tuesday, 18 August 2020
Detecting a string in JavaScript
Escaping Quotes in JavaScript
Reverse String in JavaScript
The most "popular" way of reversing a string in JavaScript is the following code fragment, which is quite common:
function reverseString(str) {
return str.split('').reverse().join('');
}
reverseString('string'); // "gnirts"
However, this will work only so long as the string being reversed does not contain surrogate pairs. Astral symbols,
Add caption |
i.e. characters outside of the basic multilingual plane, may be represented by two code units, and will lead this
naive technique to produce wrong results. Moreover, characters with combining marks (e.g. diaeresis) will appear
on the logical "next" character instead of the original one it was combined with.
'?????.'.split('').reverse().join(''); //fails
While the method will work fine for most languages, a truly accurate, encoding respecting algorithm for string
reversal is slightly more involved. One such implementation is a tiny library called Esrever, which uses regular
expressions for matching combining marks and surrogate pairs in order to perform the reversing perfectly.
Explanation
Section Explanation Result
str The input string "string"
String.prototype.split(
deliminator )
Splits string str into an array. The
parameter "" means to split between each
character.
["s","t","r","i","n","g"]
Array.prototype.reverse()
Returns the array from the split string with
its elements in reverse order. ["g","n","i","r","t","s"]
Array.prototype.join( deliminator
)
Joins the elements in the array together into
a string. The "" parameter means an empty
deliminator (i.e., the elements of the array
are put right next to each other).
Basic Info and String Concatenation
Add caption |
Finding an object's class
To find whether an object was constructed by a certain constructor or one inheriting from it, you can use the
instanceof command:
//We want this function to take the sum of the numbers passed to it
//It can be called as sum(1, 2, 3) or sum([1, 2, 3]) and should give 6
function sum(...arguments) {
if (arguments.length === 1) {
const [firstArg] = arguments
if (firstArg instanceof Array) { //firstArg is something like [1, 2, 3]
return sum(...firstArg) //calls sum(1, 2, 3)
}
}
return arguments.reduce((a, b) => a + b)
}
console.log(sum(1, 2, 3)) //6
console.log(sum([1, 2, 3])) //6
console.log(sum(4)) //4
Note that primitive values are not considered instances of any class:
console.log(2 instanceof Number) //false
console.log('abc' instanceof String) //false
console.log(true instanceof Boolean) //false
console.log(Symbol() instanceof Symbol) //false
Every value in JavaScript besides null and undefined also has a constructor property storing the function that was
used to construct it. This even works with primitives.
//Whereas instanceof also catches instances of subclasses,
//using obj.constructor does not
console.log([] instanceof Object, [] instanceof Array) //true true
console.log([].constructor === Object, [].constructor === Array) //false true
function isNumber(value) {
//null.constructor and undefined.constructor throw an error when accessed
if (value === null || value === undefined) return false
return value.constructor === Number
}
console.log(isNumber(null), isNumber(undefined)) //false false
console.log(isNumber('abc'), isNumber([]), isNumber(() => 1)) //false false false
console.log(isNumber(0), isNumber(Number('10.1')), isNumber(NaN)) //true true true
Formatting console output
Many of the console's print methods can also handle C-like string formatting, using % tokens:
console.log('%s has %d points', 'Sam', 100);
Displays Sam has 100 points.
The full list of format specifiers in JavaScript is:
Specifier Output
%s Formats the value as a string
%i or %d Formats the value as an integer
%f Formats the value as a floating point value
%o Formats the value as an expandable DOM element
%O Formats the value as an expandable JavaScript object
%c Applies CSS style rules to the output string as specified by the second parameter
Advanced styling
When the CSS format specifier (%c) is placed at the left side of the string, the print method will accept a second
parameter with CSS rules which allow fine-grained control over the formatting of that string:
console.log('%cHello world!', 'color: blue; font-size: xx-large');
Displays:
It is possible to use multiple %c format specifiers:
any substring to the right of a %c has a corresponding parameter in the print method;
this parameter may be an empty string, if there is no need to apply CSS rules to that same substring;
if two %c format specifiers are found, the 1st (encased in %c) and 2nd substring will have their rules defined in
the 2nd and 3rd parameter of the print method respectively.
if three %c format specifiers are found, then the 1st, 2nd and 3rd substrings will have their rules defined in
the 2nd , 3rd and 4th parameter respectively, and so on...
console.log("%cHello %cWorld%c!!", // string to be printed
"color: blue;", // applies color formatting to the 1st substring
"font-size: xx-large;", // applies font formatting to the 2nd substring
"/* no CSS rule*/" // does not apply any rule to the remaining substring
);
Output can be indented and enclosed in a collapsible group in the debugging console with the following methods:
console.groupCollapsed(): creates a collapsed group of entries that can be expanded through the
disclosure button in order to reveal all the entries performed after this method is invoked;
console.group(): creates an expanded group of entries that can be collapsed in order to hide the entries
after this method is invoked.
The indentation can be removed for posterior entries by using the following method:
console.groupEnd(): exits the current group, allowing newer entries to be printed in the parent group after
this method is invoked.
Groups can be cascaded to allow multiple indented output or collapsible layers within each other:
= Collapsed group expanded =>
Using HTML comments in JavaScript (Bad practice)
HTML comments (optionally preceded by whitespace) will cause code (on the same line) to be ignored by the
browser also, though this is considered bad practice.
One-line comments with the HTML comment opening sequence (<!--):
Note: the JavaScript interpreter ignores the closing characters of HTML comments (-->) here.
<!-- A single-line comment.
<!-- --> Identical to using `//` since
<!-- --> the closing `-->` is ignored.
This technique can be observed in legacy code to hide JavaScript from browsers that didn't support it:
<script type="text/javascript" language="JavaScript">
<!--
/* Arbitrary JavaScript code.
Old browsers would treat
it as HTML code. */
// -->
</script>
An HTML closing comment can also be used in JavaScript (independent of an opening comment) at the beginning of
a line (optionally preceded by whitespace) in which case it too causes the rest of the line to be ignored:
--> Unreachable JS code
These facts have also been exploited to allow a page to call itself first as HTML and secondly as JavaScript. For
example:
<!--
self.postMessage('reached JS "file"');
/*
-->
<!DOCTYPE html>
<script>
var w1 = new Worker('#1');
w1.onmessage = function (e) {
console.log(e.data); // 'reached JS "file"
};
</script>
<!--
*/
-->
When run a HTML, all the multiline text between the <!-- and --> comments are ignored, so the JavaScript
contained therein is ignored when run as HTML.
As JavaScript, however, while the lines beginning with <!-- and --> are ignored, their effect is not to escape over
multiple lines, so the lines following them (e.g., self.postMessage(...) will not be ignored when run as JavaScript,
at least until they reach a JavaScript comment, marked by /* and */. Such JavaScript comments are used in the
above example to ignore the remaining HTML text (until the --> which is also ignored as JavaScript).
Undefined and null
At first glance it may appear that null and undefined are basically the same, however there are subtle but
important differences.
undefined is the absence of a value in the compiler, because where it should be a value, there hasn't been put one,
like the case of an unassigned variable.
undefined is a global value that represents the absence of an assigned value.
typeof undefined === 'undefined'
null is an object that indicates that a variable has been explicitly assigned "no value".
typeof null === 'object'
Setting a variable to undefined means the variable effectively does not exist. Some processes, such as JSON
serialization, may strip undefined properties from objects. In contrast, null properties indicate will be preserved so
you can explicitly convey the concept of an "empty" property.
The following evaluate to undefined:
A variable when it is declared but not assigned a value (i.e. defined)
let foo;
console.log('is undefined?', foo === undefined);
// is undefined? true
Accessing the value of a property that doesn't exist
let foo = { a: 'a' };
console.log('is undefined?', foo.b === undefined);
// is undefined? true
The return value of a function that doesn't return a value
function foo() { return; }
console.log('is undefined?', foo() === undefined);
// is undefined? true
The value of a function argument that is declared but has been omitted from the function call
function foo(param) {
console.log('is undefined?', param === undefined);
}
foo('a');
foo();
// is undefined? false
// is undefined? true
undefined is also a property of the global window object.
// Only in browsers
console.log(window.undefined); // undefined
window.hasOwnProperty('undefined'); // true
Version < 5
Before ECMAScript 5 you could actually change the value of the window.undefined property to any other value
potentially breaking everything.
NaN in JavaScript
window.isNaN()
The global function isNaN() can be used to check if a certain value or expression evaluates to NaN. This function (in
short) first checks if the value is a number, if not tries to convert it (*), and then checks if the resulting value is NaN.
For this reason, this testing method may cause confusion.
(*) The "conversion" method is not that simple, see ECMA-262 18.2.3 for a detailed explanation of the algorithm.
These examples will help you better understand the isNaN() behavior:
isNaN(NaN); // true
isNaN(1); // false: 1 is a number
isNaN(-2e-4); // false: -2e-4 is a number (-0.0002) in scientific notation
isNaN(Infinity); // false: Infinity is a number
isNaN(true); // false: converted to 1, which is a number
isNaN(false); // false: converted to 0, which is a number
isNaN(null); // false: converted to 0, which is a number
isNaN(""); // false: converted to 0, which is a number
isNaN(" "); // false: converted to 0, which is a number
isNaN("45.3"); // false: string representing a number, converted to 45.3
isNaN("1.2e3"); // false: string representing a number, converted to 1.2e3
isNaN("Infinity"); // false: string representing a number, converted to Infinity
isNaN(new Date); // false: Date object, converted to milliseconds since epoch
isNaN("10$"); // true : conversion fails, the dollar sign is not a digit
isNaN("hello"); // true : conversion fails, no digits at all
isNaN(undefined); // true : converted to NaN
isNaN(); // true : converted to NaN (implicitly undefined)
isNaN(function(){}); // true : conversion fails
isNaN({}); // true : conversion fails
isNaN([1, 2]); // true : converted to "1, 2", which can't be converted to a number
This last one is a bit tricky: checking if an Array is NaN. To do this, the Number() constructor first converts the array
to a string, then to a number; this is the reason why isNaN([]) and isNaN([34]) both return false, but isNaN([1,
2]) and isNaN([true]) both return true: because they get converted to "", "34", "1,2" and "true" respectively. In
general, an array is considered NaN by isNaN() unless it only holds one element whose string representation
can be converted to a valid number.
Version ≥ 6
Number.isNaN()
In ECMAScript 6, the Number.isNaN() function has been implemented primarily to avoid the problem of
window.isNaN() of forcefully converting the parameter to a number. Number.isNaN(), indeed, doesn't try to
convert the value to a number before testing. This also means that only values of the type number, that are
also NaN, return true (which basically means only Number.isNaN(NaN)).
From ECMA-262 20.1.2.4:
When the Number.isNaN is called with one argument number, the following steps are taken:
1. If Type(number) is not Number, return false.
2. If number is NaN, return true.
3. Otherwise, return false.
Some examples:
// The one and only
Number.isNaN(NaN); // true
// Numbers
Number.isNaN(1); // false
Number.isNaN(-2e-4); // false
Number.isNaN(Infinity); // false
// Values not of type number
Number.isNaN(true); // false
Number.isNaN(false); // false
Number.isNaN(null); // false
Number.isNaN(""); // false
Number.isNaN(" "); // false
Number.isNaN("45.3"); // false
Number.isNaN("1.2e3"); // false
Number.isNaN("Infinity"); // false
Number.isNaN(new Date); // false
Number.isNaN("10$"); // false
Number.isNaN("hello"); // false
Number.isNaN(undefined); // false
Number.isNaN(); // false
Number.isNaN(function(){}); // false
Number.isNaN({}); // false
Number.isNaN([]); // false
Number.isNaN([1]); // false
Number.isNaN([1, 2]); // false
Number.isNaN([true]); // false
Array and Objects
Array |