Here are some notes & links I used on my quest of learning JavaScript. You won't find anything spectacular here :)
What are the pros and cons of using object literal notation vs class notation? : javascript
Object literals vs constructors in JavaScript - Internal Pointers
Why Object Literals in JavaScript Are Cool
Object initializer - JavaScript | MDN
Object.hasOwnProperty()
Object.hasOwnProperty determines if the whole property is defined in the object itself or in the prototype chain.
Object.keys returns an array of string where its items are the own properties from a given object
When you're using for (var key in obj) it will loop through the given object + its parent objects' properties on the prototype chain until it reaches the end of the chain. As you want to check only specific object's properties, you need to use hasOwnProperty.
This is not needed in for (var i = 0; i < length; i++) or data.forEach()
Inheritance and the prototype chain - JavaScript | MDN
Object.getPrototypeOf() - JavaScript | MDN
Why is JavaScript prototype property undefined on new objects? - Stack Overflow
How do I enumerate the properties of a JavaScript object? - Stack Overflow
object - Javascript what is property in hasOwnProperty? - Stack Overflow
Object.keys()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
Computed property name syntax (ES6)
It's a shorthand for the someObject[someKey] assignment (from ES3/5):
var a = "b"
var c = {[a]: "d"}
is same as:
var a = "b"
var c = {}
c[a] = "d"
Square Brackets Javascript Object Key
Object.values()
What is the difference between Object.values() and for..in?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values
Remove a property in an object immutably
const {prop1, prop2, ...outputObject} = originalObject;
String
In JavaScript everything is an
object (or may at least be treated as an object), except
primitives (booleans, null, numbers, strings and the value undefined (and symbol in ES6)).
In JavaScript strings can be literals or objects.
Why does instanceof return false for some literals?
Primitives are a different kind of type than objects created from within Javascript.
Literal is a primitive => Literal is NOT an object!
template string
https://stackoverflow.com/questions/19105009/how-to-insert-variables-in-javascript-strings
How to make template string substitution in runtime?
https://stackoverflow.com/questions/30003353/can-es6-template-literals-be-substituted-at-runtime-or-reused
split()
https://medium.com/@jeanpan/javascript-splice-slice-split-745b1c1c05d2
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split
Array
How to find if array contains some element which matches some criteria?
https://www.w3schools.com/jsref/jsref_find.asp
jQuery - What happens if some operation is executed on the empty array?
e.g. what happens if find returns empty array in:
$footer_ip.find(".user--ip, .virtual--ip").addClass("animated fadeInUp");
https://stackoverflow.com/questions/5705067/what-happens-when-a-jquery-selector-wasnt-found
How to create an array?
https://stackoverflow.com/questions/1629539/use-of-square-brackets-around-javascript-variables
How to redefine Array.toString function?
https://stackoverflow.com/questions/1629539/use-of-square-brackets-around-javascript-variables
Simplify your JavaScript – Use .map(), .reduce(), and .filter()
.map()
- takes 2 arguments:
- a callback
- an optional context (will be considered as this in the callback)
- callback runs for each value in the array and returns each new value in the resulting array
- resulting array will always be the same length as the original array
- Whenever you see .forEach in your code, think about using .map
.reduce()
- runs a callback for each element of an array
- passes the result of this callback (the accumulator) from one array element to the other
- accumulator can be pretty much anything (integer, string, object, etc.) and must be instantiated or passed when calling .reduce()
- .reduce() is an easy way to generate a single value or object from an array
.filter()
- if the callback function returns true, the current element will be in the resulting array. If it returns false, it won’t be.
How to remove an element from an array?
"delete" should not be used on arrays
How do I remove a property from a JavaScript object?
How to remove a property from a JavaScript object
3 Ways to clone objects in Javascript
Copying Objects in JavaScript
How to deep clone a JavaScript object
What is the most efficient way to deep clone an object in JavaScript?
How do I correctly clone a JavaScript object?
Clone a js object except for one key
How to handle immutability in JavaScript
Its Lodash features that JS doesn't have (or sometimes needs polyfills for), that you should definitely use when needed. Examples of that are object deep clone and object difference - two of the most important Lodash functionalities for me, personally. [
Lodash and usefulness of utility libraries ]
Hoisting
https://www.sitepoint.com/back-to-basics-javascript-hoisting/
Expressions and operators
Loose equality operator (==)
It tests for strict equality between two values. Both the type and the value you’re comparing have to be exactly the same.
https://codeburst.io/javascript-null-vs-undefined-20f955215a2
Double Equals(==) vs. Triple Equals(===)
Triple equals tests for loose equality and performs type coercion.
https://codeburst.io/javascript-double-equals-vs-triple-equals-61d4ce5a121a
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators
When is it OK to use == in JavaScript?
Destructuring assignment
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
[a, b, ...rest] = [10, 20, 30, 40, 50];
Spread syntax
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
https://zendev.com/2018/05/09/understanding-spread-operator-in-javascript.html
https://stackoverflow.com/questions/11704267/in-javascript-how-to-conditionally-add-a-member-to-an-object
Short-circuiting
https://codeburst.io/javascript-what-is-short-circuit-evaluation-ff22b2f5608c
Null Coalescing Operator
let a = b || c;
Regardless of the type of the first operand, if casting it to a
Boolean results in
false (like for null,
undefined,
0,
""...but not for
"false", "undefined", "null", "0", "empty", "deleted"... as they are all true since they are non-empty strings.), the assignment will use the second operand.
Is there a “null coalescing” operator in JavaScript?
The || operator in JavaScript doesn't necessarily return true or false. It's exact behavior is this:
If the first operand is truthy, it evaluates to the first operand. Otherwise, it evaluates to the second.
Why does (false || null) return null, while (null || false) returns false?
Functions
Built-in (global) functions
parseInt - what is the purpose of radix argument?
https://www.w3schools.com/jsref/jsref_parseint.asp
https://davidwalsh.name/parseint-radix
https://stackoverflow.com/questions/6611824/why-do-we-need-to-use-radix
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
https://eloquentjavascript.net/03_functions.html
How to verify that parsing some string as integer was successful?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
Function.prototype.bind()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
Arrow functions
Arrow functions which return a single value don't need braces or parenthesis at all:
The exception is the case when it returns an empty object:
const f = () => {};
// f returns an empty object
This is same as:
const f = () => ({})
or
const f = () => { return {}; }
As shown above, if we want to use curly braces, we need to use
return keyword.
http://2ality.com/2012/04/arrow-functions.html
Arrow function without curly braces
Self-Executing Anonymous Functions
http://markdalgleish.com/2011/03/self-executing-anonymous-functions/
Anonymous self-invoking function (often called "module's side effect") will run when the module is evaluated, which happens when module is imported at least once in some other module (by importing any of its exported variables, functions or classes). [
Importing a self invoking function]
[
Code Example]
I learned this hard way. Had a (Jest) unit test file which was supposed to test some function exported from some other file/module which also contained anonymous self-invoking function. Unit test file was importing named function but each time I'd run tests, this anonymous function would be executed.
Named Arguments
Cool Javascript 9: Named arguments — Functions that get and return Objects
This helped me to understand the code which omits some properties while cloning an object [
source]:
const obj = {a: 1, b: 2, c: 3, d: 4};
const clone = (({b, c, ...others}) => ({...others}))(obj); // remove b and c
This solution puts on display the beauty of JavaScript. Function declared and called in same line. Object passed as an argument is deconstructed to match the object set as argument in function definition. Spread operator. No need for return statement...I am impressed!
How to get a subset of a javascript object's properties
Pure Functions
Pure functions are functions that accept an input and returns a value without modifying any data outside its scope(Side Effects). Its output or return value must depend on the input/arguments and pure functions must return a value.
Immutability comes when we want to preserve our state. To keep our state from changing we have to create a new instance of our state objects. Immutability makes our app state predictable, ups the performance rate of our apps and to easily track changes in state. [
Understanding Javascript Mutation and Pure Functions ]
JavaScript’s object arguments are references, which means that if a function were to mutate a property on an object or array parameter, that would mutate state that is accessible outside the function.
Pure functions must not mutate external state. [
Master the JavaScript Interview: What is a Pure Function? ]
Reassigning parameters deoptimizes in many engines, specifically v8 - it's a horrible idea to do it.
Variables are free, and creating new ones rather than reusing old ones makes code much clearer.
(In addition,
nothing in JS is passed by reference, everything is passed by value, where objects are a form of "reference value" - this is a good read on the subject) [
Thoughts on "Never mutate parameters"]
To mutate, or not to mutate, in JavaScript
Don’t change objects in functions
Do not change objects after construction.
Never mutate parameters.
Never reassign parameters.
Closures
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
Events
Is addEventListener (using listeners) preferred over attaching a handler?
https://www.reddit.com/r/learnjavascript/comments/6erpv2/whats_the_difference_between_using_an_event/
https://teamtreehouse.com/community/addeventlistener-vs-things-like-onclick-onchange-etc-pure-javascript
What is the correct attaching a handler (if go down this route)?
How to avoid wrong double handler execution?
https://stackoverflow.com/questions/7794301/window-onunload-is-not-working-properly-in-chrome-browser-can-any-one-help-me
Describe event phases
(capturing, bubbling...)
https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Examples#Example_5:_Event_Propagation
jQuery - Why returning false from (click) event handler?
https://stackoverflow.com/questions/11184276/return-false-from-jquery-click-event
Event.stopPropagation()
https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation
Promises
http://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects
https://italonascimento.github.io/applying-a-timeout-to-your-promises/
https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#list-of-active-timers
https://stackoverflow.com/questions/31324110/why-does-the-promise-constructor-require-a-function-that-calls-resolve-when-co
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
https://javascript.info/promise-chaining
JavaScript: async/await with forEach()
Should a Promise.reject message be wrapped in Error?
https://stackoverflow.com/questions/26020578/should-a-promise-reject-message-be-wrapped-in-error
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject#Using_the_static_Promise.reject_method
https://stackoverflow.com/questions/26711243/promise-resolve-vs-new-promiseresolve
resolve & reject
`resolve` and `reject` functions inside a Promise's executor
async-await
https://javascript.info/async-await
http://2ality.com/2016/10/async-function-tips.html
(Especially pay attention to point #3 - Returned Promises are not wrapped - which explains when and why await can be omitted)
JavaScript loops - how to handle async/await
JavaScript: async/await with forEach()
RegEx
Comes very handy when need to test string arguments. Instead of lengthy code which would use string functions, testing a string to match some format is a one-liner with RegEx:
test: ({ app_name, app_version }) =>
/myapp/i.test(app_name) && /^12\.3/.test(app_version)
RegExp.prototype.test()
What does the forward slash mean within a JavaScript regular expression?
The slashes indicate the start and end of the regular expression.
Regular expressions have four optional flags that allow for global and case insensitive searching.
- To indicate a global search, use the g flag.
- To indicate a case-insensitive search, use the i flag.
- To indicate a multi-line search, use the m flag.
- To perform a "sticky" search, that matches starting at the current position in the target string, use the y flag.
These flags can be used separately or together in any order, and are included as part of the regular expression.
To include a flag with the regular expression, use this syntax:
var re = /pattern/flags;
Web APIs
WindowOrWorkerGlobalScope
setTimeout()
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout
How to set text in a <span> element?
https://stackoverflow.com/questions/1358810/how-do-i-change-the-text-of-a-span-element-in-javascript#
querySelector vs querySelectorAll
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
https://stackoverflow.com/questions/14377590/queryselector-and-queryselectorall-vs-getelementsbyclassname-and-getelementbyid
When to use (set) innerHTML and when innerText?
tbd...
Misc How Tos
How to declare a constant data member in a class?
https://stackoverflow.com/questions/32647215/declaring-static-constants-in-es6-classes
Best Practices
Airbnb JavaScript Style Guide
JavaScript Rules
https://www.w3schools.com/js/js_best_practices.asp
Check that there is no unnecessary console.log which goes into production.
Check that there are no unused variables.
Check return values of functions (is it null, undefined, empty array, error code etc...)
Make sure of the time order of events and functions...e.g.
document.addEventListener("DOMContentLoaded", function() {..xxx...});
If xxx is never executed but you can see that document has event handler for DOMContentLoaded event that means that the document.addEventListener("DOMContentLoaded" code was executed too late, after DOMContentLoaded event has already been fired!
var btn = document.querySelectorAll("a.btn")[0];
Use querySelector.
I prefer:
var btn = document.querySelector("a.btn");
btn.addEventListener('click', function(e) {
const url = "secure://extensions/?id=dmfdacibleoapmpfdgonigdfinmekhgp";
chrome.tabs.create({ url: url });
});
to:
var btn = document.querySelector("a.btn");
if (btn !== null) {
btn.addEventListener('click', function(e) {
const url = "secure://extensions/?id=dmfdacibleoapmpfdgonigdfinmekhgp";
chrome.tabs.create({ url: url });
});
} else {
console.log(“WARNING: a.btn element not found.”);
}
as console.log message would probably be unnoticed in the log while exception thrown in case btn is null would be marked in red in console log.
use _xxx for private member variables
use no special naming for global variables because try to avoid globals outside of application constants
Consts write as MY_CONST.
This function has a lot of side effects on the DOM and global multimap. Not necessarily a problem, although the function name doesn't communicate this. A nicer way may be restructure the app to have a function that returns a state object and then hands this off to a function which generates/mutates the DOM. It's a more "functional" way of doing it anyway! Personal preference.
when you say "state object", do you mean data (e.g. optimalGateway and multimap) in this case?
I mean an object representing all data within the application. Granted, this is quite a Redux/React way of thinking and is harder to implement with a bunch of jquery, so it may not be appropriate. Still, if I'm calling a function called loadDataFromBackgroundPage at the top level with no return value, it is very unclear that is going to have side effects on the DOM. I would expect it to have a return value of that data, and no side effects. Then that data could be handed off to another function to handle the rendering.
$() equivalent to $(document).ready()
$(handler) is now preferred to $(document).ready(handler) (https://api.jquery.com/ready/)
I have two similar handlers for $(document).click in this code so I'm going to merge them.
Function name capitalisation consistency.
selectedGatewayId = vpnExtensionEngine.getGateways().find(g => g.city.name + ", " + g.country.name === selectedLocation).id;
If find returns undefined, we'll get an error here. Might be worth adding a check for this or catching the error.
All parseInt calls should specify the base. e.g. parseInt(unixTimestampString, 10)
(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt confirms this)
Another DOM ready handler. Can we condense these in to one?
var url = "
https://extension.avastbrowser.com/vpn/about/";
Move to const?
replace var with let wherever applicable.
Instead of looping infinitely and throwing, can we adjust this condition?
That's certainly better approach as exception is used here to control the flow of execution (and not to signal exceptional behaviour).
use setTimeout vs setInterval and clearing it immediately in the callback
Callback has to be executed only once, after timeout so it makes more sense to use setTimeout
const serverApiVersionMajor = lightVpnControllerApiVersion.split(".")[0];
const serverApiVersionMinor = lightVpnControllerApiVersion.split(".")[1];
Array destructuring supported in Chrome 49+, so could rewrite these two lines as:
const [serverApiVersionMajor, serverApiVersionMinor] = lightVpnControllerApiVersion.split(".")
Arrow functions are used elsewhere, so could use one here as well for compactness. Personal preference. Also, you wouldn't need the .bind(this) as the arrow function doesn't create a closure.
Chrome 42+ supports the fetch API. More compact and returns a promise, so don't need to wrap it like this.
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
General tips:
https://news.ycombinator.com/item?id=17466391
Stack Overflow:
https://stackoverflow.com/questions/tagged/javascript
Packages
https://socket.io/
http://tesseract.projectnaptha.com/
Cool Tips and Tricks
How to print the name of the JS file currently loaded in html?
console.log('Loading script: ' + document.currentScript.src);
https://stackoverflow.com/questions/22095529/hiding-everything-until-the-page-has-finished-loading?noredirect=1&lq=1
https://en.wikipedia.org/wiki/Flash_of_unstyled_content
https://en.wikipedia.org/wiki/Screen_reader
https://stackoverflow.com/questions/2690865/visibility-attribute-question
How to add a line break to the string in messages.json?
https://phraseapp.com/docs/guides/formats/chrome-json/
https://github.com/angular-translate/angular-translate/issues/595
https://developer.mozilla.org/en-US/docs/Mozilla/Localization/Localization_content_best_practices
Where should I put <script> tags in HTML markup?
Remove Render-Blocking JavaScript
JavaScript Where To
String literals:
console.log(‘Hello, world!’)
or
console.log("Hello, world!")
What is lexical scope?
What is "this"?
What is Lexical Scope Anyway?
How do I write a named arrow function in ES2015?
Why is the content of some js files wrapped inside a function which is wrapped inside anonymous self-executed function?
(function () {...})();
What is the purpose of wrapping whole Javascript files in anonymous functions like “(function(){ … })()”?
Self-Executing Anonymous Functions
Immediately Invoked Function Expression (IIFE)
What does “use strict” do in JavaScript, and what is the reasoning behind it?
Should I 'use strict' for every single javascript function I write?
Not recommended to use “use strict” in ES6?
Strict Mode
What is this Javascript “require”?
What is require?
Requiring modules in Node.js: Everything you need to know
Commonly accepted best practices around code organization in JavaScript
ECMA-262, 9th edition, June 2018
What is the difference between String.slice and String.substring?
Create a JavaScript array containing 1…N
Tasks, microtasks, queues and schedules
https://codeburst.io/javascript-quickie-dot-notation-vs-bracket-notation-333641c0f781
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence