IDE-Editor choice
If you haven’t selected an IDE yet, consider the following options:- WebStorm for frontend development. The same company offers other editors for other languages (paid).
- Netbeans (free).
All of these IDEs are cross-platform.
For Windows, there’s also “Visual Studio”, not to be confused with “Visual Studio Code.” “Visual Studio” is a paid and mighty Windows-only editor, well-suited for the .NET platform. A free version of it is called Visual Studio Community.
+
always
+
Var takes global or function scope and is always declared at start, regardless of where it is written. Assignment is still in place though.
use 'let' and 'const' instead.+
always
"use strict"; at top of file or in function header+
Var takes global or function scope and is always declared at start, regardless of where it is written. Assignment is still in place though.
+
Besides regular numbers, there are so-called “special numeric values” which also belong to this data type:
Infinity, -Infinity and NaN.NaN represents a computational error. It is a result of an incorrect or an undefined mathematical operationNaN is sticky. Any further operation on NaN returns NaN+
there are 3 types of quotes.
- Double quotes:
"Hello". - Single quotes:
'Hello'. - Backticks:
`Hello`.
Double and single quotes are “simple” quotes. There’s no difference between them in JavaScript.
Backticks are “extended functionality” quotes. They allow us to embed variables and expressions into a string by wrapping them in ${…}
for example,
+
alert( `Hello, ${name}!` );+
null is just a special value which represents “nothing”, “empty” or “value unknown”.
The meaning of
undefined is “value is not assigned”.
+
objects are used to store collections of data and more complex entities.
+
typeof operator returns the type of the argument
+
type conversion; explicit for toString, toNumber, toBoolean.
+
A strict equality operator
=== checks the equality without type conversion.
In other words, if
note!! non-strict null==undefined. is true, null===undefined is false.
a and b are of different types, then a === b immediately returns false without an attempt to convert themnote!! non-strict null==undefined. is true, null===undefined is false.
+
We covered 3 browser-specific functions to interact with visitors:
alert("hello")- shows a message.
prompt("Type a number", 4) // 4 would be default- shows a message asking the user to input text. It returns the text or, if CANCEL or Esc is clicked,
null. confirm("please confirm")- shows a message and waits for the user to press “OK” or “CANCEL”. It returns
truefor OK andfalsefor CANCEL/Esc. - +
- conditional if (), else if(), else
- or ternary operator- condition? true : false;
- +
- conditional loops all as expected;
- while, do-while, for(;;), and for each
- break optional_label, and continue
- label is just 'labelexample:'
- +
- switch will cascade without breaks
switch(x){case'value1':// if (x === 'value1')...[break]case'value2':// if (x === 'value2')...[break]default:...[break]}- Any expression can be a
switch/caseargument but case must check same type - +
- functions...
- This function declaration
functionsayHi(){alert("Hello");}- is the basically the same as this function expression
letsayHi=function(){alert("Hello");};- A function is JS is a value and can be treated as such, including be reassigned.
- function expression needs semi-colon because its part of an expression.
- callback values can take a function name or an inline / anonymous function ie
function(){alert("You agreed.");}, A Function Declaration is usable in the whole script/code block.When a Function Declaration is made within a code block, it is visible everywhere inside that block. But not outside of it.A Function Expression is created when the execution reaches it and is usable from then on.- +
- Arrow functions
letsum=(a,b)=>a+b;/* The arrow function is a shorter form of: let sum = function(a, b) { return a + b; }; */- If we have only one argument, then parentheses can be omitted:
// same as// let double = function(n) { return n * 2 }letdouble=n=>n*2;- If there are no arguments, parentheses should be empty (but they should be present):
letsayHi=()=>alert("Hello!");- multiline example using curly braces and a return
letsum=(a,b)=>{// the curly brace opens a multiline functionletresult=a+b;returnresult;// if we use curly braces, use return to get results};Summary
- Functions are values. They can be assigned, copied or declared in any place of the code.
- If the function is declared as a separate statement in the main code flow, that’s called a “Function Declaration”.
- If the function is created as a part of an expression, it’s called a “Function Expression”.
- Function Declarations are processed before the code block is executed. They are visible everywhere in the block.
- Function Expressions are created when the execution flow reaches them.
In most cases when we need to declare a function, a Function Declaration is preferable, because it is visible prior to the declaration itself. That gives us more flexibility in code organization, and is usually more readable.So we should use a Function Expression only when a Function Declaration is not fit for the task. We’ve seen a couple of examples of that in this chapter, and will see more in the future.Arrow functions are handy for one-liners. They come in two flavors:
- Without curly braces:
(...args) => expression– the right side is an expression: the function evaluates it and returns the result. - With curly braces:
(...args) => { body }– brackets allow us to write multiple statements inside the function, but we need an explicitreturnto return something.
- Functions may have local variables: those declared inside its body. Such variables are only visible inside the function.
- Parameters can have default values:
function sum(a = 1, b = 2) {...}. - Functions always return something. If there’s no
returnstatement, then the result isundefined.
- +
Debugger command
We can also pause the code by using thedebuggercommand, like this:functionhello(name){letphrase=`Hello,${name}!`;debugger;// <-- the debugger stops heresay(phrase);}
That’s very convenient when we are in a code editor and don’t want to switch to the browser and look up the script in developer tools to set the breakpoint.- +
- documentation
Good comments
So, explanatory comments are usually bad. Which comments are good?- Describe the architecture
- Provide a high-level overview of components, how they interact, what’s the control flow in various situations… In short – the bird’s eye view of the code. There’s a special diagram language UML for high-level architecture diagrams. Definitely worth studying.
- Document a function usage
- There’s a special syntax JSDoc to document a function: usage, parameters, returned value.For instance:
/** * Returns x raised to the n-th power. * * @param {number} x The number to raise. * @param {number} n The power, must be a natural number. * @return {number} x raised to the n-th power. */functionpow(x,n){...}Such comments allow us to understand the purpose of the function and use it the right way without looking in its code.
- +
- Unit testing with mocha
- https://mochajs.org
- https://javascript.info/testing-mocha go back and read this later.
- one more rule that’s good to follow.
One test checks one thing. - +
- Objects
- An empty object (“empty cabinet”) can be created using one of two syntaxes:
letuser=newObject();// "object constructor" syntaxletuser={};// "object literal" syntax Literals and properties
We can immediately put some properties into{...}as “key: value” pairs:
letuser={// an objectname:"John",// by key "name" store value "John"age:30// by key "age" store value 30};- To remove a property, we can use
deleteoperator:
deleteuser.age; - We can also use multiword property names, but then they must be quoted:
letuser={name:"John",age:30,"likes birds":true// multiword property name must be quoted}; - The last property in the list may end with a comma:
letuser={name:"John",age:30,}
That is called a “trailing” or “hanging” comma. Makes it easier to add/remove/move around properties, because all lines become alike. Square brackets
For multiword properties, the dot access doesn’t work:// this would give a syntax erroruser.likes birds=trueThat’s because the dot requires the key to be a valid variable identifier. That is: no spaces and other limitations.There’s an alternative “square bracket notation” that works with any string:
letuser={};// setuser["likes birds"]=true;// getalert(user["likes birds"]);// true// deletedeleteuser["likes birds"];Property value shorthand
In real code we often use existing variables as values for property names.For instance:functionmakeUser(name,age){return{name:name,age:age// ...other properties};}letuser=makeUser("John",30);alert(user.name);// JohnIn the example above, properties have the same names as variables. The use-case of making a property from a variable is so common, that there’s a special property value shorthand to make it shorter.Instead ofname:namewe can just writename, like this:functionmakeUser(name,age){return{name,// same as name: nameage// same as age: age// ...};}We can use both normal properties and shorthands in the same object:
letuser={name,// same as name:nameage:30};Existence check
A notable objects feature is that it’s possible to access any property. There will be no error if the property doesn’t exist! Accessing a non-existing property just returnsundefined. It provides a very common way to test whether the property exists – to get it and compare vs undefined:letuser={};alert(user.noSuchProperty===undefined);// true means "no such property"There also exists a special operator"in"to check for the existence of a property.The syntax is:"key"inobjectFor instance:letuser={name:"John",age:30};alert("age"inuser);// true, user.age existsalert("blabla"inuser);// false, user.blabla doesn't existPlease note that on the left side ofinthere must be a property name. That’s usually a quoted string.If we omit quotes, that would mean a variable containing the actual name will be tested. For instance:letuser={age:30};letkey="age";alert(keyinuser);// true, takes the name from key and checks for such property
Using “in” for properties that storeundefinedUsually, the strict comparison"=== undefined"check works fine. But there’s a special case when it fails, but"in"works correctly.It’s when an object property exists, but storesundefined:letobj={test:undefined};alert(obj.test);// it's undefined, so - no such property?alert("test"inobj);// true, the property does exist!In the code above, the propertyobj.testtechnically exists. So theinoperator works right.Situations like this happen very rarely, becauseundefinedis usually not assigned. We mostly usenullfor “unknown” or “empty” values. So theinoperator is an exotic guest in the code.The “for…in” loop
To walk over all keys of an object, there exists a special form of the loop:for..in. This is a completely different thing from thefor(;;)construct that we studied before.The syntax:for(keyinobject){// executes the body for each key among object properties}- primitives are used by value, objects by reference.
Summary
Objects are associative arrays with several special features.They store properties (key-value pairs), where:- Property keys must be strings or symbols (usually strings).
- Values can be of any type.
To access a property, we can use:- The dot notation:
obj.property. - Square brackets notation
obj["property"]. Square brackets allow to take the key from a variable, likeobj[varWithKey].
Additional operators:- To delete a property:
delete obj.prop. - To check if a property with the given key exists:
"key" in obj. - To iterate over an object:
for (let key in obj)loop.
Objects are assigned and copied by reference. In other words, a variable stores not the “object value”, but a “reference” (address in memory) for the value. So copying such a variable or passing it as a function argument copies that reference, not the object. All operations via copied references (like adding/removing properties) are performed on the same single object.To make a “real copy” (a clone) we can useObject.assignor _.cloneDeep(obj).What we’ve studied in this chapter is called a “plain object”, or justObject.There are many other kinds of objects in JavaScript:Arrayto store ordered data collections,Dateto store the information about the date and time,Errorto store the information about an error.- …And so on.
They have their special features that we’ll study later. Sometimes people say something like “Array type” or “Date type”, but formally they are not types of their own, but belong to a single “object” data type. And they extend it in various ways.Objects in JavaScript are very powerful. Here we’ve just scratched the surface of a topic that is really huge. We’ll be closely working with objects and learning more about them in further parts of the tutorial.- +
- symbols in objects
- https://javascript.info/symbol
Summary
Symbolis a primitive type for unique identifiers.Symbols are created withSymbol()call with an optional description.Symbols are always different values, even if they have the same name. If we want same-named symbols to be equal, then we should use the global registry:Symbol.for(key)returns (creates if needed) a global symbol withkeyas the name. Multiple calls ofSymbol.forreturn exactly the same symbol.Symbols have two main use cases:- “Hidden” object properties. If we want to add a property into an object that “belongs” to another script or a library, we can create a symbol and use it as a property key. A symbolic property does not appear in
for..in, so it won’t be occasionally listed. Also it won’t be accessed directly, because another script does not have our symbol, so it will not occasionally intervene into its actions.So we can “covertly” hide something into objects that we need, but others should not see, using symbolic properties. - There are many system symbols used by JavaScript which are accessible as
Symbol.*. We can use them to alter some built-in behaviors. For instance, later in the tutorial we’ll useSymbol.iteratorfor iterables,Symbol.toPrimitiveto setup object-to-primitive conversion and so on.
Technically, symbols are not 100% hidden. There is a built-in method Object.getOwnPropertySymbols(obj)that allows us to get all symbols. Also there is a method named Reflect.ownKeys(obj) that returns all keys of an object including symbolic ones. So they are not really hidden. But most libraries, built-in methods and syntax constructs adhere to a common agreement that they are. And the one who explicitly calls the aforementioned methods probably understands well what he’s doing.- +
- object methods and 'this'
Summary
- Functions that are stored in object properties are called “methods”.
- Methods allow objects to “act” like
object.doSomething(). - Methods can reference the object as
this.
The value ofthisis defined at run-time.- When a function is declared, it may use
this, but thatthishas no value until the function is called. - That function can be copied between objects.
- When a function is called in the “method” syntax:
object.method(), the value ofthisduring the call isobject.
Please note that arrow functions are special: they have nothis. Whenthisis accessed inside an arrow function, it is taken from outside.- +
- numbers
Summary
To write big numbers:- Append
"e"with the zeroes count to the number. Like:123e6is123with 6 zeroes. - A negative number after
"e"causes the number to be divided by 1 with given zeroes. That’s for one-millionth or such.
For different numeral systems:- Can write numbers directly in hex (
0x), octal (0o) and binary (0b) systems parseInt(str, base)parses an integer from any numeral system with base:2 ≤ base ≤ 36.num.toString(base)converts a number to a string in the numeral system with the givenbase.
For converting values like12ptand100pxto a number:- Use
parseInt/parseFloatfor the “soft” conversion, which reads a number from a string and then returns the value they could read before the error.
For fractions:- Round using
Math.floor,Math.ceil,Math.trunc,Math.roundornum.toFixed(precision). - Make sure to remember there’s a loss of precision when working with fractions.
More mathematical functions:- See the Math object when you need them. The library is very small, but can cover basic needs.
- Append
- +
- strings are immutable. If you need to change, make new one.
- string.length is a property not a method, so no ()
- string
[]to access characters. (or charAt()). first retusns char or undefined. Second returns char or "" - We can also iterate over characters using
for..of: - Methods toLowerCase() and toUpperCase() change the case:
Searching for a substring
There are multiple ways to look for a substring within a string.str.indexOf
The first method is str.indexOf(substr, pos).letstr='Widget with id';alert(str.indexOf('id',2))// 12- str.lastIndexOf(substr, position) does this in reverse
includes, startsWith, endsWith
The more modern method str.includes(substr, pos) returnstrue/falsedepending on whetherstrcontainssubstrwithin.It’s the right choice if we need to test for the match, but don’t need its position:alert("Widget with id".includes("Widget"));// truealert("Hello".includes("Bye"));// falseThe optional second argument ofstr.includesis the position to start searching from:alert("Midget".includes("id"));// truealert("Midget".includes("id",3));// false, from position 3 there is no "id"The methods str.startsWith and str.endsWith do exactly what they say:alert("Widget".startsWith("Wid"));// true, "Widget" starts with "Wid"alert("Widget".endsWith("get"));// true, "Widget" ends with "get"Getting a substring
There are 3 methods in JavaScript to get a substring:substring,substrandslice.
str.slice(start [, end])- Returns the part of the string from
startto (but not including)end.For instance:letstr="stringify";alert(str.slice(0,5));// 'strin', the substring from 0 to 5 (not including 5)alert(str.slice(0,1));// 's', from 0 to 1, but not including 1, so only character at 0
- Negative values for
start/endare also possible. They mean the position is counted from the string end: Summary
Array is a special kind of object, suited to storing and managing ordered data items.- The declaration:
// square brackets (usual)letarr=[item1,item2...];// new Array (exceptionally rare)letarr=newArray(item1,item2...);The call tonew Array(number)creates an array with the given length, but without elements. - The
lengthproperty is the array length or, to be precise, its last numeric index plus one. It is auto-adjusted by array methods. - If we shorten
lengthmanually, the array is truncated.
We can use an array as a deque with the following operations:push(...items)addsitemsto the end.pop()removes the element from the end and returns it.shift()removes the element from the beginning and returns it.unshift(...items)adds items to the beginning.
To loop over the elements of the array:for (let i=0; i<arr.length; i++)– works fastest, old-browser-compatible.for (let item of arr)– the modern syntax for items only,for (let i in arr)– never use.
We will return to arrays and study more methods to add, remove, extract elements and sort arrays in the chapter Array methods.Summary
A cheatsheet of array methods:- To add/remove elements:
push(...items)– adds items to the end,pop()– extracts an item from the end,shift()– extracts an item from the beginning,unshift(...items)– adds items to the beginning.splice(pos, deleteCount, ...items)– at indexposdeletedeleteCountelements and insertitems.slice(start, end)– creates a new array, copies elements from positionstarttillend(not inclusive) into it.concat(...items)– returns a new array: copies all members of the current one and addsitemsto it. If any ofitemsis an array, then its elements are taken.
- To search among elements:
indexOf/lastIndexOf(item, pos)– look foritemstarting from positionpos, return the index or-1if not found.includes(value)– returnstrueif the array hasvalue, otherwisefalse.find/filter(func)– filter elements through the function, return first/all values that make it returntrue.findIndexis likefind, but returns the index instead of a value.
- To iterate over elements:
forEach(func)– callsfuncfor every element, does not return anything.
- To transform the array:
map(func)– creates a new array from results of callingfuncfor every element.sort(func)– sorts the array in-place, then returns it.reverse()– reverses the array in-place, then returns it.split/join– convert a string to array and back.reduce(func, initial)– calculate a single value over the array by callingfuncfor each element and passing an intermediate result between the calls.
- Additionally:
Array.isArray(arr)checksarrfor being an array.
Please note that methodssort,reverseandsplicemodify the array itself.These methods are the most used ones, they cover 99% of use cases. But there are few others:- arr.some(fn)/arr.every(fn) checks the array.The function
fnis called on each element of the array similar tomap. If any/all results aretrue, returnstrue, otherwisefalse. - arr.copyWithin(target, start, end) – copies its elements from position
starttill positionendinto itself, at positiontarget(overwrites existing).
For the full list, see the manual.From the first sight it may seem that there are so many methods, quite difficult to remember. But actually that’s much easier than it seems.Look through the cheatsheet just to be aware of them. Then solve the tasks of this chapter to practice, so that you have experience with array methods.
Afterwards whenever you need to do something with an array, and you don’t know how – come here, look at the cheatsheet and find the right method. Examples will help you to write it correctly. Soon you’ll automatically remember the methods, without specific efforts from your side.- +
- read again later.
- https://javascript.info/iterable
- +
No comments:
Post a Comment