react jsx

html ## react ### jsx `const element =

Hello, world!

;` This funny tag syntax is neither a string nor HTML. It is called JSX, and it is a syntax extension to JavaScript. We recommend using it with React to describe what the UI should look like. JSX may remind you of a template language, but it comes with the full power of JavaScript. JSX produces React “elements”. Instead of artificially separating technologies by putting markup and logic in separate files, React separates concerns with loosely coupled units called “components” that contain both. - Embedding Expressions in JSX In the example below, we declare a variable called name and then use it inside JSX by wrapping it in curly braces: const name = 'Josh Perez'; const element =

Hello, {name}

; - JSX is an Expression Too After compilation, JSX expressions become regular JavaScript function calls and evaluate to JavaScript objects. This means that you can use JSX inside of if statements and for loops, assign it to variables, accept it as arguments, and return it from functions:
1
2
3
4
5
6
function getGreeting(user) {
if (user) {
return <h1>Hello, {formatName(user)}!</h1>;
}
return <h1>Hello, Stranger.</h1>;
}
- Specifying Attributes with JSX You may use quotes to specify string literals as attributes: `const element = link ;` You may also use curly braces to embed a JavaScript expression in an attribute: `const element = ;` - Specifying Children with JSX If a tag is empty, you may close it immediately with />, like XML: `const element = ;` JSX tags may contain children:
1
2
3
4
5
6
const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);
- JSX Prevents Injection Attacks It is safe to embed user input in JSX: const title = response.potentiallyMaliciousInput; // This is safe: const element =

{title}

; By default, React DOM escapes any values embedded in JSX before rendering them. Thus it ensures that you can never inject anything that’s not explicitly written in your application. Everything is converted to a string before being rendered. This helps prevent XSS (cross-site-scripting) attacks. - Which characters need to be escaped in HTML inserting text content in your document in a location where text content is expected By "a location where text content is expected", I mean inside of an element or quoted attribute value where normal parsing rules apply. For example:

HERE

or

...

. Inside of an element, this just includes the entity escape ampersand & and the element delimiter less-than and greater-than signs < >: & becomes & < becomes < > becomes > Inside of attribute values you must also escape the quote character you're using: " becomes " ' becomes ' I encourage you to escape all five in all cases to reduce the chance of making a mistake. In general, you should not escape spaces as  .   is not a normal space, it's a non-breaking space. You can use these instead of normal spaces to prevent a line break from being inserted between two words, or to insert extra space without it being automatically collapsed, but this is usually a rare case. Don't do this unless you have a design constraint that requires it. - ! content that has special parsing rules or meaning, such as inside of a script or style tag, or as an element or attribute name. For example: `..., , , or

...

.` In these contexts, the rules are more complicated and it's much easier to introduce a security vulnerability. I strongly discourage you from ever inserting dynamic content in any of these locations. There's usually a safer alternative, such as putting the dynamic value in an attribute and then handling it with JavaScript. - JSX Represents Objects Babel compiles JSX down to React.createElement() calls. These two examples are identical:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
React.createElement() performs a few checks to help you write bug-free code but essentially it creates an object like this:

// Note: this structure is simplified
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world!'
}
};
These objects are called “React elements”. You can think of them as descriptions of what you want to see on the screen. ### Rendering an Element into the DOM Let’s say there is a
somewhere in your HTML file: `
` We call this a “root” DOM node because everything inside it will be managed by React DOM. Applications built with just React usually have a single root DOM node. If you are integrating React into an existing app, you may have as many isolated root DOM nodes as you like. To render a React element, first pass the DOM element to ReactDOM.createRoot(), then pass the React element to root.render():
1
2
3
4
5
const root = ReactDOM.createRoot(
document.getElementById('root')
);
const element = <h1>Hello, world</h1>;
root.render(element);
### Function and Class Components The simplest way to define a component is to write a JavaScript function: function Welcome(props) { return

Hello, {props.name}

; } This function is a valid React component because it accepts a single “props” (which stands for properties) object argument with data and returns a React element. We call such components “function components” because they are literally JavaScript functions. You can also use an ES6 class to define a component:
1
2
3
4
5
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
The above two components are equivalent from React’s point of view. - Composing Components Components can refer to other components in their output. This lets us use the same component abstraction for any level of detail. A button, a form, a dialog, a screen: in React apps, all those are commonly expressed as components. For example, we can create an App component that renders Welcome many times:
1
2
3
4
5
6
7
8
9
10
11
12
13
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}

function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
- Extracting Components Don’t be afraid to split components into smaller components. For example, consider this Comment component:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
It accepts author (an object), text (a string), and date (a date) as props, and describes a comment on a social media website. This component can be tricky to change because of all the nesting, and it is also hard to reuse individual parts of it. Let’s extract a few components from it. First, we will extract Avatar:
1
2
3
4
5
6
7
8
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
The Avatar doesn’t need to know that it is being rendered inside a Comment. This is why we have given its prop a more generic name: user rather than author. We recommend naming props from the component’s own point of view rather than the context in which it is being used. We can now simplify Comment a tiny bit:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<Avatar user={props.author} />
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
Next, we will extract a UserInfo component that renders an Avatar next to the user’s name:
1
2
3
4
5
6
7
8
9
10
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}
This lets us simplify Comment even further:
1
2
3
4
5
6
7
8
9
10
11
12
13
function Comment(props) {
return (
<div className="Comment">
<UserInfo user={props.author} />
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
- Props are Read-Only Whether you declare a component as a function or a class, it must never modify its own props. - Adding Local State to a Class -
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}

render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Clock />);
- Adding Lifecycle Methods to a Class We want to set up a timer whenever the Clock is rendered to the DOM for the first time. This is called “mounting” in React. We also want to clear that timer whenever the DOM produced by the Clock is removed. This is called “unmounting” in React.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}

componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}

componentWillUnmount() {
clearInterval(this.timerID);
}

tick() {
this.setState({
date: new Date()
});
}

render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Clock />);
1. When the Clock output is inserted in the DOM, React calls the componentDidMount() lifecycle method. Inside it, the Clock component asks the browser to set up a timer to call the component’s tick() method once a second. 2. Every second the browser calls the tick() method. Inside it, the Clock component schedules a UI update by calling setState() with an object containing the current time. 3. Thanks to the setState() call, React knows the state has changed, and calls the render() method again to learn what should be on the screen. This time, this.state.date in the render() method will be different, and so the render output will include the updated time. React updates the DOM accordingly. 4. If the Clock component is ever removed from the DOM, React calls the componentWillUnmount() lifecycle method so the timer is stopped. - State Updates May Be Asynchronous React may batch multiple setState() calls into a single update for performance. Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state. For example, this code may fail to update the counter: // Wrong
1
2
3
this.setState({
counter: this.state.counter + this.props.increment,
});
To fix it, use a second form of setState() that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument: // Correct
1
2
3
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
### Handling Events Handling events with React elements is very similar to handling events on DOM elements. There are some syntax differences: React events are named using camelCase, rather than lowercase. With JSX you pass a function as the event handler, rather than a string. - this You have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};

// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}

handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}

render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
use public class fields syntax to correctly bind callbacks:
1
2
3
4
5
6
7
8
9
10
11
12
13
class LoggingButton extends React.Component {
// This syntax ensures `this` is bound within handleClick.
handleClick = () => {
console.log('this is:', this);
};
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
If you aren’t using class fields syntax, you can use an arrow function in the callback:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}

render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={() => this.handleClick()}>
Click me
</button>
);
}
}
The problem with this syntax is that a different callback is created each time the LoggingButton renders. In most cases, this is fine. However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the class fields syntax, to avoid this sort of performance problem. - Passing Arguments to Event Handlers Inside a loop, it is common to want to pass an extra parameter to an event handler. For example, if id is the row ID, either of the following would work: `` `` The above two lines are equivalent, and use arrow functions and Function.prototype.bind respectively. In both cases, the e argument representing the React event will be passed as a second argument after the ID. With an arrow function, we have to pass it explicitly, but with bind any further arguments are automatically forwarded. - While declaring a variable and using an if statement is a fine way to conditionally render a component, sometimes you might want to use a shorter syntax - Inline If with Logical && Operator It works because in JavaScript, true && expression always evaluates to expression, and false && expression always evaluates to false. Therefore, if the condition is true, the element right after && will appear in the output. If it is false, React will ignore and skip it. Note that returning a falsy expression will still cause the element after && to be skipped but will return the falsy expression. In the example below,
0
will be returned by the render method.
1
2
3
4
5
6
7
8
render() {
const count = 0;
return (
<div>
{count && <h1>Messages: {count}</h1>}
</div>
);
}
- Inline If-Else with Conditional Operator Another method for conditionally rendering elements inline is to use the JavaScript conditional operator condition ? true : false. Preventing Component from Rendering In rare cases you might want a component to hide itself even though it was rendered by another component. To do this return null instead of its render output.
1
2
3
4
5
6
7
8
9
10
11
function WarningBanner(props) {
if (!props.warn) {
return null;
}

return (
<div className="warning">
Warning!
</div>
);
}
- Rendering Multiple Components You can build collections of elements and include them in JSX using curly braces {}. Below, we loop through the numbers array using the JavaScript map() function. We return a
  • element for each item. Finally, we assign the resulting array of elements to listItems: const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) =>
  • {number}
  • ); Then, we can include the entire listItems array inside a
      element: When you run code, you’ll be given a warning that a key should be provided for list items. A “key” is a special string attribute you need to include when creating lists of elements.
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      function NumberList(props) {
      const numbers = props.numbers;
      const listItems = numbers.map((number) =>
      <li key={number.toString()}>
      {number}
      </li>
      );
      return (
      <ul>{listItems}</ul>
      );
      }
      - Keys Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity: We don’t recommend using indexes for keys if the order of items may change. This can negatively impact performance and may cause issues with component state. Example: Incorrect Key Usage
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      function ListItem(props) {
      const value = props.value;
      return (
      // Wrong! There is no need to specify the key here:
      <li key={value.toString()}>
      {value}
      </li>
      );
      }

      function NumberList(props) {
      const numbers = props.numbers;
      const listItems = numbers.map((number) =>
      // Wrong! The key should have been specified here:
      <ListItem value={number} />
      );
      return (
      <ul>
      {listItems}
      </ul>
      );
      }
      Example: Correct Key Usage
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      function ListItem(props) {
      // Correct! There is no need to specify the key here:
      return <li>{props.value}</li>;
      }

      function NumberList(props) {
      const numbers = props.numbers;
      const listItems = numbers.map((number) =>
      // Correct! Key should be specified inside the array.
      <ListItem key={number.toString()} value={number} />
      );
      return (
      <ul>
      {listItems}
      </ul>
      );
      }
      - Embedding map() in JSX JSX allows embedding any expression in curly braces so we could inline the map() result:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      function NumberList(props) {
      const numbers = props.numbers;
      return (
      <ul>
      {numbers.map((number) =>
      <ListItem key={number.toString()}
      value={number} />
      )}
      </ul>
      );
      }
      - Composition vs Inheritance React has a powerful composition model, and we recommend using composition instead of inheritance to reuse code between components. - Containment Some components don’t know their children ahead of time. This is especially common for components like Sidebar or Dialog that represent generic “boxes”. We recommend that such components use the special children prop to pass children elements directly into their output:
      1
      2
      3
      4
      5
      6
      7
      function FancyBorder(props) {
      return (
      <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
      </div>
      );
      }
      This lets other components pass arbitrary children to them by nesting the JSX:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      function WelcomeDialog() {
      return (
      <FancyBorder color="blue">
      <h1 className="Dialog-title">
      Welcome
      </h1>
      <p className="Dialog-message">
      Thank you for visiting our spacecraft!
      </p>
      </FancyBorder>
      );
      }
      Try it on CodePen Anything inside the JSX tag gets passed into the FancyBorder component as a children prop. Since FancyBorder renders {props.children} inside a
      , the passed elements appear in the final output. - sometimes you might need multiple “holes” in a component. In such cases you may come up with your own convention instead of using children:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      function SplitPane(props) {
      return (
      <div className="SplitPane">
      <div className="SplitPane-left">
      {props.left}
      </div>
      <div className="SplitPane-right">
      {props.right}
      </div>
      </div>
      );
      }

      function App() {
      return (
      <SplitPane
      left={
      <Contacts />
      }
      right={
      <Chat />
      } />
      );
      }
      Try it on CodePen React elements like and are just objects, so you can pass them as props like any other data. This approach may remind you of “slots” in other libraries but there are no limitations on what you can pass as props in React. - Specialization Sometimes we think about components as being “special cases” of other components. For example, we might say that a WelcomeDialog is a special case of Dialog.
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      function Dialog(props) {
      return (
      <FancyBorder color="blue">
      <h1 className="Dialog-title">
      {props.title}
      </h1>
      <p className="Dialog-message">
      {props.message}
      </p>
      {props.children}
      </FancyBorder>
      );
      }


      class SignUpDialog extends React.Component {
      constructor(props) {
      super(props);
      this.handleChange = this.handleChange.bind(this);
      this.handleSignUp = this.handleSignUp.bind(this);
      this.state = {login: ''};
      }

      render() {
      return (
      <Dialog title="Mars Exploration Program"
      message="How should we refer to you?">
      <input value={this.state.login}
      onChange={this.handleChange} />
      <button onClick={this.handleSignUp}>
      Sign Me Up!
      </button>
      </Dialog>
      );
      }

      handleChange(e) {
      this.setState({login: e.target.value});
      }

      handleSignUp() {
      alert(`Welcome aboard, ${this.state.login}!`);
      }
      }

    the complete javascript course zero to expert

    fundamentas 01

    alert("Hello World!")

    1
    2
    3
    4
    let js = 'amazing';
    if (js === 'amazing') alert('Javascript is FUN!');
    js = 'boring';
    if (js === 'amazing') alert('Javascript is FUN!');

    javascript is a high-level object-oriented, multi-paradigm programming language

    programming language: instruct computer to do things
    high level: we dont have to worry about complex stuff like memory management
    object oriented: based on objects, for storing most kinds of data
    multi paradigm: we can use different styles of programming

    • dynamic effects and web applications in the browser -> react agular vue
    • web applications on web servers -> nodejs
    • native mobile applications -> native react, ionic
    • native desktop applications -> electorn

    ES6/ES2015

    1
    2
    40 + 8 + 23 - 10;
    console.log(40 + 8 + 23 - 10);

    value and variables

    1
    2
    3
    4
    5
    6
    7
    console.log('Jonas');
    console.log(23);

    let firstName = 'Matilda';
    console.log(firstName);
    console.log(firstName);
    console.log(firstName);

    camlcase
    let first = 'Jonas';
    let firstNamePerson;

    error number first
    let 2ads = 2;

    letter
    number8
    undersocre_
    dollarsign$

    no key word

    constants
    PI

    class name
    Person

    name descriptive
    let myFirstJob = 'Programmer';
    let myCurrentJob = 'Teacher';
    not
    let job1 = 'Programmer';
    let job2 = 'Teacher';

    data types

    dymatic type

    object or primitive

    primitive

    number
    floating point used for dicimals and integers

    string
    sequence of characters

    boolean
    true or false

    undifined
    value taken by a variable that is not yet defined(‘empty value’)
    let children;

    null

    symbol(es2015)
    unique and cannot be changed

    bigint(es2020)
    larger integers

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    // console.log(true);
    let javascriptIsFun = true;
    console.log(javascriptIsFun);

    // console.log(typeof true); // 'boolean'
    console.log(typeof javascriptIsFun); // 'boolean'
    // console.log(typeof 23); // 'number'
    // console.log(typeof 'Jonas'); // 'string'
    // console.log(typeof "Jonas"); // 'string'

    javascriptIsFun = 'YES!';
    console.log(typeof javascriptIsFun); // 'string'

    let year;
    console.log(year); // undefined
    console.log(typeof year); // 'undefined'

    year = 1991;
    console.log(year); // 1991
    console.log(typeof year); // 'number'

    // javascript bug
    console.log(typeof null); // 'object'

    let const var

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    let age = 30;
    age = 31;

    const birthYear = 1991;
    //script.js:51 Uncaught TypeError: Assignment to constant variable.
    // birthYear = 1990;
    //Uncaught SyntaxError: Missing initializer in const declaration
    // const job;

    // let is block scope var is functiong scope
    var job = 'programmer';
    job = 'teacher';

    // not recomment, global scope
    lastName = 'asdf';
    console.log(lastName);

    basic operators

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    const now = 2037
    // const ageJonas = 2037 - 1991;
    const ageJonas = now - 1991;
    // const ageSarah = 2037 - 2018;
    const ageSarah = now - 2018;
    console.log(ageJonas);
    console.log(ageJonas, ageSarah); // 46 19

    console.log(ageJonas * 2, ageJonas / 10, 2 ** 3);
    //2**3 = 2 * 2 * 2

    const firstName = 'Jonas';
    const lastName = 'Schemd';
    console.log(firstName + ' ' + lastName); // Jonas Schemd

    //asignment
    let x = 10 + 5; // 15
    x += 10; // x = x + 10 = 25
    x *= 4 // x = x * 4 = 100
    x++; // x = x + 1
    x--;
    console.log(x); //

    // comparison
    console.log(ageJonas > ageSarah); // true
    console.log(ageJonas >= 18); // true

    const isFullAge = ageJonas >= 18;
    console.log(isFullAge);


    console.log(now - 1991 > now - 2018);

    percedence

    mdn operator precedence

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    const now = 2037;
    const ageJonas = now - 1991;
    const ageSarah = now - 2018;

    console.log(now - 1991 > now - 2018);

    let x, y;
    x = y = 25 - 10 - 5;
    console.log(x, y); // 10 10

    // const averageAge = ageJonas + ageSarah / 2 // 55.5
    const averageAge = (ageJonas + ageSarah) / 2 // 32.5
    console.log(ageJonas, ageSarah);
    console.log(averageAge);

    Coding Challenge #1

    string and template literal

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    const firstName = 'Jonas'
    const job = 'teacher';
    const birthYear = 1991;
    const year = 2037;

    // I'm Jonas, a 46 years old teacher!
    const jonas = "I'm " + firstName + ', a ' + (year - birthYear) + ' years old ' + job + '!';
    console.log(jonas);

    //es6
    const jonasNew = `I'm ${firstName}, a ${year - birthYear} years old ${job}!`;
    console.log(jonasNew);

    console.log(`Just a regular string...`);

    //multiline string
    // String with
    // multiple
    // lines
    console.log('String with \n\
    multiple\n\
    lines');

    console.log(`String
    multiple
    line`);

    if else control structure

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    const age = 15;
    // const age = 19;
    // const isOldEnough = age >= 18;

    // if (isOldEnough) {
    // console.log('Sarah can start driving licese!');
    // }


    if (age >= 18) {
    console.log('Sarah can start driving licese!');
    } else {
    const yearsLeft = 18 - age;
    //Sarah is too young. Wait another 3 years :)
    console.log(`Sarah is too young. Wait another ${yearsLeft} years :)`);
    }

    // const birthYear = 1991;
    const birthYear = 2012;
    let century;
    if (birthYear <= 2000) {
    // let century = 20;
    century = 20;
    } else {
    century = 21;
    }

    // Uncaught ReferenceError: century is not defined
    // console.log(century);

    console.log(century);

    type conversion and coercion

    coercion auto
    conversion manually

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30

    // type coversion
    const inputYear = '1991';
    console.log(inputYear + 18); // '199118'

    console.log(Number(inputYear), inputYear); // 1991 '1991'
    console.log(Number(inputYear) + 18); // 2009

    // NaN not a valid number
    console.log(Number('Jonas')); // NaN
    console.log(typeof NaN); // 'number'

    console.log(String(23), 23); // '23' 23

    // type coercion
    // 'I am 23 years old'
    console.log('I am ' + 23 + ' years old');
    // console.log('I am ' + String(23) + ' years old');

    console.log('23' - '10' - 3); // 10
    // console.log(Number('23') - Number('10') - 3); // 10
    console.log('10' * '2'); // 20
    console.log('10' / '2'); // 5


    let n = '1' + 1; // 11
    n = n - 1;
    console.log(n); // 10

    console.log(2 + 3 + 4 + '5');

    truthy and falsy values

    boolean coercion

    • logical operator
    • logical context: if else statement
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    // 5 falsy values: 0, '', undefined, null, NaN
    // else are truthy values

    console.log(Boolean(0)); // false
    console.log(Boolean(undefined)); // false
    console.log(Boolean('')); // false
    console.log(Boolean('Jonas')); // true
    console.log(Boolean({})); // true
    console.log(Boolean(-1)); // true



    // const money = 0; // you should get a job
    const money = 100; // dont spent it all
    if (money) {
    console.log('dont spent it all');
    } else {
    console.log('you should get a job');
    }

    let height; // height is undefined
    // let height = 0; // height is undefined
    // let height = 100; // height is defined
    if (height) {
    console.log('height is defined');
    } else {
    console.log('height is undefined');
    }

    equal operators

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    const age = 18;

    // no type coercion
    if (age === 18) console.log('You just became an adult!');

    // true
    if ('18' == 18) console.log('You just became an adult!');
    // if (Number('18') == 18) console.log('You just became an adult!');

    // false
    if ('18' === 18) console.log('You just became an adult!');

    // input: 23
    let favourite = prompt("What's your favorite number?");
    console.log(favourite); // '21'
    console.log(typeof favourite); // 'string'

    if (favourite == 23) {
    console.log('23 is an amazing number!');
    }

    if (Number(favourite) === 23) {
    console.log('23 is an amazing number!');
    }

    favourite = Number(favourite);
    if (favourite === 23) {
    console.log('23 is an amazing number!');
    } else if (favourite === 7) {
    console.log('7 is an amazing number!');
    } else {
    console.log('number is not 7 or 23!');
    }

    if (favourite !== 23) console.log('why not 23!');

    boolean logic operators

    and or not

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31

    // const hasDriverLicense = true;
    // const hasGoodVision = true;

    // console.log(hasDriverLicense && hasGoodVision); // true

    const hasDriverLicense = true;
    const hasGoodVision = false;

    console.log(hasDriverLicense && hasGoodVision); // false
    console.log(hasDriverLicense || hasGoodVision); // ture
    console.log(!hasDriverLicense); // false


    // const shouldDrive = hasDriverLicense && hasGoodVision;

    if (hasDriverLicense && hasGoodVision) {
    console.log('sarah is able to drive!');
    } else {
    console.log('someone else should drive...');
    }


    const isTired = true;
    console.log(hasDriverLicense && hasGoodVision && isTired);

    if (hasDriverLicense && hasGoodVision && !isTired) {
    console.log('sarah is able to drive!');
    } else {
    console.log('someone else should drive...');
    }

    switch statement

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40

    const day = 'thursday';

    switch (day) {
    case 'monday': // day === 'monday'
    console.log('plan course structure');
    break;
    case 'tuesday':
    console.log('prepare theory videos');
    break;
    case 'wednesday':
    case 'thursday':
    console.log('write code examples');
    break;
    case 'friday':
    console.log('record videos');
    break;
    case 'saturday':
    case 'sunday':
    console.log('enjoy the weekend');
    break;
    default:
    console.log('not a valid day');
    break;
    }

    if (day === 'monday') {
    console.log('plan course structure');
    } else if (day === 'tuesday') {
    console.log('prepare theory videos');
    } else if (day === 'wednesday' || day === 'thursday') {
    console.log('write code examples');
    } else if (day === 'friday') {
    console.log('record videos');
    } else if (day === 'saturday' || day === 'sunday') {
    console.log('enjoy the weekend');
    } else {
    console.log('not a valid day');
    }

    statement and expression

    expression produce a value

    3 + 4
    1991
    true && false && !false

    statement
    not produce a value
    if else statement

    // error
    console.log(i am ${2037 - 1991} years old ${if(true){console.log('hello');}});

    condition operator (ternary)

    it is an expression
    only one line block of code

    es5 es6+

    use babel to transpile and polyfill code
    coverting back to es5 to ensure browser compatibility for all users

    fundamentas 02

    strict mode

    first line
    'use strict';

    1
    2
    3
    4
    5
    6
    7
    8
    9
    'use strict';

    let hasDriversLicense = false;
    const passTest = true;


    //Uncaught ReferenceError: hasDriverLicense is not defined
    if (passTest) hasDriverLicense = true;
    if (hasDriversLicense) console.log('i can dirve');

    function

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    function logger() {
    console.log('My name is Jonas');
    }

    // calling / running / invoking function
    logger(); // return undefined
    logger();
    logger();

    // parameters
    function fruitProcessor(apples, oranges) {
    // console.log(apples, oranges);
    const juice = `Juice with ${apples} apples and ${oranges} oranges.`;
    return juice;
    }

    //arguments
    const appleJuice = fruitProcessor(5, 0); // Juice with 5 apples and 0 oranges.
    console.log(appleJuice);
    // 5 3
    // Juice with 5 apples and 3 oranges.
    console.log(fruitProcessor(5, 3));

    const appleOrangeJuice = fruitProcessor(2, 4);
    console.log(appleOrangeJuice);

    function declarations vs experssions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // function declaration
    const age1 = calcAge1(1991);
    function calcAge1(birthYeah) {
    // const age = 2037 - birthYeah;
    // return age;
    return 2037 - birthYeah;
    }

    console.log(age1);


    // Uncaught ReferenceError: Cannot access 'calcAge2' before initialization
    // const age2 = calcAge2(1991);

    // function expression
    const calcAge2 = function (birthYeah) {
    return 2037 - birthYeah;
    }

    const age2 = calcAge2(1991);
    console.log(age2);

    arrow functions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28

    const calcAge2 = function (birthYeah) {
    return 2037 - birthYeah;
    }

    // arrow function
    // one param
    // one return expression
    const calcAge3 = birthYeah => 2037 - birthYeah;
    const age3 = calcAge3(1991);
    console.log(age3);

    const yearUntilRetirement = birthYeah => {
    const age = 2037 - birthYeah;
    const retirement = 65 - age;
    return retirement;
    }
    console.log(yearUntilRetirement(1991)); //19

    const yearUntilRetirement1 = (birthYeah, firstName) => {
    const age = 2037 - birthYeah;
    const retirement = 65 - age;
    return `${firstName} retires in ${retirement}`;
    }
    // Jonas retires in 19
    console.log(yearUntilRetirement1(1991, 'Jonas'));
    // Bob retires in 8
    console.log(yearUntilRetirement1(1980, 'Bob'));

    functions calling other functions

    alt text

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    function cutFruitPieces(fruit) {
    return fruit * 4
    }

    function fruitProcessor(apples, oranges) {
    // console.log(apples, oranges);
    const applePieces = cutFruitPieces(apples);
    const orangePieces = cutFruitPieces(oranges);
    const juice = `Juice with ${applePieces} pieces of apples and ${orangePieces} pieces of oranges.`;
    return juice;
    }

    //Juice with 8 pieces of apples and 12 pieces of oranges.
    console.log(fruitProcessor(2, 3));

    function reviewing

    alt text

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    const calcAge = function (birthYeah) {
    return 2037 - birthYeah;
    }

    const yearUntilRetirement = function (birthYeah, firstName) {
    const age = calcAge(birthYeah);
    const retirement = 65 - age;
    if (retirement > 0) {
    return retirement;
    // return statement immediatly finsih the function
    console.log(`${firstName} retires in ${retirement}`);
    } else {
    return -1;
    }


    }

    console.log(yearUntilRetirement(1991, 'Jonas'));
    console.log(yearUntilRetirement(1970, 'Mike'));

    introducing to array data structure

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42

    // const friend1 = 'Michael';
    // const friend2 = 'Steven';
    // const friend3 = 'Peter';

    const friends = ['Michael', 'Steven', 'Peter'];
    console.log(friends);

    const years1 = new Array(1991, 1984, 2008, 2020);
    console.log(years1);

    console.log(friends[0]); // Michael
    console.log(friends[2]); // Peter

    console.log(friends.length); // 3
    console.log(friends[friends.length - 1]); // Peter

    friends[2] = 'Jay';
    console.log(friends); // ['Michael', 'Steven', 'Jay']

    // script.js:201 Uncaught TypeError: Assignment to constant variable.
    // friends = ['Bob', 'Alice'];

    const firstName = 'Jonas';
    const jonas = [firstName, 'Schmed', 2037 - 1991, 'teacher', friends];
    console.log(jonas); // ['Jonas', 'Schmed', 46, 'teacher', Array(3)]

    //exercise

    const calcAge = function (birthYeah) {
    return 2037 - birthYeah;
    }
    const years = [1990, 1967, 2002, 2010, 2018];

    const age1 = calcAge(years[0]);
    console.log(age1);
    console.log(calcAge(years[0]));


    // [47, 70, 19]
    const ages = [calcAge(years[0]), calcAge(years[1]), calcAge(years[years.length - 1])];
    console.log(ages);

    basic array operations(methods)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37

    const friends = ['Michael', 'Steven', 'Peter'];

    //add elements

    const newLength = friends.push('Jay');
    // ['Michael', 'Steven', 'Peter', 'Jay'] 4
    console.log(friends, newLength);

    friends.unshift("John");
    // ['John', 'Michael', 'Steven', 'Peter', 'Jay']
    console.log(friends);

    // remove elements

    const lastFriend = friends.pop();
    //['John', 'Michael', 'Steven', 'Peter'] 'Jay'
    console.log(friends, lastFriend);
    friends.pop();
    // ['John', 'Michael', 'Steven']
    console.log(friends);

    const firstFriend = friends.shift();
    //  ['Michael', 'Steven', 'Peter'] 'John'
    console.log(friends, firstFriend);

    console.log(friends.indexOf('Steven')); // 1
    console.log(friends.indexOf('Bob')); // -1

    // friends.push(23);
    console.log(friends.includes('Steven')); // true
    // === equal
    // console.log(friends.includes("23")); // false

    if (friends.includes('Steven')) {
    console.log('you have a friend called Steven');
    }

    introduce to Objects

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44

    const jonas = {
    firstName: 'Jonas',
    lastName: 'Schmed',
    age: 2037 - 1991,
    job: 'teacher',
    friends: ['Michael', 'Peter', 'Steven']
    }

    // order is not important not matter

    // dot and bracket notation

    console.log(jonas.lastName); // "Schmed"

    // bracket can be any experssion
    console.log(jonas["lastName"]); // "Schmed"
    // bracket can be any experssion
    const nameKey = 'Name';
    console.log(jonas[`first${nameKey}`]); // Jonas
    console.log(jonas['last' + nameKey]); // "Schmed"


    //input 'job'
    const interestedIn = 'job';
    // const interestedIn = prompt('What do you want to know about Jonas? Choose from firstName, lastName, age, job, and friends');
    console.log(interestedIn);
    console.log(jonas[interestedIn]);
    // console.log(jonas.interestedIn); // jonas.interestedIn ===> undefinded

    if (jonas[interestedIn]) {
    console.log(jonas[interestedIn]);
    } else {
    console.log('wrong request');
    }

    // add new property

    jonas.location = 'Portugal';
    jonas['twitter'] = '@jonas';
    console.log(jonas);

    //Jonas has 3 friends, and his best friend is called Michael
    console.log(`${jonas.firstName} has ${jonas.friends.length} friends, and his best friend is called ${jonas.friends[0]}`);

    object methods

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90

    const jonas = {
    firstName: 'Jonas',
    lastName: 'Schmed',
    birthYear: 1991,
    job: 'teacher',
    friends: ['Michael', 'Peter', 'Steven'],
    hasDriverLicense: true,

    calcAge: function (birthYear) {
    return 2037 - birthYear;
    }

    //error
    // function func1(params) {
    //
    // }
    };

    // 46
    console.log(jonas.calcAge(1991));
    console.log(jonas['calcAge'](1991));

    // this key word

    const jonas1 = {
    firstName: 'Jonas',
    lastName: 'Schmed',
    birthYear: 1991,
    job: 'teacher',
    friends: ['Michael', 'Peter', 'Steven'],
    hasDriverLicense: true,

    calcAge: function () {
    // {firstName: 'Jonas', lastName: 'Schmed', birthYear: 1991, job: 'teacher', friends: Array(3), …}
    // console.log(this);
    return 2037 - this.birthYear;
    // not recomment
    // return 2037 - jonas1.birthYear;

    }

    };

    console.log(jonas1.calcAge());



    const jonas2 = {
    firstName: 'Jonas',
    lastName: 'Schmed',
    birthYear: 1991,
    job: 'teacher',
    friends: ['Michael', 'Peter', 'Steven'],
    hasDriverLicense: true,

    calcAge: function () {
    this.age = 2037 - this.birthYear;
    return this.age;
    }

    };

    console.log(jonas2.calcAge());
    console.log(jonas2.age);
    console.log(jonas2.age);

    // challenge
    const jonas3 = {
    firstName: 'Jonas',
    lastName: 'Schmed',
    birthYear: 1991,
    job: 'teacher',
    friends: ['Michael', 'Peter', 'Steven'],
    hasDriverLicense: true,

    // selfIntro: function () {
    // return `${this.firstName} is a ${2037 - this.birthYear}-year old ${this.job}, and he has ${this.hasDriverLicense ? 'a' : 'no'} driver's license`;
    // }
    calcAge: function () {
    this.age = 2037 - this.birthYear;
    return this.age;
    },
    selfIntro: function () {
    return `${this.firstName} is a ${this.calcAge()}-year old ${this.job}, and he has ${this.hasDriverLicense ? 'a' : 'no'} driver's license.`;
    }

    };
    // Jonas is a 46-year old teacher, and he has a driver's license
    console.log(jonas3.selfIntro());

    iteration for loop

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    // console.log('lifting weights repetition 1');
    // console.log('lifting weights repetition 2');
    // console.log('lifting weights repetition 3');
    // console.log('lifting weights repetition 4');
    // console.log('lifting weights repetition 5');
    // console.log('lifting weights repetition 6');

    // lifting weights repetition 1
    // lifting weights repetition 2
    // lifting weights repetition 3
    // lifting weights repetition 4
    // lifting weights repetition 5

    // condition evaluated before each iteration
    // counter update after each iteration
    for (let rep = 1; rep <= 5; rep++) {
    console.log(`lifting weights repetition ${rep}`);
    }

    loop array, break, continue

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    const jonas = [
    'Jonas',
    'Schmed',
    2037 - 1991,
    'teacher',
    ['Michael', 'Peter', 'Steven']
    ];


    //i = 4 ['Michael', 'Peter', 'Steven'] 'object'
    for (let i = 0; i < jonas.length; i++) {
    console.log(jonas[i], typeof jonas[i]);
    }

    const types = [];
    for (let i = 0; i < jonas.length; i++) {
    // types[i] = typeof jonas[i];
    types.push(typeof jonas[i]);
    }
    // ['string', 'string', 'number', 'string', 'object']
    console.log(types);


    const years = [1991, 2007, 1969, 2020];
    const ages = [];

    for (let i = 0; i < years.length; i++) {
    ages.push(2037 - years[i]);
    }
    //[46, 30, 68, 17]
    console.log(ages);


    // continue and break
    // continue: skip this iteration
    // break: finish the whole loop

    console.log('-------all items-------------');
    for (let i = 0; i < jonas.length; i++) {
    console.log(jonas[i], typeof jonas[i]);
    }

    console.log('-------only strings-------------');
    for (let i = 0; i < jonas.length; i++) {
    if (typeof jonas[i] !== 'string') {
    continue;
    }
    console.log(jonas[i], typeof jonas[i]);
    }

    console.log('-------break with number-------------');
    for (let i = 0; i < jonas.length; i++) {
    if (typeof jonas[i] === 'number') {
    break;
    }
    console.log(jonas[i], typeof jonas[i]);
    }

    looping backwards and loops in loops

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41

    const jonas = [
    'Jonas',
    'Schmed',
    2037 - 1991,
    'teacher',
    ['Michael', 'Peter', 'Steven']
    ];

    // loop backwards
    for (let i = jonas.length - 1; i >= 0; i--) {
    console.log(i, jonas[i]);
    }

    // loop in loop

    // ---------starting exercise 1------------
    // Exercise 1 Lifting weight repetition 1
    // Exercise 1 Lifting weight repetition 2
    // Exercise 1 Lifting weight repetition 3
    // Exercise 1 Lifting weight repetition 4
    // Exercise 1 Lifting weight repetition 5
    // ---------starting exercise 2------------
    // Exercise 2 Lifting weight repetition 1
    // Exercise 2 Lifting weight repetition 2
    // Exercise 2 Lifting weight repetition 3
    // Exercise 2 Lifting weight repetition 4
    // Exercise 2 Lifting weight repetition 5
    // ---------starting exercise 3------------
    // Exercise 3 Lifting weight repetition 1
    // Exercise 3 Lifting weight repetition 2
    // Exercise 3 Lifting weight repetition 3
    // Exercise 3 Lifting weight repetition 4
    // Exercise 3 Lifting weight repetition 5

    for (let exercise = 1; exercise < 4; exercise++) {
    console.log(`---------starting exercise ${exercise}------------`);
    for (let rep = 1; rep < 6; rep++) {
    console.log(`Exercise ${exercise} Lifting weight repetition ${rep}`);
    }
    }

    while loop

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

    for (let rep = 1; rep <= 5; rep++) {
    console.log(`lifting weights repetition ${rep}`);
    }

    console.log('----------------');


    // while loop


    let rep = 1;
    while (rep <= 5) {
    console.log(`lifting weights repetition ${rep}`);

    rep++;
    }

    let dice = Math.trunc(Math.random() * 6) + 1;
    // console.log(dice);

    while (dice !== 6) {

    console.log(`You rolled a ${dice}`);
    dice = Math.trunc(Math.random() * 6) + 1;
    if (dice === 6) {
    console.log('dice is 6, loop is about to end...');
    }
    }

    developer skills

    DOM AND EVENT – guess my number

    console.log(document.querySelector('.message')); // element p.message

    console.log(document.querySelector('.message').textContent); // "Start guessing..."

    select and manupulating elements

    document.querySelector('.message').textContent = 'Correct Number!'

    document.querySelector('.guess').value = 10;

    handling event -> event lisener

    (method) Element.addEventListener<keyof ElementEventMap>(type: keyof ElementEventMap, listener: (this: Element, ev: Event) => any, options?: boolean | AddEventListenerOptions | undefined): void (+1 overload)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // addEventListener -> most used one
    document.querySelector('.check').addEventListener('click', function () {
    // console.log(document.querySelector('.guess').value); // ""
    // const guess = document.querySelector('.guess').value;
    // console.log(typeof guess); // 'string'
    // "" --> 0
    const guess = Number(document.querySelector('.guess').value);

    if (!guess) {
    document.querySelector('.message').textContent = 'No number'
    }
    });

    implementing the game logic

    manipulation css styles

    change the html inline css style

    // manupilating css style
    document.querySelector('body').style.backgroundColor = '#60b347';

    document.querySelector('.number').style.width = '30rem';

    the dry principle

    project 2 modal

    1
    2
    const btnsShowModal = document.querySelectorAll('.show-modal');
    console.log(btnsShowModal); // NodeList(3) like array

    css class manupulating

    const modal = document.querySelector('.modal');
    modal.classList.remove("hidden", 'class-name');

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // btnCloseModal.addEventListener('click', () => {
    // modal.classList.add("hidden");
    // overlay.classList.add("hidden");
    // });


    // overlay.addEventListener('click', () => {
    // modal.classList.add("hidden");
    // overlay.classList.add("hidden");
    // });

    const closeModal = function () {
    modal.classList.add("hidden");
    overlay.classList.add("hidden");
    }

    btnCloseModal.addEventListener('click', closeModal);
    overlay.addEventListener('click', closeModal);

    key press event

    global event
    document

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    document.addEventListener('keydown', function (e) {

    // a key was pressed
    // KeyboardEvent {isTrusted: true, key: 'Escape', code: 'Escape', location: 0, ctrlKey: false, …}
    // Escape
    // console.log('a key was pressed', e, e.key);
    if (e.key === 'Escape' && !modal.classList.contains('hidden')) {
    closeModal();
    }
    });

    project 3 pig game

    alt text

    const player1Score = document.getElementById('score--0');

    // set img element attribute src
    dice.src = `dice-${String(currentDice)}.png`;

    document.querySelector(`.player--${currentPlayer}`).classList.toggle("player--active");

    how javascript works

    high level overview of javascript

    javascript is a high level, prototype-based object-oriented, multi-paradigm, interpreted or just-in-time compied, dynamic, single-threaded, garbage-collected programming language with first-class functions and a non-blocking event loop concurrency model.

    high level
    manage computer resources automatically
    garbage-collected

    interpreted or just in time compiled
    javascirpted engine

    multi-paradigm
    paradigm: an approach and mindset of structuring code, which will direct your coding style and technique.

    • procedural
    • objected oriented
    • functional

    prototype-based object oriented

    first-class functions
    functions are simply treated as variables. we can pass them into other functions, return them from functions.

    dynamic type
    no data type when variable definitons.
    data type of variable is automatically changed

    single-threaded
    non-blocking event loop

    concurrency model: the javascript engine handles multiple tasks happpening at the same time.
    event loop: takes long running tasks, executes them in the background, and put them back in the main thread once they are finished.

    javascript engine and runtime

    program that executes javascript code.

    v8 engine
    chrome, nodejs

    call stack
    heap

    alt text

    compilation vs interpretation
    compilation: entire code is coverted into machine code at once, and written to a binary file that can be executed by a computer.
    interpretation: interpreter runs through the source code and executes it line by line.

    just-in-time comilation
    entire code is converted into machine code at once, then executed immediately.

    parse into AST:
    abstract signtax tree

    re-compilate optimization

    js runtime in the browser

    js runtime in the browser

    nodejs runtime

    alt text

    execution contexts and the call stack

    exeution context
    environment in which a piece of javascript is executed. stores all the necessary information for some code to be executed.

    one global execution context(ec)
    default context, created from code that is not inside any function(top level)

    function execution context(ec)
    for each function call, a new execution context is created.

    • varialbe environment
      • let, const and var declarations
      • Functions
      • arguments object
    • scope chain: consists of references to varialbes that are lacated outside of the function
    • this keyword

    !!! arrow functin dont have arguents object, this keyword
    they used the arguemnt object and this keyword from the closest function pareant.

    execution context

    call stack:
    place where execution contexts get stacked on top of each other, to keep track of where we are in the execution.

    alt text

    alt text

    alt text

    alt text

    alt text

    scope and scope chain

    scoping: how programs’s variabes are organized and accessed.
    “where do variables live?” or “where can we access a certain vairalbe, and where not?”

    lexical scoping:
    scoping is controlled by placement of functions and blocks in the code;
    example like: a function write inside another function can have access to variable of the parent function

    scope: space or environment in which a certain variable is declared(variable environment in case of functions scope). there is global scope, function scope, and block scope;

    scope of a variable: region of our code where a certain variable can be accessed

    3 types of scope

    • global scope
    1
    2
    3
    const me = 'Jonas';
    const job = 'teacher';
    const year = 1989;

    outside of any function or block
    variable declared in global scope are accessible everywhere

    • function scope
    1
    2
    3
    4
    5
    6
    7
    function calcAge(birthYear) {
    const now = 2037;
    const age = now - birthYear;
    return age;
    }

    console.log(now) // ReferenceError

    variables are accessible only inside function, Not outside
    also called local scope

    • block scope (ES6)
    1
    2
    3
    4
    5
    6
    7
    // example: if block, for loop block, etc
    if(year >= 1981 && year <= 1986) {
    const millenial = true;
    const food = 'Avocado toast';
    }

    console.log(millenial) // ReferenceError

    variable are accessible only inside block(block scoped)
    however, this only applies to let and const variables!
    functions are also block scoped(only in strict mode)

    scope chain

    alt text

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    const myName = "Jonas";

    function first(){
    const age = 30;

    if (age >= 30) {
    const decade = 3;
    var millenial = true;
    }

    function second(){
    const job = 'teacher';

    console.log(`${myName} is a ${age}-old ${job}`);
    // Jonas is a 30-old teacher
    }

    second();
    }

    first();

    scope chain vs call stack

    alt text

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    const a = 'Jonas';
    first();

    function first() {
    const b = 'Hello!';
    second();

    function second() {
    const c = 'Hi!';
    third();
    }
    }

    function third() {
    const d = 'Hey!';
    console.log(d + c + b + a);
    // ReferenceError
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    function calcAge(birthYear) {
    const age = 2037 - birthYear;
    console.log(firstName); // no errors
    // console.log(lastName); // ReferenceError

    function printAge() {
    let output = `${firstName} You are ${age}, born in ${birthYear}`;
    console.log(output);

    if (birthYear >= 1981 && birthYear <= 1996) {
    var millenial = true;

    // // scope chain shadow: create new variable with the same name as outer scope's variable
    // const firstName = 'Steven'
    // const str1 = `oh, you are a millenial, ${firstName}`;
    // // oh, you are a millenial, Steven
    // console.log(str1);

    // // set the value again, reassigning outer scope's varialbe
    // output = "New output!";

    const str = `oh, you are a millenial, ${firstName}`;
    //oh, you are a millenial, Jonas
    console.log(str); // no error

    function add(a, b) {
    return a + b;
    }
    }
    // // set the value again, reassigning outer scope's varialbe
    // output = "New output!";
    // // "New output!"
    // console.log(output);


    // Uncaught ReferenceError: str is not defined
    // console.log(str);

    // var vairale is function scoped
    console.log(millenial); // no error "true"

    // in strict mode
    // function defined in block is block scoped
    //script.js:80 Uncaught ReferenceError: add is not defined
    // add(2, 3); // error
    }
    // Jonas You are 46, born in 1991
    printAge(); // no error
    return age;
    }

    const firstName = 'Jonas';
    calcAge(1991);
    // Uncaught ReferenceError: age is not defined
    // console.log(age);
    //Uncaught ReferenceError: printAge is not defined
    // printAge();

    variable environment: hoisting

    hoisting:makes some types of variable acessible/usable in the code before they are actually declared.
    “ variables lifted to the top of their scope”.
    before execution, code is scanned for variable declarations, and for each variable, a new property is created in the variable environment object.

    temporal dead zone

    alt text

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    const myName = "Jonas";

    if (myName === 'Jonas') {
    // Uncaught ReferenceError: Cannot access 'job' before initialization
    // console.log(`Jonas is a ${job}`);

    const age = 2037 - 1989;
    console.log(age);
    const job = 'teacher';

    // Uncaught ReferenceError: x is not defined
    // console.log(x);
    }

    • make it easier to avoid and catch erros: accessing variables before declaration is ba d prctice and should be avoided;
    • makes const variables actully work
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    // undefined
    console.log(me);
    // Uncaught ReferenceError: Cannot access 'job' before initialization
    // console.log(job);
    // script.js:137 Uncaught ReferenceError: Cannot access 'year' before initialization
    // console.log(year);

    var me = 'Jonas';
    let job = 'teacher';
    const year = 1991;

    // functions

    // no error
    addDecl(2, 3);
    // ReferenceError: Cannot access 'addExpr1' before initialization
    // addExpr1(2, 3);
    // ReferenceError: Cannot access 'addExpr2' before initialization
    // addExpr2(2, 3);
    // ===> undefined();
    // Uncaught TypeError: addExpr3 is not a function
    // addExpr3(2, 3);
    // Uncaught ReferenceError: Cannot access 'addArrow' before initialization
    // addArrow(2, 3);

    function addDecl(a, b) {
    return a + b;
    }

    const addExpr1 = function (a, b) {
    return a + b;
    };

    let addExpr2 = function (a, b) {
    return a + b;
    };

    var addExpr3 = function (a, b) {
    return a + b;
    };

    const addArrow = (a, b) => a + b;
    1
    2
    3
    4
    5
    6
    7
    var x = 1;
    let y = 2;
    const z = 3;

    console.log(x === window.x); // true
    console.log(x === window.y); // false
    console.log(x === window.z); // false

    this keyword

    this keyword/variable: special variable that is created for every execution context(every funtion). Takes the value of(point to) the “owner” of the function in which the this keyword is used.

    this is NOT static.
    it depends on how the function is called, and its valued is only assigned when the function is acturally called.

    • Method
      object that is calling the method
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const jonas = {
    name: 'Jonas',
    year: 1989,
    calcAge: function(){
    return 2037 - this.year;
    }
    }

    jonas.calcAge(); // 48

    • simple function call
      in strict mode
      undefinded

    • Arrow functions
      this of surrounding function (lexical this)

    • event listener
      DOM element that the handler is attatched to

    • new, call, apply, bind

    this does not point to the function itself, and also NOT the its variable environment

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54

    // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
    console.log(this);

    const calcAge = function (birthYear) {
    console.log(2037 - birthYear);
    console.log(this);
    }

    // undefined
    calcAge(1991);

    const calcAgeArrow = (birthYear) => {
    console.log(2037 - birthYear);
    console.log(this);
    }

    // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
    calcAgeArrow(1991);

    const jonas = {
    year: 1991,
    calcAge: function () {
    console.log(this);
    console.log(2037 - this.year);
    }
    };

    // {year: 1991, calcAge: ƒ}
    // 46
    jonas.calcAge();

    const matida = {
    year: 2017,
    };

    matida.calcAge = jonas.calcAge;
    // {year: 2017, calcAge: ƒ}
    console.log(matida);


    // {year: 2017, calcAge: ƒ}
    // 20
    matida.calcAge();

    const f = jonas.calcAge;
    // ƒ () {
    // console.log(this);
    // console.log(2037 - this.year);
    // }
    console.log(f);
    // script.js:225 Uncaught TypeError: Cannot read properties of undefined
    // f();

    this in regular and arrow fucntions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // dont use arrow function this time

    const jonas = {
    firstName: 'Jonas',
    year: 1991,
    calcAge: function () {
    console.log(this);
    console.log(2037 - this.year);
    },

    greet: () => console.log(`Hey ${this.firstName}`, this)
    };

    // "Hey undefined"
    // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
    jonas.greet();
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48

    // use arrow function this time

    const jonas1 = {
    firstName: 'Jonas',
    year: 1991,
    calcAge: function () {
    console.log(this);
    console.log(2037 - this.year);


    // const isMillenial = function () {
    // console.log(this);
    // console.log(this.year >= 1981 && this.year <= 1996);
    // }
    // undefined
    // Uncaught TypeError: Cannot read properties of undefined (reading 'year')
    // isMillenial();

    // solution 1
    const self = this;
    const isMillenial1 = function () {
    console.log(self);
    console.log(self.year >= 1981 && self.year <= 1996);
    }
    // {firstName: 'Jonas', year: 1991, calcAge: ƒ, greet: ƒ}
    // true
    isMillenial1();

    // solution 2
    const isMillenial2 = () => {
    console.log(this);
    console.log(this.year >= 1981 && this.year <= 1996);
    }
    // {firstName: 'Jonas', year: 1991, calcAge: ƒ, greet: ƒ}
    // true
    isMillenial2();

    },

    greet: () => console.log(`Hey ${this.firstName}`, this)
    };

    // "Hey undefined"
    // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
    jonas1.greet();

    jonas1.calcAge();

    primitives vs object (primitive vs reference types)

    alt text

    alt text

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    let age = 30;
    let oldAge = age;
    age = 31;
    console.log(age); // 31
    console.log(oldAge); // 30

    const me = {
    name: 'Jonas',
    age: 30,
    };

    const friend = me;
    friend.age = 27;
    // {name: 'Jonas', age: 27}
    console.log('Me', me);
    // {name: 'Jonas', age: 27}
    console.log('Friend', friend);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54

    ///////////////// primitive type
    let lastName = 'Williams';
    let oldLastName = lastName;
    lastName = "Davis";
    console.log(lastName); // Davis
    console.log(oldLastName); // Williams


    ///////////// reference type
    const jessica = {
    firstName: 'Jessica',
    lastName: 'Williams',
    age: 27,
    };

    let marriedJessica = jessica;
    marriedJessica.lastName = 'Davis';
    // Before marriage: {firstName: 'Jessica', lastName: 'Davis', age: 27}
    console.log('Before marriage:', jessica);
    // After marriage: {firstName: 'Jessica', lastName: 'Davis', age: 27}
    console.log('After marriage:', marriedJessica);

    // marriedJessica = {};

    ///////////// copying objects



    const jessica2 = {
    firstName: 'Jessica',
    lastName: 'Williams',
    age: 27,
    family: ['Alice', 'Bob']
    };

    const jessicaCopy = Object.assign({}, jessica2);

    jessicaCopy.lastName = 'Davis';

    // Before marriage: {firstName: 'Jessica', lastName: 'Williams', age: 27}
    console.log('Before marriage:', jessica2);
    // After marriage: {firstName: 'Jessica', lastName: 'Davis', age: 27}
    console.log('After marriage:', jessicaCopy);


    /////////// shalow copy
    jessicaCopy.family.push('Mary');
    jessicaCopy.family.push('John');

    // Before marriage: {firstName: 'Jessica', lastName: 'Williams', age: 27, family: Array(4)}
    console.log('Before marriage:', jessica2);
    // Before marriage: {firstName: 'Jessica', lastName: 'Williams', age: 27, family: Array(4)}
    console.log('After marriage:', jessicaCopy);

    data structures, strings

    destructuring array

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42

    const arr = [2, 3, 4];
    const a = arr[0];
    const b = arr[1];
    const c = arr[2];

    const [x, y, z] = arr;
    console.log(x); // 2
    console.log(y); // 3
    console.log(z); // 4
    console.log(arr); // [2, 3, 4]


    const restaurant = {
    name: 'Classico Italiano',
    location: 'Via Angelo Tavanti 23, Firenze, Italy',
    categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
    starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
    mainMenu: ['Pizza', 'Pasta', 'Risotto'],
    order: function (starterIndex, mainIndex) {
    return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
    }
    };
    const [first, second] = restaurant.categories;
    console.log(first); // Italian
    console.log(second); // Pizzeria

    let [main, , secondary] = restaurant.categories;
    console.log(main); // Italian
    console.log(secondary); // Vegetarian

    ////// swicth values

    // const temp = main;
    // main = secondary;
    // secondary = temp;
    // console.log(main); // Vegetarian
    // console.log(secondary); // Italian

    console.log(main, secondary);
    [main, secondary] = [secondary, main];
    console.log(main, secondary);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // receive 2 return values from a function
    const restaurant1 = {
    name: 'Classico Italiano',
    location: 'Via Angelo Tavanti 23, Firenze, Italy',
    categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
    starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
    mainMenu: ['Pizza', 'Pasta', 'Risotto'],
    order: function (starterIndex, mainIndex) {
    return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
    }
    };

    //  ['Garlic Bread', 'Pizza']
    // console.log(restaurant.order(2, 0));
    const [starter, mainCourse] = restaurant1.order(2, 0);
    console.log(starter, mainCourse); // Garlic Bread Pizza
    1
    2
    3
    4
    5
    6
    7
    8
    // nested destructuring
    const nested = [2, 4, [5, 6]];

    const [firstN, , nestedArray] = nested;
    console.log(firstN, nestedArray); // 2 [5, 6]

    const [i, , [j, k]] = nested;
    console.log(i, j, k); // 2 5 6
    1
    2
    3
    4
    5
    6
    // Default values
    const [p, q, r] = [8, 9];
    console.log(p, q, r); // 8 9 undefined

    const [l, m, n = 1] = [8, 9];
    console.log(l, m, n); // 8 9 1

    destructuring object

    get data from api

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    const restaurant = {
    name: 'Classico Italiano',
    location: 'Via Angelo Tavanti 23, Firenze, Italy',
    categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
    starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
    mainMenu: ['Pizza', 'Pasta', 'Risotto'],

    openingHours: {
    thu: {
    open: 12,
    close: 22,
    },
    fri: {
    open: 11,
    close: 23,
    },
    sat: {
    open: 0, // Open 24 hours
    close: 24,
    },
    },
    order: function (starterIndex, mainIndex) {
    return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
    },
    orderDelivery: function (obj) {
    console.log(obj);
    },
    orderDelivery1: function ({ starterIndex = 1, mainIndex = 0, time = '20:00', address }) {
    console.log(starterIndex, mainIndex, time, address);
    console.log(`Order received! ${this.starterMenu[starterIndex]} and ${this.mainMenu[mainIndex]} will be delivered to ${address} at ${time}`);
    },
    };

    restaurant.orderDelivery({
    time: '22:30',
    address: 'via del sole, 21',
    mainIndex: 2,
    starterIndex: 2,
    })

    // 2 2 '22:30' 'via del sole, 21'
    // Order received! Garlic Bread and Risotto will be delivered to via del sole, 21 at 22:30
    restaurant.orderDelivery1({
    time: '22:30',
    address: 'via del sole, 21',
    mainIndex: 2,
    starterIndex: 2,
    })

    // 2 2 '22:30' 'via del sole, 21'
    // Order received! Garlic Bread and Risotto will be delivered to via del sole, 21 at 22:30
    restaurant.orderDelivery1({
    time: '22:30',
    address: 'via del sole, 21',
    mainIndex: 2,
    starterIndex: 2,
    })

    // 1 0 '20:00' 'via del ssdole, 21'
    // Order received! Bruschetta and Pizza will be delivered to via del ssdole, 21 at 20:00
    restaurant.orderDelivery1({
    address: 'via del ssdole, 21',
    starterIndex: 1,
    })
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102

    const restaurant = {
    name: 'Classico Italiano',
    location: 'Via Angelo Tavanti 23, Firenze, Italy',
    categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
    starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
    mainMenu: ['Pizza', 'Pasta', 'Risotto'],

    openingHours: {
    thu: {
    open: 12,
    close: 22,
    },
    fri: {
    open: 11,
    close: 23,
    },
    sat: {
    open: 0, // Open 24 hours
    close: 24,
    },
    },
    order: function (starterIndex, mainIndex) {
    return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
    },
    orderDelivery: function (obj) {
    console.log(obj);
    },
    orderDelivery1: function ({ starterIndex = 1, mainIndex = 0, time = "20:00", address }) {
    console.log(starterIndex, mainIndex, time, address);
    console.log(`Order received! ${this.starterMenu[starterIndex]} and ${this.mainMenu[mainIndex]} will be delivered to ${address} at ${time}`);
    },
    };

    restaurant.orderDelivery({
    time: '22:30',
    address: 'via del sole, 21',
    mainIndex: 2,
    starterIndex: 2,
    })

    // 2 2 '22:30' 'via del sole, 21'
    // Order received! Garlic Bread and Risotto will be delivered to via del sole, 21 at 22:30
    restaurant.orderDelivery1({
    time: '22:30',
    address: 'via del sole, 21',
    mainIndex: 2,
    starterIndex: 2,
    })


    // 1 0 '20:00' 'via del ssdole, 21'
    // Order received! Bruschetta and Pizza will be delivered to via del ssdole, 21 at 20:00
    restaurant.orderDelivery1({
    address: 'via del ssdole, 21',
    starterIndex: 1,
    })

    const { name, openingHours, categories } = restaurant;

    // Classico Italiano
    // {thu: {…}, fri: {…}, sat: {…}}
    // (4) ['Italian', 'Pizzeria', 'Vegetarian', 'Organic']
    console.log(name, openingHours, categories);


    const { name: restaurantName, openingHours: hours, categories: tags } = restaurant;
    // // Classico Italiano
    // {thu: {…}, fri: {…}, sat: {…}}
    // (4) ['Italian', 'Pizzeria', 'Vegetarian', 'Organic']
    console.log(restaurantName, hours, tags);

    // default values
    const { menu = [], starterMenu: starters = [] } = restaurant;
    // []
    // (4) ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad']
    console.log(menu, starters);

    // mutating variables

    let a = 111;
    let b = 999;
    const obj = { a: 23, b: 7, c: 14 };
    // Uncaught SyntaxError: Unexpected token '='
    // { a, b } = obj;

    ({ a, b } = obj);
    // 23 7
    console.log(a, b);


    // nested objects
    const { fri } = openingHours;
    // {open: 11, close: 23}
    console.log(fri);

    const { fri: { open, close } } = openingHours;
    console.log(open, close); // 11 23

    const { fri: { open: o, close: c } } = openingHours;
    console.log(o, c); // 11 23

    spread operator

    right side of asignment operator

    get all the values spreadly

    used only when
    in array
    function arguments

    works on all iterables
    arrays stirng maps, sets, NOT objects

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90

    const arr = [7, 8, 9];
    const badNewArr = [1, 2, arr[0], arr[1], arr[2]];
    console.log(badNewArr);

    const newArr = [1, 2, ...arr];
    // [1, 2, 7, 8, 9]
    console.log(newArr);

    // 1 2 7 8 9
    console.log(...newArr);


    const restaurant = {
    name: 'Classico Italiano',
    location: 'Via Angelo Tavanti 23, Firenze, Italy',
    categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
    starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
    mainMenu: ['Pizza', 'Pasta', 'Risotto'],

    openingHours: {
    thu: {
    open: 12,
    close: 22,
    },
    fri: {
    open: 11,
    close: 23,
    },
    sat: {
    open: 0, // Open 24 hours
    close: 24,
    },
    },
    order: function (starterIndex, mainIndex) {
    return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
    },
    orderDelivery: function ({ starterIndex = 1, mainIndex = 0, time = "20:00", address }) {
    console.log(starterIndex, mainIndex, time, address);
    console.log(`Order received! ${this.starterMenu[starterIndex]} and ${this.mainMenu[mainIndex]} will be delivered to ${address} at ${time}`);
    },
    orderPasta: function (ing1, ing2, ing3) {
    console.log(ing1, ing2, ing3);
    console.log(`Here is your delicious pasta with ${ing1}, ${ing2}, ${ing3}`);
    },
    };


    // ['Pizza', 'Pasta', 'Risotto', 'Gnocci']
    const newMenu = [...restaurant.mainMenu, 'Gnocci'];
    console.log(newMenu);

    // copy array(shallow)

    const mianMenuCopy = [...restaurant.mainMenu];

    // join 2 arrays

    const menu = [...restaurant.mainMenu, ...restaurant.starterMenu]
    // ['Pizza', 'Pasta', 'Risotto', 'Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad']
    console.log(menu);

    const str = 'Jonas';
    const letters = [...str, ' ', 'S.'];
    // ['J', 'o', 'n', 'a', 's', ' ', 'S.']
    console.log(letters);

    //
    // const ingredients = [prompt('Let\'s make pasta! Ingredient 1?'), prompt('Let\'s make pasta! Ingredient 2?'), prompt('Let\'s make pasta! Ingredient 3?')]
    const ingredients = ['q', 'q', 'q'];
    console.log(ingredients);

    // Here is your delicious pasta with q, q, q
    restaurant.orderPasta(...ingredients);

    // Object

    const newRestaurant = { ...restaurant, founder: 'Guiseppe' };
    // {name: 'Classico Italiano', location: 'Via Angelo Tavanti 23, Firenze, Italy', categories: Array(4), starterMenu: Array(4), mainMenu: Array(3), …}
    console.log(newRestaurant);


    // shalow copy
    const restaurantCoy = { ...restaurant };
    // Classico Italiano
    console.log(restaurant.name);
    restaurantCoy.name = 'Ristorant roma';
    // Classico Italiano
    console.log(restaurant.name);

    rest pattern

    left side of asignment operator

    collect rest elemnets

    always in the last place and only one

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97

    //// array

    const arr = [1, 2, ...[3, 4]];
    // [1, 2, 3, 4]
    console.log(arr);

    const [a, b, ...others] = [1, 2, 3, 4, 5];
    // 1 2 [3, 4, 5]
    console.log(a, b, others);


    const restaurant = {
    name: 'Classico Italiano',
    location: 'Via Angelo Tavanti 23, Firenze, Italy',
    categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
    starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
    mainMenu: ['Pizza', 'Pasta', 'Risotto'],

    openingHours: {
    thu: {
    open: 12,
    close: 22,
    },
    fri: {
    open: 11,
    close: 23,
    },
    sat: {
    open: 0, // Open 24 hours
    close: 24,
    },
    },
    order: function (starterIndex, mainIndex) {
    return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
    },
    orderDelivery: function ({ starterIndex = 1, mainIndex = 0, time = "20:00", address }) {
    console.log(starterIndex, mainIndex, time, address);
    console.log(`Order received! ${this.starterMenu[starterIndex]} and ${this.mainMenu[mainIndex]} will be delivered to ${address} at ${time}`);
    },
    orderPasta: function (ing1, ing2, ing3) {
    console.log(ing1, ing2, ing3);
    console.log(`Here is your delicious pasta with ${ing1}, ${ing2}, ${ing3}`);
    },
    orderPizza: function (mianIngredient, ...otherIngredients) {
    console.log(mianIngredient, otherIngredients);
    }
    };


    const [pizza, , risotto, ...otherFood] = [...restaurant.mainMenu, ...restaurant.starterMenu];
    // Pizza
    // Risotto
    // ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad']
    console.log(pizza, risotto, otherFood);

    // objects

    const { sat, ...weekdays } = restaurant.openingHours;
    // {thu: {…}, fri: {…}}
    console.log(weekdays);

    ///// function

    const add = function (...numbers) {
    console.log(numbers);
    let sum = 0;
    for (let i = 0; i < numbers.length; i++) {
    sum += numbers[i];
    }
    console.log(sum);
    }

    // [2, 3]
    //5
    add(2, 3);
    // [5, 3, 7, 4]
    // 19
    add(5, 3, 7, 4);
    /// [5, 3, 7, 4, 2, 3, 1]
    // 35
    add(5, 3, 7, 4, 2, 3, 1);


    const x = [23, 5, 7];

    // [23, 5, 7]
    // 35
    add(...x);


    // mushrooms
    // ['onion', 'olives', 'spinach']
    restaurant.orderPizza('mushrooms', 'onion', 'olives', 'spinach');
    // mushrooms
    // []
    restaurant.orderPizza('mushrooms');

    short circuiting

    ||
    if the first value is a turthy value, it will imediately return the first value

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71

    // 3
    console.log(3 || 'jonas'); // 3
    console.log('' || 'jonas'); // jonas
    console.log(true || 0); // true
    console.log(undefined || null); // null
    // Hello
    console.log(undefined || 0 || '' || 'Hello' || 23 || null);


    const restaurant = {
    name: 'Classico Italiano',
    location: 'Via Angelo Tavanti 23, Firenze, Italy',
    categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
    starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
    mainMenu: ['Pizza', 'Pasta', 'Risotto'],

    openingHours: {
    thu: {
    open: 12,
    close: 22,
    },
    fri: {
    open: 11,
    close: 23,
    },
    sat: {
    open: 0, // Open 24 hours
    close: 24,
    },
    },
    order: function (starterIndex, mainIndex) {
    return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
    },
    orderDelivery: function ({ starterIndex = 1, mainIndex = 0, time = "20:00", address }) {
    console.log(starterIndex, mainIndex, time, address);
    console.log(`Order received! ${this.starterMenu[starterIndex]} and ${this.mainMenu[mainIndex]} will be delivered to ${address} at ${time}`);
    },
    orderPasta: function (ing1, ing2, ing3) {
    console.log(ing1, ing2, ing3);
    console.log(`Here is your delicious pasta with ${ing1}, ${ing2}, ${ing3}`);
    },
    orderPizza: function (mianIngredient, ...otherIngredients) {
    console.log(mianIngredient, otherIngredients);
    }
    };

    const guests1 = restaurant.numGuests ? restaurant.numGuests : 10;
    console.log(guests1); // 10

    const guests2 = restaurant.numGuests || 10;
    console.log(guests2); // 10

    restaurant.numGuests = 23;
    const guests3 = restaurant.numGuests || 10;
    console.log(guests3); // 23

    ////////////////

    //////// AND

    console.log(0 && 'Jonas'); // 0
    console.log(7 && 'Jonas'); // Jonas
    console.log('Hello' && 23 && null && 'jonas'); // null

    if (restaurant.orderPizza) {
    restaurant.orderPizza('mushrooms', 'spinach');
    }

    restaurant.orderPizza && restaurant.orderPizza('mushrooms', 'spinach');

    nullish coalescing oparator

    1
    2
    3
    4
    5
    6
    7
    // if restaurant.numGuests = 0
    const guests2 = restaurant.numGuests || 10;
    console.log(guests2); // 10

    // nullish: nul and undefined (NOT or '')
    const guestsCorrect = restaurant.numGuests ?? 10;
    console.log(guestsCorrect);

    logical assignment operators(es2021)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37


    const rest1 = {
    name: 'Capri',
    numGuests: 20,
    // numGuests: 0,
    };
    const rest2 = {
    name: 'La Piazza',
    owner: 'Giavanni Rossi',
    };

    // rest2.numGuests = rest2.numGuests || 10;
    // rest1.numGuests = rest1.numGuests || 10;
    // console.log(rest1, rest2);

    // rest1.numGuests ||= 10;
    // rest2.numGuests ||= 10;
    // console.log(rest1, rest2);


    // {name: 'Capri', numGuests: 20}
    // {name: 'La Piazza', owner: 'Giavanni Rossi', numGuests: 10}
    rest1.numGuests ??= 10;
    rest2.numGuests ??= 10;
    console.log(rest1, rest2);

    // {name: 'Capri', numGuests: 20, owner: undefined}
    // {name: 'La Piazza', owner: '<Anon>', numGuests: 10}
    //
    rest1.owner = rest1.owner && '<Anon>'
    rest2.owner = rest2.owner && '<Anon>'
    console.log(rest1, rest2);

    rest1.owner &&= '<Anon>'
    rest2.owner &&= '<Anon>'
    console.log(rest1, rest2);

    for of loop

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46

    const restaurant = {
    name: 'Classico Italiano',
    location: 'Via Angelo Tavanti 23, Firenze, Italy',
    categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
    starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
    mainMenu: ['Pizza', 'Pasta', 'Risotto'],

    };

    const menu = [...restaurant.starterMenu, ...restaurant.mainMenu];
    console.log(menu);


    // Focaccia
    // Bruschetta
    // Garlic Bread
    // Caprese Salad
    // Pizza
    // Pasta
    // Risotto
    for (const item of menu) {
    console.log(item);
    }
    // can use break and continue


    // Array Iterator {}
    console.log(menu.entries());


    for (const item of menu.entries()) {
    // [0, 'Focaccia']
    console.log(item);
    // '1: Focaccia'
    console.log(`${item[0] + 1}: ${item[1]}`);

    }


    for (const [i, e] of menu.entries()) {

    // '1: Focaccia'
    console.log(`${i + 1}: ${e}`);

    }

    enhanced object literals

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    const weekdays = ['mon', 'tue', 'wen', 'thu', 'fri', 'sat', 'sun'];

    const openingHours = {
    thu: {
    open: 12,
    close: 22,
    },
    // fri:
    [weekdays[4]]: {
    open: 11,
    close: 23,
    },
    // day-6:
    [`day-${2 + 4}`]: {
    open: 0, // Open 24 hours
    close: 24,
    },
    };
    const restaurant = {
    name: 'Classico Italiano',
    location: 'Via Angelo Tavanti 23, Firenze, Italy',
    categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
    starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
    mainMenu: ['Pizza', 'Pasta', 'Risotto'],

    // openingHours: openingHours,
    // es6 enhanced object literals
    openingHours,

    // order: function (starterIndex, mainIndex) {
    // return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
    // },

    // es6 new syntax
    order(starterIndex, mainIndex) {
    return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
    },
    }

    optinal chaining (?.)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103

    const weekdays = ['mon', 'tue', 'wen', 'thu', 'fri', 'sat', 'sun'];

    const openingHours = {
    thu: {
    open: 12,
    close: 22,
    },
    // fri:
    [weekdays[4]]: {
    open: 11,
    close: 23,
    },
    // day-6:
    [`day-${2 + 4}`]: {
    open: 0, // Open 24 hours
    close: 24,
    },
    sat: {
    open: 0, // Open 24 hours
    close: 24,
    },
    };

    const restaurant = {
    name: 'Classico Italiano',
    location: 'Via Angelo Tavanti 23, Firenze, Italy',
    categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
    starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
    mainMenu: ['Pizza', 'Pasta', 'Risotto'],

    // openingHours: openingHours,
    // es6 enhanced object literals
    openingHours,

    // order: function (starterIndex, mainIndex) {
    // return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
    // },

    // es6 new syntax
    order(starterIndex, mainIndex) {
    return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
    },

    };


    // undefined
    console.log(restaurant.openingHours.mon);
    // script.js:725 Uncaught TypeError: Cannot read properties of undefined (reading 'open')
    // console.log(restaurant.openingHours.mon.open);
    // undefined
    if (restaurant.openingHours && restaurant.openingHours.mon) console.log(restaurant.openingHours.mon.open);

    // with optional chaining

    // if (restaurant.openingHours.mon) console.log(restaurant.openingHours.mon.open);
    console.log(restaurant.openingHours.mon?.open);

    // if (restaurant.openingHours && restaurant.openingHours.mon) console.log(restaurant.openingHours.mon.open);
    console.log(restaurant.openingHours?.mon?.open);


    const days = ['mon', 'tue', 'wen', 'thu', 'fri', 'sat', 'sun'];


    // On mon, we open at closed
    // On tue, we open at closed
    // On wen, we open at closed
    // On thu, we open at 12
    // On fri, we open at 11
    // On sat, we open at 0
    // On sun, we open at closed
    for (const day of days) {
    // console.log(day);
    const open = (restaurant.openingHours[day]?.open) ?? 'closed';
    console.log(`On ${day}, we open at ${open}`);
    }

    ///// on methods
    //  ['Focaccia', 'Pasta']
    console.log(restaurant.order?.(0, 1) ?? 'Method does not exist');
    // Method does not exist
    console.log(restaurant.orderRisotto?.(0, 1) ?? 'Method does not exist');


    ///// on arrays (empty)

    const users = [
    {
    name: 'Jonas',
    email: 'hello@jonas.com',
    }
    ];


    // if(users.length > 0) console.log(users[0].name);
    // else console.log('User array empty');
    // Jonas
    console.log(users[0]?.name ?? 'User array empty');

    // User array empty
    console.log(users[1]?.name ?? 'User array empty');

    loop object key value entries

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74

    const openingHours = {
    thu: {
    open: 12,
    close: 22,
    },
    // fri:
    fri: {
    open: 11,
    close: 23,
    },
    // day-6:
    [`day-${2 + 4}`]: {
    open: 0, // Open 24 hours
    close: 24,
    },
    sat: {
    open: 0, // Open 24 hours
    close: 24,
    },
    };

    ////////// property name

    //  ['thu', 'fri', 'day-6', 'sat']
    console.log(Object.keys(openingHours));

    let openStr = `We are open on ${Object.keys(openingHours).length} days: `;
    // thu
    // fri
    // day-6
    // sat
    for (const day of Object.keys(openingHours)) {
    // console.log(day);
    openStr += `${day},`;
    }

    // We are open on 4 days: thu,fri,day-6,sat,
    console.log(openStr);

    ////// properties value

    // [{…}, {…}, {…}, {…}]
    // 0: {open: 12, close: 22}
    // 1: {open: 11, close: 23}
    // 2: {open: 0, close: 24}
    // 3: {open: 0, close: 24}
    const values = Object.values(openingHours);
    console.log(values);


    /////// objec enties

    // [Array(2), Array(2), Array(2), Array(2)]
    // 0: (2) ['thu', {…}]
    // 1: (2) ['fri', {…}]
    // 2: (2) ['day-6', {…}]
    // 3: (2) ['sat', {…}]
    const entries = Object.entries(openingHours);
    console.log(entries);

    for (const [key, value] of Object.entries(openingHours)) {
    // console.log(key, value);

    //On thu we open at 12 and close at 22
    console.log(`On ${key} we open at ${value?.open} and close at ${value?.close}`);
    }

    for (const [key, { open, close }] of Object.entries(openingHours)) {
    // console.log(key, value);

    //On thu we open at 12 and close at 22
    console.log(`On ${key} we open at ${open} and close at ${close}`);
    }

    sets (unique elements)

    order of sets is irrelevant
    no way to get only one element from a set

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56

    const ordersSet = new Set([
    'Pasta',
    'Pizza',
    'Pizza',
    'Risotto',
    'Pasta',
    'Pizza',
    ]);


    // Set(3) {'Pasta', 'Pizza', 'Risotto'}
    console.log(ordersSet);
    // Set(5) {'J', 'o', 'n', 'a', 's'}
    console.log(new Set("Jonas"));

    console.log(ordersSet.size); // 3

    console.log(ordersSet.has('Pizza')); // true
    console.log(ordersSet.has('Bread')); // false


    ordersSet.add('Garlic Bread');
    ordersSet.add('Garlic Bread');
    // Set(4) {'Pasta', 'Pizza', 'Risotto', 'Garlic Bread'}
    console.log(ordersSet);

    ordersSet.delete('Garlic Bread')
    // Set(3) {'Pasta', 'Pizza', 'Risotto'}
    console.log(ordersSet);

    // ordersSet.clear();
    // // Set(0) {size: 0}
    // console.log(ordersSet);


    // Pasta
    // Pizza
    // Risotto
    for (const order of ordersSet) {
    console.log(order);
    }

    ///example

    const staff = ['Waiter', 'Chef', 'Waiter', 'Manager', 'Chef', 'Waiter'];
    const staffUnique = new Set(staff);
    console.log(staffUnique);

    const staffUniqueArr = [...new Set(staff)]
    // ['Waiter', 'Chef', 'Manager']
    console.log(staffUniqueArr);

    // 3
    console.log(new Set(['Waiter', 'Chef', 'Waiter', 'Manager', 'Chef', 'Waiter']).size);

    maps

    key can be any type of data

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    const rest = new Map();
    rest.set('name', 'Classic italinano');
    rest.set(1, 'Firenze, Italy');
    rest.set(2, 'Firenze, Italy');
    // Map(3) {'name' => 'Classic italinano', 1 => 'Firenze, Italy', 2 => 'Firenze, Italy'}
    console.log(rest);

    rest
    .set('categories', ['Italian', 'Piszzeria', 'Vegetarian', 'Organic'])
    .set('open', 11)
    .set('close', 23).
    set(true, 'We are open!')
    .set(false, 'We are closed');
    // Map(5) {'name' => 'Classic italinano', 1 => 'Firenze, Italy', 2 => 'Firenze, Italy', 'categories' => Array(4), 'open' => 11, ...}
    console.log(rest);

    console.log(rest.get('name')); // Classic italinano
    console.log(rest.get(1)); // Firenze, Italy

    const time = 21;
    // We are open!
    console.log(rest.get(time > rest.get('open') && time < rest.get('close')));

    console.log(rest.has('categories'));
    rest.delete(2)
    console.log(rest);
    console.log(rest.size); // 7
    rest.clear();

    ////// array as key
    rest.set([1, 2], 'TEST');
    // Map(1) {Array(2) => 'TEST'}
    console.log(rest);

    // not the same array [1, 2]
    // undefined
    console.log(rest.get([1, 2]));

    const arr = [1, 2]
    rest.set(arr, 'TEST');
    // Map(1) {Array(2) => 'TEST'}
    console.log(rest);

    // TEST
    console.log(rest.get(arr));


    //// object as key
    rest.set(document.querySelector('h1'), 'Heading')
    console.log(rest);

    maps: iteration

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    const question = new Map([
    ['question', 'Waht is the best programmong language in the world?'],
    [1, 'C'],
    [2, 'java'],
    [3, 'javascritp'],
    ['correct', 3],
    [true, 'you are Correct!'],
    [false, 'Try again'],
    ]);
    // Map(7) {'question' => 'Waht is the best programmong language in the world?', 1 => 'C', 2 => 'java', 3 => 'javascritp', 'correct' => 3, …}
    console.log(question);


    const openingHours = {
    thu: {
    open: 12,
    close: 22,
    },
    // fri:
    fri: {
    open: 11,
    close: 23,
    },
    // day-6:
    [`day-${2 + 4}`]: {
    open: 0, // Open 24 hours
    close: 24,
    },
    sat: {
    open: 0, // Open 24 hours
    close: 24,
    },
    };

    // (4) [Array(2), Array(2), Array(2), Array(2)]
    // 0: (2) ['thu', {…}]
    // 1: (2) ['fri', {…}]
    // 2: (2) ['day-6', {…}]
    // 3: (2) ['sat', {…}]
    console.log(Object.entries(openingHours));

    // covert object ot map

    const hoursMap = new Map(Object.entries(openingHours));
    // Map(4) {'thu' => {…}, 'fri' => {…}, 'day-6' => {…}, 'sat' => {…}}
    console.log(hoursMap);

    // Answer 1: C
    // Answer 2: java
    // Answer 3: javascritp
    for (const [key, value] of question) {
    if (typeof key === 'number') {
    console.log(`Answer ${key}: ${value}`);
    }
    }

    // input '3'
    const answer = 1;
    // const answer = Number(prompt('Your answer: '));
    console.log(answer);

    // you are Correct!
    console.log(question.get(answer === question.get('correct')));

    ////////convert map to an arrary

    // [
    // ['question', 'Waht is the best programmong language in the world?'],
    // [1, 'C'],
    // [2, 'java'],
    // [3, 'javascritp'],
    // ['correct', 3],
    // [true, 'you are Correct!'],
    // [false, 'Try again'],
    // ]
    console.log('...question', [...question]);
    // MapIterator {'question', 1, 2, 3, 'correct', …}
    console.log(question.keys());
    // MapIterator {'Waht is the best programmong language in the world?', 'C', 'java', 'javascritp', 3, …}
    console.log(question.values());
    // MapIterator {'question' => 'Waht is the best programmong language in the world?', 1 => 'C', 2 => 'java', 3 => 'javascritp', 'correct' => 3, …}
    console.log(question.entries());

    which data structure to use

    sources of data

    1. from the program iteself: data written directly in source code (e.g. status messages)
    2. from the ui: data input from the user or data written in DOM(e.g. tasks in todo app)
    3. From external sources: data fetched for example from web api(e.g. rcipe objects)

    simple list
    key/value pairs: key allow us to describe values

    array <> sets
    array:

    • use when you need ordered list of values(might contain duplicates)
    • use when you need to manipulate data

    sets

    • use when you need to work with unique values
    • use when high-performance is really important
    • use to remove duplicates form arrays

    objects

    • more ‘traditonal’ key/value store (‘abused’ object)

    • easier to write and access value with . and []

    • use when you need to include functions(methods)

    • use when working with json (can convert to map)

    maps

    • better performance

    • keys can have any data type

    • easy to iterate

    • easy to compute size

    • use when you simply need to map key to values

    • use whe you need keys that are not strings

    String methods

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44


    const airline = 'TAP Air Portugal';
    const plane = 'A320';

    console.log(plane[0]); // 'A'
    console.log(plane[1]); // '3'
    console.log(plane[2]); // '2'
    console.log('B737'[1]); // '7'

    console.log(airline.length); // 16
    console.log('airline'.length); // 7

    // first occurance
    console.log(airline.indexOf('r')); // 6
    console.log(airline.indexOf('Portugal')); // 8
    console.log(airline.indexOf('portugal')); // -1
    // last occurance
    console.log(airline.lastIndexOf('r')); // 10

    console.log(airline.slice(4)); // Air Portugal
    console.log(airline.slice(4, 7)); // 'Air'
    console.log(airline); // 'TAP Air Portugal'

    console.log(airline.slice(0, airline.indexOf(' '))); // 'TAP'
    console.log(airline.slice(airline.lastIndexOf(' ') + 1)); // 'Portugal'
    console.log(airline.slice(-2)); // al
    console.log(airline.slice(1, -1)); // AP Air Portuga

    // B AND E are middle seats
    const checkMiddleSeat = function (seat) {
    const s = seat.slice(-1);
    if (s === 'B' || s === 'E') {
    console.log('you got the middle seat');
    } else {
    console.log('YOu got lucky');
    }
    }
    // you got the middle seat
    checkMiddleSeat('11B')
    // YOu got lucky
    checkMiddleSeat('23C')
    // you got the middle seat
    checkMiddleSeat('3E')
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67


    const airline = 'TAP Air Portugal';


    console.log(airline.toLowerCase()); // tap air portugal
    console.log(airline.toUpperCase()); // TAP AIR PORTUGAL

    // fix capitalization in name
    const passenger = 'jOnAS';
    const passengerLower = passenger.toLowerCase();
    const passengerCorrect = passengerLower[0].toUpperCase() + passengerLower.slice(1);
    console.log(passengerCorrect); // Jonas

    // comparing email
    const email = 'hello@jonas.io';
    const loginEmail = ' Hello@Jonas.Io \n';

    // const trimEmail = loginEmail.trim();
    // console.log(trimEmail); // 'Hello@Jonas.Io'
    // const lowerEmail = trimEmail.toLowerCase();

    const normalizedEmail = loginEmail.trim().toLowerCase();
    console.log(normalizedEmail); // 'hello@jonas.io'

    // replacing

    const priceGB = '288,97¥';
    const priceUs = priceGB.replace('¥', '$').replace(',', '.');
    console.log(priceUs); // 288.97$

    const announcement = 'All passengers come to barding door 23, Bording door 23!'
    // just the first occurance
    // All passengers come to barding gate 23, Bording door 23!
    console.log(announcement.replace('door', 'gate'));

    // regex global flag
    // All passengers come to barding gate 23, Bording gate 23!
    console.log(announcement.replace(/door/g, 'gate'));

    // return BOOLEAN value

    const plane = 'Airbus A320neo';
    console.log(plane.includes('A320')); // true
    console.log(plane.includes('Boeing')); // false
    console.log(plane.startsWith('Airbus')); // true

    if (plane.startsWith('Airbus') && plane.endsWith('neo')) {
    console.log('Part of the new airbus family');
    }

    /// exercise

    const checkBaggage = function (items) {
    const baggage = items.toLowerCase();
    if (baggage.includes('knife') || baggage.includes('gun')) {
    console.log('You are not allowed on board');
    } else {
    console.log('Welcome aboard');
    }
    }
    // You are not allowed on board
    checkBaggage('I have a laptop, some Food and pocket Knife');
    // Welcome aboard
    checkBaggage('Sock and camera');
    // You are not allowed on board
    checkBaggage('Got some snacks and a gun for protection');
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69

    ////// split and join

    // (4) ['a', 'very', 'nice', 'string']
    console.log('a+very+nice+string'.split('+'));
    //  ['Jonas', 'Schmedtmann']
    console.log('Jonas Schmedtmann'.split(' '));
    const [firstName, lastName] = 'Jonas Schmedtmann'.split(' ');
    // Jonas Schmedtmann
    console.log(firstName, lastName);


    const newName = ['Mr.', firstName, lastName.toUpperCase()].join(' ');
    console.log(newName); // 'Mr. Jonas SCHMEDTMANN'

    const capitalizdName = function (name) {
    name = name.toLowerCase();
    const names = name.split(' ');
    const newName = []
    for (const n of names) {
    // const nNew = n[0].toUpperCase() + n.slice(1);

    const nNew = n.replace(n[0], n[0].toUpperCase());
    newName.push(nNew);
    }
    return newName.join(' ');
    }

    const passenger = 'jessica ann simth daivs';
    // Jessica Ann Simth Daivs
    console.log(capitalizdName(passenger));

    ///// padding
    // Pads the current string with a given string (possibly repeated) so that the resulting string reaches a given length.

    const message = 'Go to gete 23!';
    // '+++++++++++Go to gete 23!'
    console.log(message.padStart(25, "+"));
    // Go to gete 23!+++++++++++
    console.log(message.padEnd(25, "+"));

    const maskCreditCard = function (number) {
    const str = number + '';
    const last = str.slice(-4);
    return last.padStart(str.length, '*')

    }

    // '***********8965'
    console.log(maskCreditCard(457814236578965));
    // *****8965
    console.log(maskCreditCard('236578965'));


    /////repeat

    const message2 = 'Bad weather... All Departures Delayed...';
    // Bad weather... All Departures Delayed...Bad weather... All Departures Delayed...Bad weather... All Departures Delayed...
    console.log(message2.repeat(3));

    const planeInline = function (n) {
    console.log(`There are ${n} plane in line ${'✈️'.repeat(n)}`);
    }
    // There are 5 plane in line ✈️✈️✈️✈️✈️
    planeInline(5);
    // There are 3 plane in line ✈️✈️✈️
    planeInline(3);
    // There are 12 plane in line ✈️✈️✈️✈️✈️✈️✈️✈️✈️✈️✈️✈️
    planeInline(12);

    function deep

    default parameters

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36

    const bookings = []

    // ES 6
    // the express can contain the other param before the param
    const createBooking = function (flightNum, numPassengers = 1 + 0, price = 199 * numPassengers) {

    // ES 5
    // numPassengers = numPassengers || 1;
    // price = price || 199;

    const booking = {
    flightNum,
    numPassengers,
    price,
    }
    console.log(booking);
    bookings.push(booking);
    }

    // {flightNum: 'LH123', numPassengers: undefined, price: undefined}
    // createBooking('LH123');


    // ES 6
    // {flightNum: 'LH123', numPassengers: 1, price: 199}
    createBooking('LH123');

    // {flightNum: 'LH123', numPassengers: 2, price: 800}
    createBooking('LH123', 2, 800);

    // {flightNum: 'LH123', numPassengers: 3, price: 597}
    createBooking('LH123', 3);

    // {flightNum: 'LH123', numPassengers: 1, price: 1000}
    createBooking('LH123', undefined, 1000);

    how passing arguments works: value vs reference

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40


    const flight = 'LH234';
    const jonas = {
    name: 'Jonas Schmedtmann',
    passport: 21346795,
    }
    const checkIn = function (flightNum, passenger) {
    flightNum = 'LH999';
    passenger.name = 'Mr.' + passenger.name;
    if (passenger.passport === 21346795) {
    console.log('Check In');
    } else {
    console.log('Wrong passport');
    }
    }

    // LH234
    // {name: 'Jonas Schmedtmann', passport: 21346795}
    console.log(flight, jonas);

    // same as doing ...
    // const flightNum = flight;
    // const passenger = jonas;
    checkIn(flight, jonas);


    // LH234
    // {name: 'Mr.Jonas Schmedtmann', passport: 21346795}
    console.log(flight, jonas);

    ///// example

    const newPassport = function (person) {
    person.passport = Math.trunc(Math.random() * 10000000000);
    }

    newPassport(jonas);
    // Wrong passport
    checkIn(flight, jonas);

    first class and higher order functions

    functions are simply values

    functions are just another ‘type’ of object

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    // store functions in variables or properties

    const add = (a, b) => a + b;
    const counter = {
    value: 23,
    inc: function () {
    this.value++;
    }
    }

    // pass functions as arguments to other functions
    // addEventListenner is higher order function
    // greet is the callback function
    const greet = () => console.log('Hey Jonas');
    btnClose.addEventListenner('click', greet);


    // return functions form functions
    // count is the higher order function
    // // function(){ counter++; } is the returned function
    function count() {
    let counter = 0;
    return function () {
    counter++;
    }
    }

    // call methods on functions
    counter.inc.bind(someOtherObject);

    high order functions

    a function that receives anthoer function as an argument
    a function that returns a new function
    or both

    functins accepting callback functions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    const oneWord = function (str) {
    return str.replace(/ /g, '').toLowerCase();
    };

    const upperFirstWord = function (str) {
    const [first, ...others] = str.split(' ');
    return [first.toUpperCase(), ...others].join(' ')
    };

    const transformer = function (str, fn) {
    console.log(`Original string: ${str}`);
    console.log(`Transformed string: ${fn(str)}`);
    console.log(`Trnasformed by: ${fn.name}`);
    }

    // Original string: JavaScript is the best programming language!
    // Transformed string: JAVASCRIPT is the best programming language!
    // Trnasformed by: upperFirstWord
    transformer('JavaScript is the best programming language!', upperFirstWord);

    // Original string: JavaScript is the best programming language!
    // Transformed string: javascriptisthebestprogramminglanguage!
    // Trnasformed by: oneWord
    transformer('JavaScript is the best programming language!', oneWord);

    const high5 = function () {
    console.log('😍');
    }

    document.body.addEventListener('click', high5);

    ['Jonas', 'Martha', 'Adam'].forEach(high5);

    functions returning functions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    const greet = function (greeting) {
    return function (name) {
    console.log(`${greeting} ${name}`);
    }
    }

    const greeterHey = greet('Hey');
    greeterHey('Jonas');
    greeterHey('Steven');


    greet('Hey')('Jonas');

    // functional programming

    const greet1 = greeting => name => console.log(`${greeting} ${name}`);

    the CALL and apply METHODS

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55

    const lufthansa = {
    airline: 'Lufthansa',
    iataCode: 'LH',
    booking: [],
    book(flightNum, name) {
    console.log(`${name} booked a seat on ${this.airline} flight ${this.iataCode}${flightNum}`);
    this.booking.push({
    flight: `${this.iataCode}${flightNum}`,
    name: name,
    })
    }
    }
    // Jonas Schmedtmann booked a seat on Lufthansa flight LH238
    lufthansa.book(238, 'Jonas Schmedtmann');
    // Jonas Smith booked a seat on Lufthansa flight LH635
    lufthansa.book(635, 'Jonas Smith');

    console.log(lufthansa.booking);


    const eurowings = {
    airline: 'Eurowings',
    iataCode: 'EW',
    booking: [],
    }


    const book = lufthansa.book;

    // in strict mode
    // regular functions call "this" is undefined
    // Uncaught TypeError: Cannot read properties of undefined
    // book(23, 'Sarah Williams');


    // Sarah Williams booked a seat on Eurowings flight EW23
    book.call(eurowings, 23, 'Sarah Williams');
    // Mary cooper booked a seat on Lufthansa flight LH239
    book.call(lufthansa, 239, 'Mary cooper');

    const swiss = {
    airline: 'Swiss Air Lines',
    iataCode: 'LX',
    booking: [],
    }

    // Mary cooper booked a seat on Swiss Air Lines flight LX556
    book.call(swiss, 556, 'Mary cooper');

    // Apply method
    const flightData = [583, 'George Cooper'];
    // George Cooper booked a seat on Swiss Air Lines flight LX583
    book.apply(swiss, flightData);
    book.call(swiss, ...flightData);

    bind method

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65


    const lufthansa = {
    airline: 'Lufthansa',
    iataCode: 'LH',
    booking: [],
    book(flightNum, name) {
    console.log(`${name} booked a seat on ${this.airline} flight ${this.iataCode}${flightNum}`);
    this.booking.push({
    flight: `${this.iataCode}${flightNum}`,
    name: name,
    })
    }
    };


    const eurowings = {
    airline: 'Eurowings',
    iataCode: 'EW',
    booking: [],
    };

    const book = lufthansa.book;
    const bookEW = book.bind(eurowings);

    // Steven Williams booked a seat on Eurowings flight EW23
    bookEW(23, 'Steven Williams');

    /////// partial application
    const bookEW23 = book.bind(eurowings, 23);
    // John Smith booked a seat on Eurowings flight EW23
    bookEW23('John Smith');
    // Martha Cooper booked a seat on Eurowings flight EW23
    bookEW23('Martha Cooper');

    ///// with Event Listeners

    lufthansa.planes = 300;
    lufthansa.buyPlane = function () {
    this.planes++;
    console.log(this, this.planes);
    }

    // button element
    // NaN
    document.querySelector('.buy').addEventListener('click', lufthansa.buyPlane)
    //
    document.querySelector('.buy').addEventListener('click', lufthansa.buyPlane.bind(lufthansa));

    /////// partial application

    const addTax = function (rate, value) {
    return value + value * rate;
    }
    // 220
    console.log(addTax(0.1, 200));

    // addVAT = function (value) {
    // return value + value * 0.23;
    // }
    // created a new function
    const addVAT = addTax.bind(null, 0.23);

    // 246
    console.log(addVAT(200));

    immediately invoked function expression

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34

    const runOnce = function () {
    console.log('this will never run again');
    }

    runOnce();
    runOnce();

    // Uncaught SyntaxError: Function statements require a function name
    // function() {
    // console.log('this will never run again');
    // }

    (function () {
    console.log('this will never run again');
    // const isPrivate = 23;
    })();

    (() => console.log('this will also never run again'))();

    // function scope

    // Uncaught ReferenceError: isPrivate is not defined
    // console.log(isPrivate);

    {
    const isPrivate = 23;
    var notPrivate = 46;
    }

    // Uncaught ReferenceError: isPrivate is not defined
    // console.log(isPrivate);
    // 46
    console.log(notPrivate);

    closures

    make functions remenber all the variables where it is birthed place.

    a function has access to the variable environment(VE) of the execution context in which it was created.
    even if it was gone.

    closure: VE attached to the function, exactly as it was at the time and place the function was created

    closure is priority over scope chain


    less formal

    a closure is the closed-over variable environment of the execution context in which a function was created, even after that execution context is gone;

    a closure give a function aceess to all the variables of its parent function, even after that parent function has returned. The function keeps a reference to its outer scope, which preserves the scope chain throughout time.

    a closeure makes sure that a function doesnt lose connection to variable that existed at the function’s birth place

    a clsure is like a backpack that a function carries around wherever it goes. This backpack has all the variable that were present in the environment where the function was created.

    we can not directly access a closure-over variables explicitly

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    const secureBooking = function () {
    let passengerCount = 0;

    return function () {
    passengerCount++;
    console.log(`${passengerCount} passengers`);
    }
    };

    const booker = secureBooking();
    // 1 passengers
    booker();
    // 2 passengers
    booker();
    // 3 passengers
    booker();

    console.dir(booker);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57

    //// ///// example 1

    let f;

    const g = function () {
    const a = 23;
    f = function () {
    console.log(a * 2);
    }
    }

    const h = function () {
    const b = 777;
    f = function () {
    console.log(b * 2);
    }
    }

    g();
    // 46
    f();

    console.dir(f)

    // re-assigning f function
    h();
    // 1554
    f();

    console.dir(f)


    ///// example 2

    const boardPassengers = function (n, wait) {
    const perGoup = n / 3;

    // 1s
    setTimeout(function () {
    console.log(`we are now boarding all ${n} passengers`);
    console.log(`There are 3 groups, each with ${perGoup} passengers`);
    }, wait * 1000);

    console.log(`will start boading in ${wait} seconds`);
    };

    // 'will start boading in 3 seconds'
    //////////////// 3s late
    // 'we are now boarding all 180 passengers'
    // 'There are 3 groups, each with 60 passengers'

    // closure have high priority
    const perGoup = 1000;

    boardPassengers(180, 3);

    1
    2
    3
    4
    5
    6
    7
    (function () {
    const header = document.querySelector('h1');
    header.style.color = 'red';
    document.body.addEventListener('click', function () {
    header.style.color = 'blue';
    });
    })();

    array deep

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61

    let arr = ['a', 'b', 'c', 'd', 'e'];


    // Returns a copy of a section of an array. For both start and end, a negative index can be used to indicate an offset from the end of the array. For example, -2 refers to the second to last element of the array.
    // (3) ['c', 'd', 'e']
    console.log(arr.slice(2));
    // (2) ['c', 'd']
    console.log(arr.slice(2, 4));
    // (2) ['c', 'd']
    console.log(arr.slice(-3, -1));
    // (2) ['b', 'c']
    console.log(arr.slice(1, -2));
    // (2) ['d', 'e']
    console.log(arr.slice(-2));
    // copy
    // (5) ['a', 'b', 'c', 'd', 'e']
    console.log(arr.slice());
    console.log([...arr]);

    ////////////// splice

    // Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.

    // @param start — The zero-based location in the array from which to start removing elements.

    // @param deleteCount — The number of elements to remove.

    // @returns — An array containing the elements that were deleted.
    // (3) ['c', 'd', 'e']
    // console.log(arr.splice(2));

    arr.splice(-1);

    //  ['a', 'b', 'c', 'd']
    console.log(arr);


    /////////// reverse
    // Reverses the elements in an array in place. This method mutates the array and returns a reference to the same array.

    arr = ['a', 'b', 'c', 'd', 'e'];

    const arr2 = ['j', 'i', 'h', 'g', 'f'];
    // (5) ['f', 'g', 'h', 'i', 'j']
    console.log(arr2.reverse());
    // (5) ['f', 'g', 'h', 'i', 'j']
    console.log(arr2);

    //////////////// concat

    const letters = arr.concat(arr2);
    // (10) ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
    console.log(letters);
    console.log([...arr, ...arr2]);

    //////////////// join
    // a - b - c - d - e - f - g - h - i - j
    //
    // a - b - c - d - e - f - g - h - i - j
    console.log(letters.join(' - '));

    at method

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    const arr = [23, 11, 64];

    // 23
    // console.log(arr[0]);
    console.log(arr.at(0));

    // 64
    // console.log(arr[arr.length - 1]);
    // console.log(arr.slice(-1)[0]);
    console.log(arr.at(-1));

    // 's'
    console.log(`jonas`.at(-1));

    foreach: looping arrays

    foreach
    cant break or continue

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41

    const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];

    for (const movement of movements) {
    if (movement > 0) {
    console.log(`You deposited ${movement}`);
    } else {
    console.log(`You withdraw ${Math.abs(movement)}`);
    }
    }

    console.log('------------------');

    // (method) Array<number>.forEach(callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any): void
    movements.forEach(function (movement) {
    if (movement > 0) {
    console.log(`You deposited ${movement}`);
    } else {
    console.log(`You withdraw ${Math.abs(movement)}`);
    }
    });

    console.log('------------------');

    for (const [i, movement] of movements.entries()) {
    if (movement > 0) {
    console.log(`Movement ${i + 1}: You deposited ${movement}`);
    } else {
    console.log(`Movement ${i + 1}: You withdraw ${Math.abs(movement)}`);
    }
    }

    console.log('------------------');

    movements.forEach(function (movement, i, arr) {
    if (movement > 0) {
    console.log(`Movement ${i + 1}: You deposited ${movement}`);
    } else {
    console.log(`Movement ${i + 1}: You withdraw ${Math.abs(movement)}`);
    }
    });

    foreach with maps and sets

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

    const currencies = new Map([
    ['USD', 'United States dollar'],
    ['EUR', 'Euro'],
    ['GBP', 'Pound sterling'],
    ]);


    // (method) Map<string, string>.forEach(callbackfn: (value: string, key: string, map: Map<string, string>) => void, thisArg?: any): void
    currencies.forEach(function (value, key, map) {
    console.log(`${key}: ${value}`);
    })

    /////// sets

    const currenciesUnique = new Set(['USD', 'GBP', 'USD', 'EUR', 'EUR']);

    console.log(currenciesUnique);


    // (method) Set<string>.forEach(callbackfn: (value: string, value2: string, set: Set<string>) => void, thisArg?: any): void
    currenciesUnique.forEach(function (value, value2, map) {
    console.log(`${value2}: ${value}`);
    });

    bankist project

    alt text

    create DOM element

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    const containerMovements = document.querySelector('.movements');
    containerMovements.innerHTML = '';

    const html = `
    <div class="movements__row">
    <div class="movements__type movements__type--${type}">${i + 1} ${type}</div>
    <div class="movements__value">${mov}</div>
    </div>
    `;
    // (method) Element.insertAdjacentHTML(position: InsertPosition, text: string): void
    containerMovements.insertAdjacentHTML('afterbegin', html)

    position
    A string representing the position relative to the element. Must be one of the following strings

    “beforebegin”
    Before the element. Only valid if the element is in the DOM tree and has a parent element.

    “afterbegin”
    Just inside the element, before its first child.

    “beforeend”
    Just inside the element, after its last child.

    “afterend”
    After the element. Only valid if the element is in the DOM tree and has a parent element.

    1
    2
    3
    4
    5
    6
    7
    <!-- beforebegin -->
    <p>
    <!-- afterbegin -->
    foo
    <!-- beforeend -->
    </p>
    <!-- afterend -->

    data transformations: map, filter, reduce

    map
    returns a new array containg the results of applying an operation on all origianl array elements.

    filter
    filter returns a new array containing the array elements that passed a specified test condition

    reduce
    boils(reduce) all array elements down to one single value(e.g. adding all elements together)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    const arr = [3, 1, 4, 3, 2];

    // map(callbackfn: (value: number, index: number, array: number[]) => any, thisArg?: any): any[]
    // A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
    // Calls a defined callback function on each element of an array, and returns an array that contains the results.

    const mapArr = arr.map(function (value) {
    return value * 2;
    })

    // (5) [6, 2, 8, 6, 4]
    console.log(mapArr);


    // filter(predicate: (value: number, index: number, array: number[]) => value is number, thisArg?: any): number[]
    // A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
    // Returns the elements of an array that meet the condition specified in a callback function.
    const filteredArr = arr.filter(function (value) {
    return value > 2;
    });

    // (3) [3, 4, 3]
    console.log(filteredArr);

    // reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number
    // A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
    // Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
    const reducedResult = arr.reduce(function (acc, current) {
    return acc + current;
    });

    // 13
    console.log(reducedResult);

    map

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

    const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];


    const eurToUsd = 1.1;

    const movmentsUsd = movements.map(function (mov) {
    return mov * eurToUsd;
    });

    console.log(movements);
    console.log(movmentsUsd);

    const movementsUsdFor = [];
    for (const mov of movements) {
    movementsUsdFor.push(mov * eurToUsd);
    }
    console.log(movementsUsdFor);

    const movmentsUsd1 = movements.map(mov => mov * eurToUsd);
    console.log(movmentsUsd1);

    const movementsDescriptions = movements.map((mov, i) => `Movement ${i + 1}: You ${mov > 0 ? 'deposited' : 'withdraw'} ${Math.abs(mov)}`);

    console.log(movementsDescriptions);

    filter method

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];

    const deposits = movements.filter((mov) => {
    return mov > 0;
    });
    // (5) [200, 450, 3000, 70, 1300]
    console.log(deposits);

    const deposits1 = [];
    for (const mov of movements) {
    if (mov > 0) {
    deposits1.push(mov);
    }
    }
    // (5) [200, 450, 3000, 70, 1300]
    console.log(deposits1);

    const withdrawals = movements.filter(mov => mov < 0);
    // (3) [-400, -650, -130]
    console.log(withdrawals);

    the reduce method

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27

    const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];

    // accumulator
    // (method) Array<number>.reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number (+2 overloads)
    // @param initialValue — If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
    //
    const balance = movements.reduce(function (acc, cur, i, arr) {
    // Iteration 0: 0
    // Iteration 1: 200
    // Iteration 2: 650
    // Iteration 3: 250
    // Iteration 4: 3250
    // Iteration 5: 2600
    // Iteration 6: 2470
    // Iteration 7: 2540
    console.log(`Iteration ${i}: ${acc}`);
    return acc + cur;
    }, 0);
    // 3840
    console.log(balance);

    let balance2 = 0;
    for (const mov of movements) {
    balance2 += mov;
    }
    console.log(balance2);
    1
    2
    3
    4
    5
    6
    /// maximum value

    const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];

    const max = movements.reduce((acc, mov) => acc < mov ? mov : acc, movements[0]);
    console.log(max);

    chainning methods

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    const eurToUsd = 1.1;
    const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];

    // pipeline
    const totalDepositesUsd = movements
    .filter(mov => mov > 0)
    // .map((mov, i, arr) => {
    // console.log(arr);
    // return mov * eurToUsd
    // })
    .map(mov => mov * eurToUsd)
    .reduce((acc, mov) => acc + mov, 0);

    // 5522.000000000001
    console.log(totalDepositesUsd);

    the find method

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27

    const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];

    // return the first element

    // (method) Array<number>.find(predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number | undefined (+1 overload)
    // Returns the value of the first element in the array where predicate is true, and undefined otherwise.
    // @param predicate
    //find calls predicate once for each element of the array, in ascending order, until it finds one where predicate returns true. If such an element is found, find immediately returns that element value. Otherwise, find returns undefined.
    const firstWithdrawal = movements.find(mov => mov < 0);
    // -400
    console.log(firstWithdrawal);


    console.log(accounts);
    const account = accounts.find(acc => acc.owner === 'Jessica Davis');
    console.log(account);

    // for of
    let accountFor = {};
    for (const acc of accounts) {
    if (acc.owner === 'Jessica Davis') {
    accountFor = acc;
    }
    }

    console.log(accountFor);

    bankist project login page

    1
    2
    3
    4
    5
    6
    7
    8
    const btnLogin = document.querySelector('.login__btn');
    btnLogin.addEventListener('click', function (e) {
    // prevent form form submitting
    e.preventDefault();
    });

    const inputLoginPin = document.querySelector('.login__input--pin');
    inputClosePin.blur();

    bankist project: implementing transfers

    the findindex method

    1
    2
    3
    4
    5
    /// delete account
    const index = accounts.findIndex(acc => acc.username === currentAccount.username)
    // console.log(accounts);
    accounts.splice(index, 1)
    // console.log(accounts);

    some and every methods

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

    //////////some

    const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];

    // only for elements value equal to arguments
    console.log(movements.includes(-130));

    const anyDeposits = movements.some(mov => mov > 5000);
    console.log(anyDeposits);

    ///////every
    // Determines whether all the members of an array satisfy the specified test.

    // false
    console.log(movements.every(mov => mov > 0));
    // true
    console.log(account4.movements.every(mov => mov > 0));

    /////// separate callback

    const deposit = mov => mov > 0;
    console.log(movements.some(deposit));
    console.log(movements.every(deposit));
    console.log(movements.filter(deposit));

    flat and flatmap

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41

    const arr = [[1, 2, 3], [4, 5, 6], 7, 8];
    // (8) [1, 2, 3, 4, 5, 6, 7, 8]
    // Returns a new array with all sub-array elements concatenated into it recursively up to the specified depth.
    // @param depth — The maximum recursion depth
    console.log(arr.flat());

    const arrDeep = [[1, 2, 3], [4, [5, 6]], 7, 8];
    // (7) [1, 2, 3, 4, Array(2), 7, 8]
    // console.log(arrDeep.flat());
    // (8) [1, 2, 3, 4, 5, 6, 7, 8]
    console.log(arrDeep.flat(2));

    const accountsMovements = accounts.map(acc => acc.movements);
    // (4) [Array(8), Array(8), Array(8), Array(5)]
    // 0: (8) [200, 450, -400, 3000, -650, -130, 70, 1300]
    // 1: (8) [5000, 3400, -150, -790, -3210, -1000, 8500, -30]
    // 2: (8) [200, -200, 340, -300, -20, 50, 400, -460]
    // 3: (5) [430, 1000, 700, 50, 90]
    console.log(accountsMovements);

    const allMovements = accountsMovements.flat();
    // (29) [200, 450, -400, 3000, -650, -130, 70, 1300, 5000, 3400, -150, -790, -3210, -1000, 8500, -30, 200, -200, 340, -300, -20, 50, 400, -460, 430, 1000, 700, 50, 90]
    console.log(allMovements);
    const overallBalance = allMovements.reduce((acc, mov) => acc + mov, 0);
    // 17840
    console.log(overallBalance);

    const overallBalanceChain = accounts
    .map(acc => acc.movements)
    .flat()
    .reduce((acc, mov) => acc + mov, 0);
    console.log(overallBalanceChain);

    ///////////////flatmap
    /// only one level deep

    const overallBalanceFlatMap = accounts
    .flatMap(acc => acc.movements)
    .reduce((acc, mov) => acc + mov, 0);
    console.log(overallBalanceFlatMap);

    sorting arrays

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    const owners = ['Jonas', 'Zach', 'Adam', 'Martha'];

    // (method) Array<string>.sort(compareFn?: ((a: string, b: string) => number) | undefined): string[]
    // Sorts an array in place. This method mutates the array and returns a reference to the same array.

    // @param compareFn
    // Function used to determine the order of the elements. It is expected to return a negative value if the first argument is less than the second argument, zero if they're equal, and a positive value otherwise. If omitted, the elements are sorted in ascending, ASCII character order.
    // [11,2,22,1].sort((a, b) => a - b)
    // (4) ['Adam', 'Jonas', 'Martha', 'Zach']
    console.log(owners.sort());
    // (4) ['Adam', 'Jonas', 'Martha', 'Zach']
    console.log(owners);

    //// Numbers
    const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];
    // (8) [200, 450, -400, 3000, -650, -130, 70, 1300]
    console.log(movements);
    // // (8) [-130, -400, -650, 1300, 200, 3000, 450, 70]
    // console.log(movements.sort());

    // return < 0 , a, b
    // return > 0 , b, a
    // (8) [-650, -400, -130, 70, 200, 450, 1300, 3000]
    console.log(movements.sort((a, b) => {
    if (a > b) return 1;
    if (b > a) return -1;
    }));


    // (8) [3000, 1300, 450, 200, 70, -130, -400, -650]
    console.log(movements.sort((a, b) => {
    if (a > b) return -1;
    if (b > a) return 1;
    }));

    // (8) [-650, -400, -130, 70, 200, 450, 1300, 3000]
    console.log(movements.sort((a, b) => a - b));
    1
    2
    3
    4
    5
    6
    7
    8
    9
    const dogs1 = [
    { weight: 22, curFood: 250, owners: ['Alice', 'Bob'] },
    { weight: 8, curFood: 200, owners: ['Matilda'] },
    { weight: 13, curFood: 275, owners: ['Sarah', 'John'] },
    { weight: 32, curFood: 340, owners: ['Michael'] },
    ];

    const copyDogs1 = dogs1.slice().sort((a, b) => a.weight - b.weight);
    console.log(copyDogs1);

    creating and filling arrays

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55

    console.log([1, 2, 3, 4, 5, 6, 7, 8]);
    console.log(new Array(1, 2, 3, 4, 5, 6, 7, 8));

    const x = new Array(7);
    // (7) [empty × 7]
    console.log(x);

    // (7) [empty × 7]
    // console.log(x.map(() => 5));


    // Changes all array elements from start to end index to a static value and returns the modified array
    // @param value — value to fill array section with
    // @param start
    // index to start filling the array at. If start is negative, it is treated as length+start where length is the length of the array.
    // @param end
    // index to stop filling the array at. If end is negative, it is treated as length+end.
    x.fill(1);
    // (7) [1, 1, 1, 1, 1, 1, 1]
    console.log(x);

    x.fill(2, 3, 5)
    // (7) [1, 1, 1, 2, 2, 1, 1]
    console.log(x);

    //// Array.from


    // (method) ArrayConstructor.from<any, number>(iterable: Iterable<any> | ArrayLike<any>, mapfn: (v: any, k: number) => number, thisArg?: any): number[] (+3 overloads)
    // Creates an array from an iterable object.
    // @param iterable — An iterable object to convert to an array.
    // @param mapfn — A mapping function to call on every element of the array.
    // (7) [1, 1, 1, 1, 1, 1, 1]
    console.log((Array.from({ length: 7 }, () => 1)));
    // (7) [1, 2, 3, 4, 5, 6, 7]
    console.log(Array.from({ length: 7 }, (value, index) => index + 1));
    // console.log(Array.from({ length: 7 }, (_, index) => index + 1));

    ////// querySelectorAll --> nodelist
    ////// dont have all array methods, like map()
    ////// convert to array

    const movementsUI = Array.from(document.querySelectorAll('.movements__value'));
    // (2) [div.movements__value, div.movements__value]
    console.log(movementsUI);

    const movementsUI2 = [...document.querySelectorAll('.movements__value')];

    labelBalance.addEventListener('click', function () {
    const movementsUI1 = Array.from(document.querySelectorAll('.movements__value'), el => Number(el.textContent.replace('€', '')));
    // (8) [-30, 8500, -1000, -3210, -790, -150, 3400, 5000]
    console.log(movementsUI1);

    })

    array summary

    alt text

    numbers and dates, times, intl

    conveting and check numbers

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35

    // all floating 64
    console.log(23 === 23.0); // 23
    // binary base 2
    console.log(0.1 + 0.2); // 0.30000000000000004

    // convert string to number
    console.log(Number('23'));
    console.log(+'23');

    ///////// parsing

    //(method) NumberConstructor.parseInt(string: string, radix?: number | undefined): number
    // Converts A string to an integer.
    // @param string — A string to convert into a number.
    // @param radix
    // A value between 2 and 36 that specifies the base of the number in string. If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. All other strings are considered decimal.
    console.log(Number.parseInt('30px')); // 30
    console.log(Number.parseFloat(' 2.5rem ')); // 2.5

    console.log(Number.isFinite(23)); // true
    //
    console.log(Number.isNaN(20)); // false
    console.log(Number.isNaN('20')); // false
    console.log(Number.isNaN(23 / 0)); // false
    console.log(Number.isNaN(+'20x')); // true

    // Only finite values of the type number, result in true.
    // check if value is number
    console.log(Number.isFinite(23)); // true
    console.log(Number.isFinite(23 / 0)); // false
    console.log(Number.isFinite(+'20x')); // false

    console.log(Number.isInteger(23)); // true
    console.log(Number.isInteger(23.2)); // false

    Math method and rounding

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50

    // Returns the square root of a number.
    console.log(Math.sqrt(25));
    // console.log(25 ** (1 / 2));

    // Returns the larger of a set of supplied numeric expressions.
    console.log(Math.max(5, '454', 12, 35, 65));


    console.log(Math.min(5, '454', 12, 35, 65));

    console.log(Math.PI * 10 ** 2);

    // random Returns a pseudorandom number between 0 and 1.
    // trunc Returns the integral part of the a numeric expression, x, removing any fractional digits. If x is already an integer, the result is x.
    console.log(Math.trunc(Math.random() * 6) + 1);

    const randomInt = (min, max) => Math.trunc(Math.random() * (max - min) + 1) + min;
    console.log(randomInt(2, 9));

    ///////// rounding integers

    // Returns a supplied numeric expression rounded to the nearest integer.
    console.log(Math.round(23.3)); // 23
    console.log(Math.round(23.9)); // 24

    // Returns the smallest integer greater than or equal to its numeric argument.
    console.log(Math.ceil(23.3)); // 24
    console.log(Math.ceil(23.9)); // 24
    console.log(Math.ceil(23)); // 23
    // Returns the greatest integer less than or equal to its numeric argument.
    console.log(Math.floor(23.3)); // 23
    console.log(Math.floor(23.9)); // 23
    console.log(Math.floor(23)); // 23

    console.log(Math.floor(-23.2)); // -24

    // when positive value floor === trunc
    console.log(Math.trunc(23.3)); // 23
    console.log(Math.trunc(23.9)); // 23
    console.log(Math.trunc(23)); // 23

    console.log(Math.trunc(-23.2)); // -23


    ///// rounding decimals
    console.log((2.7).toFixed(0)); // '3'
    console.log((2.7).toFixed(2)); // '2.70'
    console.log((2.2346).toFixed(2)); // '2.23'
    console.log(+(2.2346).toFixed(2)); // 2.23

    remainder operator

    1
    2
    3
    4
    5
    6
    7
    8
    9

    // remainder
    console.log(5 % 2);

    // even or odd

    const isEven = n => n % 2 === 0;
    console.log(isEven(8)); // true
    console.log(isEven(9)); // false

    numeric separators

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // 2,874,600,000
    const diameter = 2874600000;
    const diameter1 = 2_874_600_000;
    console.log(diameter1); // 2874600000

    const priceCents = 345_99;
    console.log(priceCents); // 34599

    const PI = 3.14_15;
    // const PI = 3._1415; // error
    // const PI = 3_.1415; // error
    // const PI = _3.1415; // error
    // const PI = 3.1415_; // error

    console.log(Number('230000'));
    console.log(Number('230_000')); // NaN
    console.log(Number.parseInt('230_000')); // 230

    BigInt

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

    // biggest number javascipt can represent
    // 9007199254740991
    console.log(2 ** 53 - 1);
    console.log(Number.MAX_SAFE_INTEGER);

    // 1.2365469446566512e+32
    console.log(123654694465665131313132131316464);

    // 123654694465665131313132131316464n
    console.log(123654694465665131313132131316464n);
    console.log(BigInt(123654694465665131313132131316464n));

    // Operations
    // 1365746113224452954n
    console.log(11321654n + 1365746113213131300n);

    // Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions
    // console.log(2315646 + 213654321316543123n);
    console.log(BigInt(2315646) + 213654321316543123n);

    console.log(typeof 20n); // 'bigint'

    console.log(321654212354n + ' is big'); // 321654212354 is big


    // divisions

    console.log(10n / 3n); // 3n

    creating dates

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    const now = new Date();
    console.log(now);

    console.log(new Date('Feb 21 2024 12:58:51'));

    console.log(new Date('December 24, 2015'));

    // '2019-11-18T21:31:17.178Z'
    console.log(account1.movementsDates[0]);
    console.log(new Date(account1.movementsDates[0]));

    // Date(year: number, monthIndex: number, date?: number | undefined, hours?: number | undefined, minutes?: number | undefined, seconds?: number | undefined, ms?: number | undefined): Date
    // The full year designation is required for cross-century date accuracy. If year is between 0 and 99 is used, then year is assumed to be 1900 + year.
    // Thu Nov 19 2037 15:52:12 GMT+0800 (中国标准时间)
    console.log(new Date(2037, 10, 19, 15, 52, 12));

    // Thu Dec 03 2037 15:52:12 GMT+0800 (中国标准时间)
    console.log(new Date(2037, 10, 33, 15, 52, 12));

    ///// time stamps
    // 1970-01-01
    console.log(new Date(0));
    // 3 days
    // Sun Jan 04 1970 08:00:00 GMT+0800 (中国标准时间)
    console.log(new Date(3 * 24 * 60 * 60 * 1000));

    /// working with Date

    const future = new Date(2037, 10, 13, 15, 52)
    // Fri Nov 13 2037 15:52:00 GMT+0800 (中国标准时间)
    console.log(future);
    console.log(future.getFullYear()) // 2037
    console.log(future.getMonth()) // 10
    console.log(future.getDate()) // 13
    console.log(future.getHours()) // 15
    console.log(future.getMinutes()) // 52
    console.log(future.getSeconds()) // 0
    console.log(future.getMilliseconds()) // 0

    // 2037-11-13T07:52:00.000Z
    console.log(future.toISOString()); //
    // 2141711520000
    console.log(future.getTime());
    // Fri Nov 13 2037 15:52:00 GMT+0800 (中国标准时间)
    console.log(new Date(2141711520000));
    // 1708492446836
    console.log(Date.now());

    future.setFullYear(2040);
    // Tue Nov 13 2040 15:52:00 GMT+0800 (中国标准时间)
    console.log(future);

    adding dates to bankist app project

    1
    2
    const day = `${now.getDate()}`.padStart(2, 0);
    const month = String(now.getMonth() + 1).padStart(2, 0);

    operation with dates

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    const future = new Date(2037, 10, 13, 15, 52)
    // 2141711520000
    console.log(Number(future));

    const daysPassed = function (date1, date2) {
    return Math.abs(date2 - date1) / (24 * 60 * 60 * 1000);
    }

    const days1 = daysPassed(new Date(2037, 3, 14), new Date(2037, 3, 24, 10, 8))
    // 10.422222222222222
    console.log(days1);

    internationalizing date (intl i18n)

    ISO LANGUAGE CODE TABLE
    http://www.lingoes.net/en/translator/langcode.htm

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    const now = new Date();
    // new (locales?: string | string[] | undefined, options?: Intl.DateTimeFormatOptions | undefined) => Intl.DateTimeFormat
    // (method) Intl.DateTimeFormat.format(date?: number | Date | undefined): string
    // labelDate.textContent = new Intl.DateTimeFormat('en-GB').format(now);
    // labelDate.textContent = new Intl.DateTimeFormat('en-US').format(now);
    // labelDate.textContent = new Intl.DateTimeFormat('zh-CN').format(now);

    const options = {
    hour: 'numeric',
    minute: 'numeric',
    day: 'numeric',
    // month: 'numeric',
    // month: 'long',
    month: '2-digit',
    year: 'numeric',
    weekday: 'long'


    }
    const locale = navigator.language;
    // 'zh-CN'
    console.log(locale);
    labelDate.textContent = new Intl.DateTimeFormat('zh-CN', options).format(now);

    internationalzing numbers (intl)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    const num = 134641312.32;

    const options = {
    // style: 'unit',
    // unit: 'mile-per-hour',
    style: 'percent',
    // style: 'currency',
    // currency: 'EUR',
    // useGrouping: false,

    }

    // US 134,641,312.32
    console.log('US', new Intl.NumberFormat('en-US').format(num));
    // Germany 134.641.312,32
    console.log('Germany', new Intl.NumberFormat('de-DE').format(num));
    // zh-CN 134,641,312.32 mi/h
    const locale = navigator.language;
    console.log(locale, new Intl.NumberFormat(locale, options).format(num));

    timer: setTimeout setInterval

    setTimeout once
    setInterval repeat

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // setTimeout(handler: TimerHandler, timeout?: number | undefined, ...arguments: any[]): number
    // 3000 -> 3s
    // the code is not stop here
    // Waiting...
    // Here is your pizza
    setTimeout(function () {
    console.log('Here is your pizza');
    }, 3000);
    console.log('Waiting...');

    // Here is your pizza with olives and spinach
    setTimeout(function (ing1, ing2) {
    console.log(`Here is your pizza with ${ing1} and ${ing2}`);
    }, 3000, 'olives', 'spinach');

    const ingredients = ['olives', 'spinach'];

    const pizzaTimer = setTimeout(function (ing1, ing2) {
    console.log(`Here is your pizza with ${ing1} and ${ing2}`);
    }, 3000, ...ingredients);

    console.log(pizzaTimer); // 4
    if (ingredients.includes('spinach')) clearTimeout(pizzaTimer)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const timeInter = setInterval(function () {
    const now = new Date();
    const hour = now.getHours();
    const min = now.getMinutes();
    const sec = now.getSeconds();
    console.log(`${hour}:${min}:${sec}`);
    }, 1000);

    setTimeout(function () {
    clearInterval(timeInter);
    }, 5000);

    bankist project: implemetn a countdown

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    const startLogoutTimer = function () {
    const tick = function () {
    const min = String(Math.floor(time / 60)).padStart(2, 0);
    const sec = String(time % 60).padStart(2, 0);

    // print the remaining time to the ui
    labelTimer.textContent = `${min}: ${sec}`;

    // when 0 seconds, stop timer and logout user
    if (time === 0) {
    clearInterval(timer);
    labelWelcome.textContent = 'LOG IN TO GET STARTED';
    containerApp.style.opacity = 0;

    }

    time--;
    }

    // set time to 5 mins
    let time = 120;

    // call the timer every second
    tick();
    const timer = setInterval(tick, 1000);
    return timer;
    }
    1
    2
    3
    4
    5
    let timer;
    btnLogin.addEventListener('click', function (e) {
    if (timer) clearInterval(timer)
    timer = startLogoutTimer();
    });

    advanced DOM and EVENT

    DOM deep

    • allows us to make javascript interact with the browser;
    • we can write javascript to create, modify and delete Html elements; set styles, classes and attributes; and listen and respond to events;
    • dom tree is generated from an html document, which can then interac with;
    • dom is a very complex api(application programming interface) that contains lots of methods and properties to interact with the dom tree

    types of dom objects

    alt text

    select, create, and delete elements

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48

    console.log(document.documentElement);
    console.log(document.head);
    console.log(document.body);

    // Returns the first element that is a descendant of node that matches selectors.
    const header = document.querySelector('.header');
    // NodeList
    const allSections = document.querySelectorAll('.section');
    console.log(allSections);

    console.log(document.getElementById('section--1'));
    // HTMLCollection ---> live collection
    console.log(document.getElementsByTagName('button'));
    // HTMLCollection
    console.log(document.getElementsByClassName('btn'));

    // create and insert elements

    // .insertAdjacentHTML()

    // Creates an instance of the element for the specified tag.
    const message = document.createElement('div');
    // classList: Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object.
    message.classList.add('cookie-message');
    message.textContent = 'We use cookied ....';

    message.innerHTML = 'We use cookied ....<button class="btn btn--close-cookie">Got it!</button>';

    // Inserts nodes before the first child of node, while replacing strings in nodes with equivalent Text nodes.
    header.prepend(message);
    // append: Inserts nodes after the last child of node, while replacing strings in nodes with equivalent Text nodes.
    ///// if it is used twice it is moved, not copy
    // cloneNode: Returns a copy of node. If deep is true, the copy also includes the node's descendants.
    header.append(message.cloneNode(true));

    // Inserts nodes just after node, while replacing strings in nodes with equivalent Text nodes.
    header.after(message);
    // Inserts nodes just before node, while replacing strings in nodes with equivalent Text nodes.
    header.before(message)

    //////////delete elements

    document.querySelector('.btn--close-cookie').addEventListener('click', function () {
    // Removes node.
    message.remove();
    // message.parentElement.removeChild(message);
    });

    style, attribute and class

    1
    2
    3
    4
    5
    6
    :root {
    --color-primary: #5ec576;
    --color-secondary: #ffcb03;
    --color-tertiary: #ff585f;
    --color-primary-darker: #4bbb7d;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <img
    src="img/logo.png"
    alt="Bankist logo"
    class="nav__logo"
    id="logo"
    designer="lucfe"
    data-version-number="3.0"
    />

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71

    //// inline style
    message.style.backgroundColor = '#37383d';
    message.style.width = '120%';
    /// in the style sheet, no inline style ''
    console.log(message.style.color);
    // rgb(55, 56, 61)
    console.log(message.style.backgroundColor);

    // CSSStyleDeclaration {0: 'accent-color', 1: 'align-content',...}
    // console.log(getComputedStyle(message));
    console.log(getComputedStyle(message).color);

    message.style.height = Number.parseFloat(getComputedStyle(message).height, 10) + 30 + 'px';
    console.log(message.style.height); // 85.6667px

    // setProperty:
    // (method) CSSStyleDeclaration.setProperty(property: string, value: string | null, priority?: string | undefined): void
    document.documentElement.style.setProperty('--color-primary', 'orangered')

    ////// Attributes

    const logo = document.querySelector('.nav__logo');

    ///// element standard attributes/property
    // Bankist logo
    console.log(logo.alt);
    /// full path
    // http://127.0.0.1:5500/complete-javascript-course-master/13-Advanced-DOM-Bankist/starter/img/logo.png
    console.log(logo.src);
    // nav__logo
    console.log(logo.className);

    logo.alt = 'Beautiful minimalist logo'

    //// non standard attributes/property

    // Returns element's first attribute whose qualified name is qualifiedName,
    console.log(logo.getAttribute('designer')); // lucfe
    // relative path: img/logo.png
    console.log(logo.getAttribute('src'));

    // (method) Element.setAttribute(qualifiedName: string, value: string): void
    // Sets the value of element's first attribute whose qualified name is qualifiedName to value.
    logo.setAttribute('designer', 'jonas');

    const link = document.querySelector('.nav__link--btn')
    console.log(link.href);// http://127.0.0.1:5500/complete-javascript-course-master/13-Advanced-DOM-Bankist/starter/index.html#
    console.log(link.getAttribute('href')); //

    /// data attributes
    // data-version-number="3.0"
    console.log(logo.dataset.versionNumber); // 3.0


    /// classList:
    // (property) Element.classList: DOMTokenList
    // Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object.

    // Adds all arguments passed, except those already present.
    logo.classList.add('c', 'j');
    // Adds all arguments passed, except those already present.
    logo.classList.remove('c');
    // If force is not given, "toggles" token, removing it if it's present and adding it if it's not present.
    logo.classList.toggle('c');
    // (method) DOMTokenList.contains(token: string): boolean
    // Returns true if token is present, and false otherwise.
    logo.classList.contains('c');

    // !!! dont use/// erase all classes
    // logo.className = 'jonas'

    smooth scrolling

    1
    2
    3
    4
    5
    <div class="header__title">
    <button class="btn--text btn--scroll-to">Learn more &DownArrow;</button>
    </div>
    <section class="section" id="section--1">
    </section>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

    const btnScrollTo = document.querySelector('.btn--scroll-to');
    const section1 = document.getElementById('section--1');

    btnScrollTo.addEventListener('click', e => {
    const s1coords = section1.getBoundingClientRect();
    // DOMRect {x: 0, y: 573.3333740234375, width: 1221.3333740234375, height: 1403.15625, top: 573.3333740234375, …}
    console.log(s1coords);

    console.log('current scroll (x/y)', window.pageXOffset, window.pageYOffset); // current scroll (x/y) 0 300

    // height/width of the viewport 573 1221
    console.log('height/width of the viewport', document.documentElement.clientHeight, document.documentElement.clientWidth);

    // scrolling relative to the viewport
    // window.scrollTo(s1coords.left + window.pageXOffset, s1coords.top + window.pageYOffset);

    // // smoth
    // window.scrollTo({
    // letf: s1coords.left + window.scrollX,
    // top: s1coords.top + window.scrollY,
    // behavior: "smooth"
    // });

    /// modern browser
    section1.scrollIntoView({
    behavior: "smooth",
    });
    })

    types of event and event handlers

    old
    <h1 onclick="alert('HTML alert')">

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    const h1 = document.querySelector('h1');

    const alertH1 = function (e) {
    alert('addEventListener: your are reading the heading');

    // Removes the event listener in target's event listener list with the same type, callback, and options.
    h1.removeEventListener('mouseenter', alertH1)
    }

    /// like mouse hover
    /// can add multible eventhandlers
    /// Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched.
    h1.addEventListener('mouseenter', alertH1);

    setTimeout(() => {
    h1.removeEventListener('mouseenter', alertH1)
    }, 5000);

    // /// old school
    // h1.onmouseenter = function (e) {
    // alert('addEventListener: your are reading the heading')
    // }

    event propagation: bubbling and capturing

    propagetion传播;培养
    the spreading of something (a belief or practice) into new regions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <html>
    <head>
    <title>A Simple Page</title>
    </head>
    <body>
    <section>
    <p>A paragraph with a <a href="#">link</a></p>
    <p>A second paragraph</p>
    </section>
    <section>
    <img src="dom.png" alt="THE DOM">
    </section>
    </body>
    </html>
    1. capturing phase
    2. target phase
    3. bubbling phase

    alt text

    1
    2
    3
    4
    5
    6
    document.querySelector('section').addEventListener('click', () => {
    alert('you clicked me')
    });
    document.querySelector('a').addEventListener('click', () => {
    alert('you clicked me')
    });

    example:

    alt text

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <nav class="nav">
    <img
    src="img/logo.png"
    alt="Bankist logo"
    class="nav__logo"
    id="logo"
    designer="lucfe"
    data-version-number="3.0"
    />
    <ul class="nav__links">
    <li class="nav__item">
    <a class="nav__link" href="#">Features</a>
    </li>
    </ul>
    </nav>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51

    // document.querySelector('section').addEventListener('click', () => {
    // alert('you clicked me')
    // });
    // document.querySelector('a').addEventListener('click', () => {
    // alert('you clicked me')
    // });


    /// rgb(255, 255, 255)

    const randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);
    const randomColor = () => `rgb(${randomInt(0, 255)}, ${randomInt(0, 255)}, ${randomInt(0, 255)})`

    console.log(randomColor());

    // nav__link
    // nav__links
    // nav

    document.querySelector('.nav__link').addEventListener('click', function (e) {
    console.log('nav__link');
    this.style.backgroundColor = randomColor();

    // <a> element
    console.log('LINK', e.target);

    // stop progagation
    // When dispatched in a tree, invoking this method prevents event from reaching any objects other than the current object.
    // e.stopPropagation();

    // When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET.
    }, true)
    document.querySelector('.nav__links').addEventListener('click', function (e) {
    console.log('nav__links');
    this.style.backgroundColor = randomColor();

    // <a> element
    console.log('LINKs', e.target);

    /// this === e.currentTarget
    // <ul>
    console.log('Links', e.currentTarget);
    })
    document.querySelector('.nav').addEventListener('click', function (e) {
    console.log('nav');
    this.style.backgroundColor = randomColor();

    // <a> element
    console.log('nav', e.target);
    })

    event delegation implementing: page navigation

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <nav class="nav">
    <img
    src="img/logo.png"
    alt="Bankist logo"
    class="nav__logo"
    id="logo"
    designer="lucfe"
    data-version-number="3.0"
    />
    <ul class="nav__links">
    <li class="nav__item">
    <a class="nav__link" href="#section--1">Features</a>
    </li>
    </ul>
    <ul class="nav__links">
    <li class="nav__item">
    <a class="nav__link" href="#section--2">Features</a>
    </li>
    </ul>
    </nav>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    //////////// page navigation

    // document.querySelectorAll('.nav__link').forEach(function (el) {
    // el.addEventListener('click', function (e) {
    // e.preventDefault();
    // console.log('LINK');

    // const id = this.getAttribute('href');
    // console.log(id);
    // document.querySelector(id).scrollIntoView({
    // behavior: 'smooth'
    // });
    // });
    // });

    // 1. add event listenner to comon parent elemetnt
    // 2. determine what element originated the event
    document.querySelector('.nav__links').addEventListener('click', function (e) {
    console.log(e.target);

    e.preventDefault();

    // mathing startegy
    if (e.target.classList.contains('nav__link')) {
    console.log('LINK');

    const id = e.target.getAttribute('href');
    console.log(id);
    document.querySelector(id).scrollIntoView({
    behavior: 'smooth'
    });
    }
    });

    examples 2
    add eventlistener that dont exit at the monment

    DOM traversingDOM traversing

    select elmenent by another elements

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <div class="header__title">
    <h1 onclick="alert('HTML alert')">
    When
    <!-- Green highlight effect -->
    <span class="highlight">banking</span>
    meets<br />
    <span class="highlight">minimalist</span>
    </h1>
    <h4>A simpler banking experience for a simpler life.</h4>
    <button class="btn--text btn--scroll-to">Learn more &DownArrow;</button>
    <img
    src="img/hero.png"
    class="header__img"
    alt="Minimalist bank items"
    />
    </div>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48

    const h1 = document.querySelector('h1');

    ///// going downwards: child

    ///// no matter how deep the child element are
    console.log(h1.querySelectorAll('.highlight'));

    // NodeList(9) [text, comment, text, span.highlight, text, br, text, span.highlight, text]
    console.log(h1.childNodes);
    // HTMLCollection(3) [span.highlight, br, span.highlight]
    console.log(h1.children);

    // element: span.highlight
    console.log(h1.firstElementChild);
    // element: span.highlight
    console.log(h1.lastElementChild);


    ///////// going upwards: parents


    // element: div.header__title
    console.log(h1.parentNode);
    console.log(h1.parentElement);


    // Returns the first (starting at element) inclusive ancestor that matches selectors, and null otherwise.
    /// reverse directiong of querySelector
    // element: header.header
    console.log(h1.closest('.header'));
    // element: h1
    console.log(h1.closest('h1'));

    // going sideways: siblings
    // null
    console.log(h1.previousElementSibling);
    // element: h4
    console.log(h1.nextElementSibling);


    /// chaining
    // HTMLCollection
    console.log(h1.parentElement.children);
    [...h1.parentElement.children].forEach(function (el) {
    if (el !== h1) el.style.transform = 'scale(0.5)';
    });

    tabs: tabbed component

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    <div class="operations">
    <div class="operations__tab-container">
    <button
    class="btn operations__tab operations__tab--1 operations__tab--active"
    data-tab="1"
    >
    <span>01</span>Instant Transfers
    </button>
    ...
    </div>


    <div
    class="operations__content operations__content--1 operations__content--active"
    >
    <div class="operations__icon operations__icon--1">
    </div>
    <h5 class="operations__header">
    Tranfser money to anyone, instantly! No fees, no BS.
    </h5>
    <p>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
    eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
    ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
    aliquip ex ea commodo consequat.
    </p>
    </div>
    ...
    </div>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    const tabs = document.querySelectorAll('.operations__tab');
    const tabsContainer = document.querySelector('.operations__tab-container');
    const tabsContent = document.querySelectorAll('.operations__content');

    tabsContainer.addEventListener('click', e => {
    e.preventDefault();
    const clicked = e.target.closest('button');
    console.log(clicked);

    /// guard clause
    if (!clicked) return;

    /// remove active class and add active tab
    tabs.forEach(t => t.classList.remove('operations__tab--active'));
    clicked.classList.add('operations__tab--active');

    /// active content area
    tabsContent.forEach(content => { content.classList.remove('operations__content--active') });
    document.querySelector(`.operations__content--${clicked.dataset.tab}`).classList.add('operations__content--active');

    });

    passing arguments to event handlers

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <nav class="nav">
    <img
    src="img/logo.png"
    alt="Bankist logo"
    class="nav__logo"
    id="logo"
    designer="lucfe"
    data-version-number="3.0"
    />
    <ul class="nav__links">
    <li class="nav__item">
    <a class="nav__link" href="#section--1">Features</a>
    </li>
    <li class="nav__item">
    <a class="nav__link" href="#section--2">Operations</a>
    </li>
    <li class="nav__item">
    <a class="nav__link" href="#section--3">Testimonials</a>
    </li>
    <li class="nav__item">
    <a class="nav__link nav__link--btn btn--show-modal" href="#"
    >Open account</a
    >
    </li>
    </ul>
    </nav>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

    const handleHover = function (e, opacity) {
    if (e.target.classList.contains('nav__link')) {
    const link = e.target;
    const siblings = link.closest('.nav').querySelectorAll('.nav__link');
    const logo = link.closest('.nav').querySelector('img');
    siblings.forEach(el => {
    if (el !== link) {
    el.style.opacity = this;
    }
    logo.style.opacity = this;
    });
    }
    }

    const nav = document.querySelector('.nav');
    // mouseenter dont progonation

    /// method 1
    // nav.addEventListener('mouseover', function (e) {
    // handleHover(e, 0.5);
    // });

    /// method 2
    nav.addEventListener('mouseover', handleHover.bind(0.5)
    );
    // passing 'argument' into handler
    // only one argument
    nav.addEventListener('mouseout', handleHover.bind(1));

    the scroll event: sticky navigation bar

    1
    2
    3
    4
    .nav.sticky {
    position: fixed;
    background-color: rgba(255, 255, 255, 0.95);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    /////// sticky naivgation

    const initialCoords = section1.getBoundingClientRect();
    console.log(initialCoords);

    //// scroll event not RECOMMENTED
    //// perfoming is bad
    window.addEventListener('scroll', function (e) {
    console.log(e);
    console.log(window.scrollY);

    if (window.scrollY > initialCoords.top) {
    nav.classList.add('sticky');
    } else {
    nav.classList.remove('sticky');
    }

    })

    better way: intersection observer api

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    ///provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport.


    // const obsCallback = function (entries, observer) {
    // entries.forEach(entry => {
    // console.log(entry); // IntersectionObserverEntry
    // })
    // };

    // const obsOptions = {
    // root: null,
    // threshold: [0, 0.2],
    // }


    // const observer = new IntersectionObserver(obsCallback, obsOptions);
    // observer.observe(section1);

    const header = document.querySelector('.header');
    const navHeight = nav.getBoundingClientRect().height;

    const stickyNav = function (entries) {
    const [entry] = entries;
    console.log(entry);

    if (!entry.isIntersecting) {
    nav.classList.add('sticky')
    } else {
    nav.classList.remove('sticky')
    }
    }

    const headerObserver = new IntersectionObserver(stickyNav, {
    root: null,
    threshold: 0,
    rootMargin: `-${navHeight}px`
    });

    headerObserver.observe(header);

    revealing elements on scroll

    1
    2
    3
    4
    .section--hidden {
    opacity: 0;
    transform: translateY(8rem);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    /////////// reveal sections

    const allSections = document.querySelectorAll('.section');

    const revealSection = function (entries, observer) {
    const [entry] = entries;
    console.log(entry);

    if (!entry.isIntersecting) return;
    entry.target.classList.remove('section--hidden');
    observer.unobserve(entry.target);
    };

    const sectionObserver = new IntersectionObserver(revealSection, {
    root: null,
    threshold: 0.15,

    });

    allSections.forEach(section => {
    section.classList.add('section--hidden');
    sectionObserver.observe(section);
    })

    lazy image loading

    1
    2
    3
    4
    5
    6
    <img
    src="img/digital-lazy.jpg"
    data-src="img/digital.jpg"
    alt="Computer"
    class="features__img lazy-img"
    />
    1
    2
    3
    .lazy-img {
    filter: blur(20px);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    ///// lazy loading images

    const imgTargets = document.querySelectorAll('img[data-src]');
    console.log(imgTargets);

    const loadImg = function (entries, observer) {
    const [entry] = entries;
    console.log(entry);

    if (!entry.isIntersecting) return;

    // replace the src img with data-src
    entry.target.src = entry.target.dataset.src;


    // remove the filter css class
    // should wait the image all loaded the remove the filter class
    // entry.target.classList.remove('lazy-img');
    entry.target.addEventListener('load', e => {
    entry.target.classList.remove('lazy-img');
    });


    // remove the observer
    observer.unobserve(entry.target);
    }

    const imgObserver = new IntersectionObserver(loadImg, {
    root: null,
    threshold: 0,
    rootMargin: '200px',
    });

    imgTargets.forEach(img => imgObserver.observe(img));

    building a slider component

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <section class="section" id="section--3">
    <div class="section__title section__title--testimonials">TITLE</div>

    <div class="slider">
    <!-- <div class="slide slide--1">
    <div class="testimonial">
    Lorem ipsum dolor sit, amet consectetur adipisicing elit. Explicabo,
    untur fugiat quae. Possimus illo est commodi iure
    veritatis rem ducimus adipisci cupiditate, quae quisquam?
    </div>
    </div>

    <div class="slide slide--2"></div> -->

    <div class="slide"><img src="img/img-1.jpg" alt="Photo 1" /></div>
    <div class="slide"><img src="img/img-2.jpg" alt="Photo 2" /></div>
    <div class="slide"><img src="img/img-3.jpg" alt="Photo 3" /></div>
    <div class="slide"><img src="img/img-4.jpg" alt="Photo 4" /></div>
    <button class="slider__btn slider__btn--left">&larr;</button>
    <button class="slider__btn slider__btn--right">&rarr;</button>
    <div class="dots"></div>
    </div>
    </section>
    1
    2
    3
    4
    5
    <div class="dots">
    <button class="dots__dot dots__dot--active" data-slide="0"></button>
    <button class="dots__dot" data-slide="1"></button>
    <button class="dots__dot" data-slide="2"></button>
    </div>
    1
    2
    3
    4
    .slider {

    overflow: hidden;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    //////////////slider

    const slider = function () {


    const sildes = document.querySelectorAll('.slide');
    const slider = document.querySelector('.slider');
    const btnLeft = document.querySelector('.slider__btn--left');
    const btnRight = document.querySelector('.slider__btn--right');
    const dotContainer = document.querySelector('.dots');

    let currentSlide = 0;
    const maxSlide = sildes.length

    // slider.style.overflow = 'visible';

    const createDots = function () {
    // for (let index = 0; index < maxSlide; index++) {
    // const buttonEl = document.createElement('button');
    // buttonEl.classList.add('dots__dot');
    // buttonEl.dataset['slide'] = index;
    // console.log(buttonEl);
    // dotContainer.append(buttonEl);
    // }
    sildes.forEach((_, i) => {
    dotContainer.insertAdjacentHTML('beforeend', `<button class="dots__dot" data-slide="${i}"></button>`);
    });

    };



    const activateDot = function (slide) {
    const dots = document.querySelectorAll('.dots__dot');
    dots.forEach(dot => dot.classList.remove('dots__dot--active'));
    const clicked = document.querySelector(`.dots__dot[data-slide="${slide}"]`)
    clicked.classList.add('dots__dot--active');
    }



    const goToSlide = function (slide) {
    sildes.forEach((s, i) => {
    s.style.transform = `translateX(${100 * i - 100 * slide}%)`;
    });

    /// active dot
    activateDot(slide);
    }


    /// next slide

    const nextSlide = function () {
    if (currentSlide === maxSlide - 1) {
    currentSlide = 0;
    } else {
    currentSlide++;
    }

    /// -100 0 100 200
    goToSlide(currentSlide);
    }

    const preSlide = function () {
    if (currentSlide === 0) {
    currentSlide = maxSlide - 1;
    } else {
    currentSlide--;
    }

    /// -100 0 100 200
    goToSlide(currentSlide);
    }

    const init = function () {

    createDots();
    activateDot(0);
    /// begining
    goToSlide(0);
    // 0, 100, 200, 300
    // sildes.forEach((s, i) => {
    // s.style.transform = `translateX(${100 * i}%)`;
    // });
    }

    init();
    /////////////events

    btnRight.addEventListener('click', nextSlide);

    btnLeft.addEventListener('click', preSlide)

    document.addEventListener('keydown', function (e) {
    // console.log(e);
    if (e.key === 'ArrowLeft') {
    preSlide();
    } else if (e.key === 'ArrowRight') {
    nextSlide();
    }

    });

    dotContainer.addEventListener('click', function (e) {
    e.preventDefault();
    const clicked = e.target;
    if (clicked.classList.contains('dots__dot')) {
    goToSlide(clicked.dataset.slide);

    /// active dot
    activateDot(clicked.dataset.slide);

    }
    })

    }

    slider();

    DOM load event

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // html and js downloaded
    document.addEventListener('DOMContentLoaded', function (e) {
    console.log(e);
    console.log(e.timeStamp);
    });

    /// all resources loaded, include css, images
    window.addEventListener('load', function (e) {
    console.log(e);
    });

    /// before user leave the page, like: close the tab
    // window.addEventListener('beforeunload', function (e) {
    // e.preventDefault();
    // console.log(e);
    // e.returnValue = '';
    // })

    js loading and execude

    alt text

    alt text

    OOP

    what is OOP?

    • oop is a programming paradigm based on the concept of objects

    • we use objects to model(describe) real world or abstract features

    • object may contain data(properties) and code (methods). by using objects, we pack data and the corresponding behavior into one block;

    • in oop, objects are self-contained pieces/ blocks of code

    • objects are building blocks of applicatins, and interact with one another;

    • interactions happen through a pubblic interface (API): methods that the code outside of the object can access and use to communicate with the object;

    • OOP was developed with the goal of organizing code, to make it more flexible and easier to maintain(avoid ‘spaghetti code’)

    • Abstraction: Ignoring or hiding details that dont matter, allowing us to get an overview perspective of the thing we’re implementing, instead of messing with details that don’t really matter to our implementation.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    User {
    user
    private password
    private email

    login(word){
    this.password == word
    }
    commnent(text) {
    this.checkSPAM(text)
    }
    private checkSPAM(text){
    // Verify logic
    }
    }
    • Encapsulation: Keeping properties and methos private inside the class, so they are not accessible from outside the class. Some methods cas be exposed as a public interface(API)

    alt text

    • Inheritance: Making all properties and methods of a certain class available to a child class, forming a hierarchical relationshipp between classes. This allows us to reuse commmon logic and to model real world relationships.

    alt text

    • Polymorphism: A child class can overwrite a method it inherited from a parent class.

    javascript OOP

    • Objects are linked to a prototype object;
    • Prototypal inheritance: The prototype contains methods (behavior) that are accessible to all objects linked to that prototype;
    • behavior is delegated(授权) to the linked prototype object.

    3 ways of implementing prototypal inheritance in javascript

    1. Constructor funtions
      • Technique to create objects from a function;
      • This is how built-in objects like Arrays, Maps or Sets are actually implemented.
    2. ES6 Classes
      • Modern alternative to constructor function syntax;
      • ‘Syntactic sugar’: behind the scenes, ES6 classes work exactly like constructor functions
      • ES6 clasees do not behavior like classes in “classical OOP”
    3. Object.create()
      • the easiest and most straightforward way of linking an object to a prototype object.

    constructor function and the new operator

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    //// dont use arrow function(no this keyword)
    const Person = function (firstName, birthYear) {
    // Person {}
    console.log(this);

    // instance properties
    this.firstName = firstName;
    this.birthYear = birthYear;

    // /// dont do this//
    // /// the object new create will all have the same copy function
    // this.clacAge = function(){
    // console.log(2037 - this.birthYear);
    // }

    }

    const jonas = new Person('Jonas', 1991);
    // Person {firstName: 'Jonas', birthYear: 1991}
    console.log(jonas);

    // 1. new object {} is created
    // 2. function is called, this is point to the new object {}
    // 3. the new object {} is linked to prototype
    // 4. function automatically return the new object {}

    const matilda = new Person('Matilda', 2017);
    const jack = new Person('Jack', 1975);
    console.log(matilda, jack);

    const jay = 'Jay';

    console.log(jonas instanceof Person); // true
    console.log(jay instanceof Person); // false

    prototypes

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    // prototypes

    //// all function have properties called prototype
    /// all the objects (the constructor function created ) have all the methods and properties ( the prototype object have)


    Person.prototype.calcAge = function () {
    console.log(2037 - this.birthYear);
    }
    // {calcAge: ƒ, constructor: ƒ}
    console.log(Person.prototype);

    console.log(jonas);
    jonas.calcAge(); // 46
    matilda.calcAge(); // 20




    // {calcAge: ƒ, constructor: ƒ}
    console.log(jonas.__proto__);
    console.log(jonas.__proto__ === Person.prototype); // true


    console.log(Person.prototype.isPrototypeOf(jonas)); // ture
    console.log(Person.prototype.isPrototypeOf(matilda)); // true
    console.log(Person.prototype.isPrototypeOf(Person)); // false


    ///// set properties to prototype

    Person.prototype.species = 'Homo Sapiens';

    console.log(jonas.species, matilda.species);

    console.log(jonas.hasOwnProperty('firstName')); // true
    console.log(jonas.hasOwnProperty('species')); // false

    prototypal inheritance: the prototype chain

    alt text

    alt text

    prototypal inheritance: built-in objects

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58


    // {species: 'Homo Sapiens', calcAge: ƒ, constructor: ƒ}
    console.log(jonas.__proto__);
    // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
    console.log(jonas.__proto__.__proto__);
    /// null
    console.log(jonas.__proto__.__proto__.__proto__);

    // ƒ Person(firstName, birthYear)
    console.dir(Person.prototype.constructor)

    /// true
    console.log(Person.prototype.constructor === Person)


    ///// array

    const arr = [1, 2, 5, 47, 98, 74, 42, 2, 5];

    // [constructor: ƒ, at: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, …]
    console.log(arr.__proto__);
    console.log(arr.__proto__ === Array.prototype); // true

    // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
    console.log(arr.__proto__.__proto__);
    console.log(arr.__proto__.__proto__ === Object.prototype); // true

    ////// example
    ////// dont do this in reality
    Array.prototype.unique = function () {
    return [...new Set(this)];
    }
    // (7) [1, 2, 5, 47, 98, 74, 42]
    console.log(arr.unique());

    //////

    const h1 = document.querySelector('h1');
    console.dir(h1);
    // HTMLHeadingElement
    console.dir(h1.__proto__);
    // HTMLElement
    console.dir(h1.__proto__.__proto__);
    // Element
    console.dir(h1.__proto__.__proto__.__proto__);
    // Node
    console.dir(h1.__proto__.__proto__.__proto__.__proto__);
    // EventTarget
    console.dir(h1.__proto__.__proto__.__proto__.__proto__.__proto__);
    // Object
    console.dir(h1.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__);


    /// ƒ anonymous()
    console.dir((x => x + 1).__proto__);
    /// Object
    console.dir((x => x + 1).__proto__.__proto__);

    ES6 classes

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    //// class expression
    // const PersonCl = class {}


    //// class declaration
    class PersonCl {
    constructor(firstName, birthYear) {
    this.firstName = firstName;
    this.birthYear = birthYear;
    }

    /// Methods will be added to the Constructor function's prototype property
    calcAge() {
    console.log(2037 - this.birthYear);
    }
    }

    const jessica = new PersonCl('Jessica', 1996);
    console.log(jessica.firstName);

    jessica.calcAge();

    // true
    console.log(jessica.__proto__ === PersonCl.prototype);


    // 1. Classes are NOt hoisted
    // 2. Class are first-class citizens
    // 3. classes are executed in strict mode

    classes: getter and setter

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38

    class Car {
    constructor(make, speed) {
    this.make = make;
    this.speed = speed;
    }

    accelerate() {
    this.speed += 10;
    console.log(this.speed);
    }

    brake() {
    this.speed -= 5;
    console.log(this.speed);
    }

    get speedUS() {
    return this.speed / 1.6
    }

    set speedUS(speedUS) {
    this.speed = speedUS * 1.6;
    }
    }

    const bmw = new Car('BMW', 120);
    const merc = new Car('Mercedes', 95);

    const ford = new Car('Ford', 120);

    console.log(ford.speed); // 120
    console.log(ford.speedUS); // 75
    console.log(ford.speedUS = 100); // 100
    console.log(ford.speed); // 160

    console.log(ford);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63

    const account = {
    owner: 'jonas',
    movements: [200, 530, 120, 300],


    get latest() {
    return this.movements.slice(-1).pop();
    },

    set latest(mov) {
    this.movements.push(mov)
    }
    }

    console.log(account.latest); // 300
    account.latest = 50;
    console.log(account.latest); // 50

    console.log(account);

    ////// class

    class PersonCl {
    constructor(fullName, birthYear) {
    this.fullName = fullName;
    this.birthYear = birthYear;
    }

    /// Methods will be added to the Constructor function's prototype property
    calcAge() {
    console.log(2037 - this.birthYear);
    }

    /// add 'get age()' to prototype
    //// add 'age' properties to object
    get age() {
    return 2037 - this.birthYear;
    }

    set fullName(name) {
    if (name.includes(' ')) this._fullName = name;
    else alert('not a full name')
    }

    get fullName() {
    console.log('this come for getter');
    return this._fullName;
    }
    }

    const jessica = new PersonCl('Jessica Davis', 1996);

    console.log(jessica);

    console.log(jessica.age); // 41

    console.log(jessica.fullName);
    // 'not a full name'
    // console.log(jessica.fullName = 'Jessica');
    // 'not a full name'
    // const walter = new PersonCl('Walter', 1996);

    static methods

    Array.from()
    method belong to Constructor object

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54

    const Person = function (firstName, birthYear) {
    // Person {}
    console.log(this);

    // instance properties
    this.firstName = firstName;
    this.birthYear = birthYear;


    }

    const jonas = new Person('Jonas', 1991);
    // Person {firstName: 'Jonas', birthYear: 1991}
    console.log(jonas);

    const matilda = new Person('Matilda', 2017);
    const jack = new Person('Jack', 1975);
    console.log(matilda, jack);

    Person.hey = function () {
    console.log('Hey there 👋');
    console.dir(this);
    }

    // this: ƒ Person(firstName, birthYear)
    /// object call a function, 'this' is the object
    Person.hey();

    // jonas.hey();

    /////// class

    class PersonCl {
    constructor(fullName, birthYear) {
    this.fullName = fullName;
    this.birthYear = birthYear;
    }

    /// Methods will be added to the Constructor function's prototype property
    calcAge() {
    console.log(2037 - this.birthYear);
    }

    // not add to instance
    static hey() {
    console.log('Hey there 👋');
    console.dir(this);
    }
    }


    // this: class PersonCl
    PersonCl.hey();

    Object.create

    alt text

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

    const PersonProto = {
    calcAge() {
    console.log(2037 - this.birthYear);
    },

    init(firstName, birthYear) {
    this.firstName = firstName;
    this.birthYear = birthYear;
    }
    };

    const steven = Object.create(PersonProto);

    //
    // {calcAge: ƒ}
    console.log(steven.__proto__);
    // true
    console.log(steven.__proto__ === PersonProto);

    steven.name = 'Steven';
    steven.birthYear = 2002;

    steven.calcAge(); // 35

    /////
    const sarah = Object.create(PersonProto);
    sarah.init('Sarah', 1979);
    sarah.calcAge();

    inheritance between ‘classes’: constructor functions

    alt text

    alt text

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51

    const Person = function (firstName, birthYear) {
    this.firstName = firstName;
    this.birthYear = birthYear;

    };

    Person.prototype.calcAge = function () {
    console.log(2037 - this.birthYear);
    };


    const Student = function (firstName, birthYear, course) {
    // this.firstName = firstName;
    // this.birthYear = birthYear;
    Person.call(this, firstName, birthYear);

    this.course = course;
    };
    ///// Student.prototype.__proto__ === Person.prototype
    Student.prototype = Object.create(Person.prototype);

    ////
    // ƒ Person(firstName, birthYear)
    console.dir(Student.prototype.constructor);
    ///////////
    Student.prototype.constructor = Student;

    Student.prototype.introduce = function () {
    console.log(`My name is ${this.firstName} and I study ${this.course}`);
    }

    const mike = new Student('Mike', 2020, 'Computer Science');

    console.log(mike);
    mike.introduce();

    mike.calcAge();



    // {introduce: ƒ}
    console.log(mike.__proto__);
    // {calcAge: ƒ, constructor: ƒ}
    console.log(mike.__proto__.__proto__);
    // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
    console.log(mike.__proto__.__proto__.__proto__);

    console.log(mike instanceof Student); // true
    console.log(mike instanceof Person); // true
    console.log(mike instanceof Object); // true

    polymorphism

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46

    const Car = function (make, speed) {
    this.make = make;
    this.speed = speed;

    }

    Car.prototype.accelerate = function () {
    this.speed += 10;
    console.log(this.speed);
    }
    Car.prototype.brake = function () {
    this.speed -= 5;
    console.log(this.speed);
    }

    const car1 = new Car('BMW', 120);
    const car2 = new Car('Mercedes', 95);

    const EV = function (make, speed, charge) {
    Car.call(this, make, speed);
    this.charge = charge;
    }

    EV.prototype = Object.create(Car.prototype);

    EV.prototype.constructor = EV;

    EV.prototype.chargeBattery = function (chargeTo) {
    this.charge = chargeTo;
    };

    EV.prototype.accelerate = function () {
    this.speed += 20;
    this.charge--;
    console.log(`${this.make} going at ${this.speed} km/h, with a charge of ${this.charge}%`);
    }

    const tesla = new EV('Tesla', 120, 23);


    tesla.accelerate();
    tesla.chargeBattery(90);
    tesla.accelerate();
    tesla.accelerate();
    tesla.chargeBattery(90);

    inheritance between ‘classes’: ES6 classes

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48

    class PersonCl {
    constructor(firstName, birthYear) {
    this.firstName = firstName;
    this.birthYear = birthYear;
    }

    /// Methods will be added to the Constructor function's prototype property
    calcAge() {
    console.log(2037 - this.birthYear);
    }
    }

    const jessica = new PersonCl('Jessica', 1996);
    console.log(jessica.firstName);

    class StudentCl extends PersonCl {
    constructor(firstName, birthYear, course) {
    /// Always need to happen first!!
    /// will create 'this' variable
    super(firstName, birthYear);

    this.course = course;
    }
    introduce() {
    console.log(`My name is ${this.firstName} and I study ${this.course}`);
    }

    calcAge() {
    console.log(`I feel more like ${2037 - this.birthYear + 10}`);
    }
    }

    const martha = new StudentCl('Martha Jones', 2012, 'Computer Science');
    // StudentCl {firstName: 'Martha Jones', birthYear: 2012, course: 'Computer Science'}
    console.log(martha);
    martha.introduce();

    martha.calcAge();


    ///// if no added argument to super() method then :;
    // class StudentCl1 extends PersonCl {
    // }

    // const martha1 = new StudentCl1('Martha Jones', 2012);
    // /// StudentCl1 {firstName: 'Martha Jones', birthYear: 2012}
    // console.log(martha1);

    inheritance between ‘classes’: Object.create

    alt text

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

    const PersonProto = {
    calcAge() {
    console.log(2037 - this.birthYear);
    },

    init(firstName, birthYear) {
    this.firstName = firstName;
    this.birthYear = birthYear;
    }
    };

    // const steven = Object.create(PersonProto);

    const StudentProto = Object.create(PersonProto);
    StudentProto.init = function (firstName, birthYear, course) {
    PersonProto.init.call(this, firstName, birthYear);
    this.course = course;
    }
    StudentProto.introduce = function () {
    console.log(`My name is ${this.firstName} and I study ${this.course}`);
    }

    const jay = Object.create(StudentProto);

    jay.init('Jay', 2010, 'Computer Science');
    jay.calcAge();
    jay.introduce();

    class example

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46

    class Account {
    constructor(owner, currency, pin) {
    this.owner = owner;
    this.currency = currency;
    this.pin = pin;

    this.movements = [];
    this.locale = navigator.language;

    console.log(`Thanks for opening an account, ${this.owner}`);
    }

    deposit(val) {
    this.movements.push(val);
    }

    withdraw(val) {
    this.movements.push(-val);
    }

    approveLoan(val) {
    return true;
    }

    requestLoan(val) {
    if (this.approveLoan()) {
    this.deposit(val);
    console.log('Loan approved');
    }
    }
    }

    const acc1 = new Account('Jonas', 'EUR', 1111);
    console.log(acc1);

    // acc1.movements.push(250);
    // acc1.movements.push(-140);
    // acc1.approveLoan(1000)


    acc1.deposit(250);
    acc1.withdraw(140);
    acc1.requestLoan(1000);

    console.log(acc1);

    Encapsulation: protected properties and methods

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53

    class Account {
    constructor(owner, currency, pin) {
    this.owner = owner;
    this.currency = currency;
    this._pin = pin;

    this._movements = [];
    this.locale = navigator.language;

    console.log(`Thanks for opening an account, ${this.owner}`);
    }

    // public interface
    getMovements() {
    return this._movements;
    }

    deposit(val) {
    this._movements.push(val);
    }

    withdraw(val) {
    this._movements.push(-val);
    }

    _approveLoan(val) {
    return true;
    }

    requestLoan(val) {
    if (this._approveLoan(val)) {
    this.deposit(val);
    console.log('Loan approved');
    }
    }
    }

    const acc1 = new Account('Jonas', 'EUR', 1111);
    console.log(acc1);

    // acc1._movements.push(250);
    // acc1._movements.push(-140);
    // acc1._approveLoan(1000)

    console.log(acc1.getMovements());


    acc1.deposit(250);
    acc1.withdraw(140);
    acc1.requestLoan(1000);

    console.log(acc1);

    Encapsulation: private class fields and methods

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82

    ////////// not implement yet!!!!!!
    // public fields
    // private fields
    // public Methods
    // private Methods


    class Account {
    /// public fields
    /// add to all instance of class, !!!!not add to the prototype
    locale = navigator.language;

    //// private fields
    /// add to all instance of class, !!!!not add to the prototype
    #movements = [];
    #pin;


    constructor(owner, currency, pin) {
    this.owner = owner;
    this.currency = currency;
    /// protected property
    this.#pin = pin;

    // this._movements = [];
    // this.locale = navigator.language;

    console.log(`Thanks for opening an account, ${this.owner}`);
    }

    ///// public Methods
    // public interface
    getMovements() {
    return this.#movements;
    }

    deposit(val) {
    this.#movements.push(val);
    }

    withdraw(val) {
    this.#movements.push(-val);
    }


    requestLoan(val) {
    if (this.#approveLoan(val)) {
    this.deposit(val);
    console.log('Loan approved');
    }
    }

    /// Private methods
    #approveLoan(val) {
    return true;
    }

    }

    const acc1 = new Account('Jonas', 'EUR', 1111);
    console.log(acc1);

    // acc1._movements.push(250);
    // acc1._movements.push(-140);
    // acc1._approveLoan(1000)

    // Uncaught SyntaxError: Private field '#movements' must be declared in an enclosing class
    // acc1.#movements.push(250);
    // acc1.#movements.push(-140);
    // Uncaught SyntaxError: Private field '#approveLoan' must be declared in an enclosing class
    // acc1.#approveLoan(1000)

    console.log(acc1.getMovements());


    acc1.deposit(250);
    acc1.withdraw(140);
    acc1.requestLoan(1000);

    console.log(acc1);

    chain methods

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    class Account {
    /// public fields
    /// add to all instance of class, !!!!not add to the prototype
    locale = navigator.language;

    //// private fields
    /// add to all instance of class, !!!!not add to the prototype
    #movements = [];
    #pin;


    constructor(owner, currency, pin) {
    this.owner = owner;
    this.currency = currency;
    /// protected property
    this.#pin = pin;

    // this._movements = [];
    // this.locale = navigator.language;

    console.log(`Thanks for opening an account, ${this.owner}`);
    }

    ///// public Methods
    // public interface
    getMovements() {
    return this.#movements;
    }

    deposit(val) {
    this.#movements.push(val);
    return this;
    }

    withdraw(val) {
    this.#movements.push(-val);
    return this
    }


    requestLoan(val) {
    if (this.#approveLoan(val)) {
    this.deposit(val);
    console.log('Loan approved');
    return this;
    }
    }

    /// Private methods
    #approveLoan(val) {
    return true;
    }

    }

    const acc1 = new Account('Jonas', 'EUR', 1111);
    console.log(acc1);


    console.log(acc1.getMovements());


    acc1.deposit(250);
    acc1.withdraw(140);
    acc1.requestLoan(1000);

    console.log(acc1);

    /////////////////////////////////chaining

    acc1.deposit(300).deposit(500).withdraw(35).requestLoan(3554).deposit(211);

    console.log(acc1.getMovements());

    OOP summary

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70

    class Person {
    constructor(fullName, birthYear) {
    this.fullName = fullName;
    this.birthYear = birthYear;
    }
    }
    // Child class and parent class
    // inheritance between classes, automatically sets prototype
    class Student extends Person {
    // public field(similar to property, available on created object)
    university = 'University of London';
    // private fields(not accessible outside of class)
    #studyHours = 0;
    #course;
    // static public field (available only on class)
    static numSubjects = 10;

    // constructor method, called by new operator. mandatory(强制) in regular class, might be omitted in a child class
    constructor(fullName, birthYear, startYear, course) {
    // call to parent(super) class (necessary with extend).Need to happen before accessing this
    super(fullName, birthYear);

    // instance property(available on created object)
    this.startYear = startYear;

    // redefining private field
    this.#course = course;
    }

    // public method
    introduce() {
    console.log(`I study ${this.#course} at ${this.university}`);
    }

    study(h) {
    // referencing private field and method
    this.#makecoffe();
    this.#studyHours += h;
    }

    // private method(might not yet work in your browser. "fake" alternative: _ instead of #)
    #makecoffe() {
    return 'Here is a coffee for you '
    }

    // getter method
    get testScore() {
    return this._testScore;
    }

    // setter method(use _ to set property with same name as method, and also add getter)
    set testScore(score) {
    this._testScore = score <= 20 ? score : 0;
    }

    // static method(available only on class. can not access instance properties nor methods, only static ones)
    static printCurriculum() {
    console.log(`There are ${this.numSubjects} subjects`);
    }
    }

    // creating new object with new operator
    const studentJonas = new Student('Jonas', 2020, 2037, 'Medicine');
    studentJonas.introduce(); // I study Medicine at University of London
    studentJonas.study(2);
    studentJonas.testScore = 36;
    console.log(studentJonas.testScore); // 0
    console.log(Student.numSubjects) // 10
    Student.printCurriculum();

    Mapty app OOP project

    project planning

    1. user stories
      • description of the application’s functionality from the user’s perspective
      • common format: As a [type of user(who)], I want [an action(what)] so that [a benefit(why)]
      • example
        1. as a user, i want to log my running workouts with location, distance, time, pace and steps/minute, so i can keep a log of all my running
        2. as a user, i want to log my cycling workouts with location, distance, time, speed and elevtion gain, so i can keep a log of all my cycling
        3. as a user i want to see all my workouts at a glance, so i can easily track my progress over time
        4. as a user, i want to also see my workouts on a map, so i can easily check where i work out the most
        5. as a user, i want to see all my workouts when i leave the app and come back later, so that i can keep using the app over time
    2. features
      • user 1:
        • 1.map where user clicks to add new workout(best way to get location coordinates)
        • 2.geolocation to display map at current location(more user friendly)
        • 3.form to input distance, time, pace, steps/minute
      • user 2: 4.form to input distance, time, speed, elevation gain
      • user 3: 5.display all workouts in a list
      • user 4: 6.display all workouts on the map
      • user 5:
        • 7.store workout data in the browser using local storage API
        • 8.on page load, read the saved data from local storage and display
    3. flowchart
      alt text
    4. architecture
    5. development

    the geolacation api

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    // Geolocation.getCurrentPosition(successCallback: PositionCallback, errorCallback?: PositionErrorCallback | null | undefined, options?: PositionOptions | undefined): void
    if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(
    function (position) {
    // console.log(position);
    const { latitude, longitude } = position.coords;
    console.log(latitude, longitude);
    console.log(`https://www.google.com/maps/@${latitude},${longitude}`);
    },
    function () {
    alert('Could not get your position')
    });
    }

    leaflet library: displaying a map

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    const coords = [latitude, longitude];

    // L.map(map-container-html-element-id)setView([latitude, longitude], zoomratio)
    const map = L.map('map').setView(coords, 13);

    // L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
    // attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    // }).addTo(map);
    L.tileLayer('https://tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);

    L.marker(coords).addTo(map)
    .bindPopup('A pretty CSS popup.<br> Easily customizable.')
    .openPopup();

    leaflet library: displaying a map marker

    1
    2
    3
    4
    5
    6
    .running-popup .leaflet-popup-content-wrapper {
    border-left: 5px solid var(--color-brand--2);
    }
    .cycling-popup .leaflet-popup-content-wrapper {
    border-left: 5px solid var(--color-brand--1);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    map.on('click', function (mapEvent) {
    console.log(mapEvent);
    const { latlng: { lat, lng } } = mapEvent;
    console.log(lat, lng);

    L.marker([lat, lng]).addTo(map)
    .bindPopup(L.popup({
    maxWidth: 250,
    minWidth: 100,
    // the popup closing when another popup is opened.
    autoClose: false,
    // the popup closing when user clicks on the map
    closeOnClick: false,
    // A custom CSS class name to assign to the popup.
    className: 'running-popup',
    }))
    // Sets the content of the popup bound to this layer.
    .setPopupContent('Workout')
    .openPopup();
    });

    render workout input form

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    <form class="form hidden">
    <div class="form__row">
    <label class="form__label">Type</label>
    <select class="form__input form__input--type">
    <option value="running">Running</option>
    <option value="cycling">Cycling</option>
    </select>
    </div>
    <div class="form__row">
    <label class="form__label">Distance</label>
    <input class="form__input form__input--distance" placeholder="km" />
    </div>
    <div class="form__row">
    <label class="form__label">Duration</label>
    <input
    class="form__input form__input--duration"
    placeholder="min"
    />
    </div>
    <div class="form__row">
    <label class="form__label">Cadence</label>
    <input
    class="form__input form__input--cadence"
    placeholder="step/min"
    />
    </div>
    <div class="form__row form__row--hidden">
    <label class="form__label">Elev Gain</label>
    <input
    class="form__input form__input--elevation"
    placeholder="meters"
    />
    </div>
    <button class="form__btn">OK</button>
    </form>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    const form = document.querySelector('.form');
    const inputType = document.querySelector('.form__input--type');
    const inputCadence = document.querySelector('.form__input--cadence');
    const inputElevation = document.querySelector('.form__input--elevation');

    let map, mapEvent;

    if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(
    function (position) {
    // console.log(position);
    const { latitude, longitude } = position.coords;
    console.log(latitude, longitude);
    console.log(`https://www.google.com/maps/@${latitude},${longitude}`);

    const coords = [latitude, longitude];

    // L.map(map-container-html-element-id)setView([latitude, longitude], zoomratio)
    map = L.map('map').setView(coords, 13);

    // L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
    // attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    // }).addTo(map);
    L.tileLayer('https://tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);

    // L.marker(coords).addTo(map)
    // .bindPopup('A pretty CSS popup.<br> Easily customizable.')
    // .openPopup();


    /// handling clicks on map
    map.on('click', function (mapE) {
    mapEvent = mapE;

    form.classList.remove('hidden');
    inputDistance.focus();

    });
    },
    function () {
    alert('Could not get your position')
    });
    }


    form.addEventListener('submit', function (e) {
    e.preventDefault();

    /// clear input field
    inputDistance.value = inputDuration.value = inputCadence.value = inputElevation.value = '';

    /// display marker
    console.log(mapEvent);
    const { latlng: { lat, lng } } = mapEvent;
    console.log(lat, lng);
    L.marker([lat, lng]).addTo(map)
    .bindPopup(L.popup({
    maxWidth: 250,
    minWidth: 100,
    // the popup closing when another popup is opened.
    autoClose: false,
    // the popup closing when user clicks on the map
    closeOnClick: false,
    // A custom CSS class name to assign to the popup.
    className: 'running-popup',
    }))
    // Sets the content of the popup bound to this layer.
    .setPopupContent('Workout')
    .openPopup();
    });

    inputType.addEventListener('change', function () {
    inputElevation.closest('.form__row').classList.toggle('form__row--hidden');
    inputCadence.closest('.form__row').classList.toggle('form__row--hidden');
    })

    project architecture

    alt text

    refactoring the project code for architecture

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    // prettier-ignore
    const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

    const form = document.querySelector('.form');
    const containerWorkouts = document.querySelector('.workouts');
    const inputType = document.querySelector('.form__input--type');
    const inputDistance = document.querySelector('.form__input--distance');
    const inputDuration = document.querySelector('.form__input--duration');
    const inputCadence = document.querySelector('.form__input--cadence');
    const inputElevation = document.querySelector('.form__input--elevation');


    class App {
    #map;
    #mapEvent;


    constructor() {
    this._getPostion();
    form.addEventListener('submit', this._newWorkout.bind(this));
    inputType.addEventListener('change', this._toggleElevationField);
    }

    _getPostion() {
    if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(
    this._loadMap.bind(this),
    function () {
    alert('Could not get your position')
    });
    }
    }

    _loadMap(position) {
    const { latitude, longitude } = position.coords;
    const coords = [latitude, longitude];
    this.#map = L.map('map').setView(coords, 13);

    L.tileLayer('https://tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(this.#map);

    /// handling clicks on map
    this.#map.on('click', this._showForm.bind(this));
    }


    _showForm(mapE) {
    this.#mapEvent = mapE;

    form.classList.remove('hidden');
    inputDistance.focus();
    }

    _newWorkout(e) {
    e.preventDefault();

    /// clear input field
    inputDistance.value = inputDuration.value = inputCadence.value = inputElevation.value = '';

    /// display marker
    console.log(this.#mapEvent);
    const { latlng: { lat, lng } } = this.#mapEvent;
    console.log(lat, lng);
    L.marker([lat, lng]).addTo(this.#map)
    .bindPopup(L.popup({
    maxWidth: 250,
    minWidth: 100,
    autoClose: false,
    closeOnClick: false,
    className: 'running-popup',
    }))
    .setPopupContent('Workout')
    .openPopup();
    }

    _toggleElevationField() {
    inputElevation.closest('.form__row').classList.toggle('form__row--hidden');
    inputCadence.closest('.form__row').classList.toggle('form__row--hidden');
    }

    }

    const app = new App();

    creating classes to managing workout data

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45

    class Workout {
    date = new Date();
    id = (Date.now() + '').slice(-10);

    constructor(coords, distance, duration) {
    this.coords = coords; // [lati, long]
    this.distance = distance; // in km
    this.duration = duration; // in min

    }
    }

    class Running extends Workout {
    constructor(coords, distance, duration, cadence) {
    super(coords, distance, duration);
    this.cadence = cadence;
    this.calcPace();
    }

    calcPace() {
    // min / km
    this.pace = this.duration / this.distance;
    return this.pace;
    }
    }

    class Cycling extends Workout {
    constructor(coords, distance, duration, elevationGain) {
    super(coords, distance, duration);
    this.elevationGain = elevationGain;
    this.calcSpeed();
    }

    calcSpeed() {
    // min / km
    this.speed = this.distance / (this.duration / 60);
    return this.speed;
    }
    }

    const run1 = new Running([39, -12], 5.2, 25, 178);
    const cycling1 = new Cycling([39, -12], 27, 95, 532);

    console.log(run1, cycling1);

    create a new workout

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    class Running extends Workout {
    type = 'running';}
    class Cycling extends Workout {
    type = 'cycling';}
    class App {

    #workouts = [];
    _newWorkout(e) {

    const validInputs = (...inputs) => inputs.every(inp => Number.isFinite(inp));
    const allPositive = (...inputs) => inputs.every(inp => inp > 0);

    e.preventDefault();

    //// get data from form
    const type = inputType.value;
    // const distance = Number(inputDistance.value);
    // const duration = Number(inputDuration.value);
    const distance = +inputDistance.value;
    const duration = +inputDuration.value;
    const { latlng: { lat, lng } } = this.#mapEvent;
    const coords = [lat, lng];
    let workout;

    //// if workout is runnign, create running object
    if (type === 'running') {
    const cadence = +inputCadence.value;
    //// check the data is valid
    // if (!Number.isFinite(distance) ||
    // !Number.isFinite(duration) ||
    // !Number.isFinite(cadence))
    // return alert('input should be a number');
    if (!validInputs(distance, duration, cadence) ||
    !allPositive(distance, duration, cadence))
    return alert('input should be a positive number');

    workout = new Running(coords, distance, duration, cadence);
    }

    //// if workout is runnign, create running object
    if (type === 'cycling') {
    const elevation = +inputElevation.value;
    if (!validInputs(distance, duration, elevation) ||
    !allPositive(distance, duration))
    return alert('input should be a positive number');

    workout = new Cycling(coords, distance, duration, elevation);
    }

    //// ad new object to workout array
    this.#workouts.push(workout);
    console.log(this.#workouts);

    //// render workout on map as marker
    /// display marker
    this._renderWorkoutMarker(workout);

    //// render workout on list

    //// hide form + clear input fields

    /// clear input field
    inputDistance.value = inputDuration.value = inputCadence.value = inputElevation.value = '';


    }

    _renderWorkoutMarker(workout) {
    L.marker(workout.coords).addTo(this.#map)
    .bindPopup(L.popup({
    maxWidth: 250,
    minWidth: 100,
    autoClose: false,
    closeOnClick: false,
    className: `${workout.type}-popup`,
    }))
    .setPopupContent('workout')
    .openPopup();
    }

    }

    render workouts

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    <li class="workout workout--running" data-id="1234567890">
    <h2 class="workout__title">Running on April 14</h2>
    <div class="workout__details">
    <span class="workout__icon">🏃‍♂️</span>
    <span class="workout__value">5.2</span>
    <span class="workout__unit">km</span>
    </div>
    <div class="workout__details">
    <span class="workout__icon"></span>
    <span class="workout__value">24</span>
    <span class="workout__unit">min</span>
    </div>
    <div class="workout__details">
    <span class="workout__icon">⚡️</span>
    <span class="workout__value">4.6</span>
    <span class="workout__unit">min/km</span>
    </div>
    <div class="workout__details">
    <span class="workout__icon">🦶🏼</span>
    <span class="workout__value">178</span>
    <span class="workout__unit">spm</span>
    </div>
    </li>

    <li class="workout workout--cycling" data-id="1234567891">
    <h2 class="workout__title">Cycling on April 5</h2>
    <div class="workout__details">
    <span class="workout__icon">🚴‍♀️</span>
    <span class="workout__value">27</span>
    <span class="workout__unit">km</span>
    </div>
    <div class="workout__details">
    <span class="workout__icon"></span>
    <span class="workout__value">95</span>
    <span class="workout__unit">min</span>
    </div>
    <div class="workout__details">
    <span class="workout__icon">⚡️</span>
    <span class="workout__value">16</span>
    <span class="workout__unit">km/h</span>
    </div>
    <div class="workout__details">
    <span class="workout__icon"></span>
    <span class="workout__value">223</span>
    <span class="workout__unit">m</span>
    </div>
    </li>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    _renderWorkout(workout) {
    let html = `
    <li class="workout workout--${workout.type}" data-id="${workout.id}">
    <h2 class="workout__title">${workout.description}</h2>
    <div class="workout__details">
    <span class="workout__icon">${workout.type === 'running' ? '🏃‍♂️' : '🚴‍♀️'}</span>
    <span class="workout__value">${workout.distance}</span>
    <span class="workout__unit">km</span>
    </div>
    <div class="workout__details">
    <span class="workout__icon">⏱</span>
    <span class="workout__value">${workout.duration}</span>
    <span class="workout__unit">min</span>
    </div>
    `;

    if (workout.type === 'running') html += `
    <div class="workout__details">
    <span class="workout__icon">⚡️</span>
    <span class="workout__value">${workout.pace.toFixed(1)}</span>
    <span class="workout__unit">min/km</span>
    </div>
    <div class="workout__details">
    <span class="workout__icon">🦶🏼</span>
    <span class="workout__value">${workout.cadence}</span>
    <span class="workout__unit">spm</span>
    </div>
    </li>
    `;
    if (workout.type === 'cycling') html += `
    <div class="workout__details">
    <span class="workout__icon">⚡️</span>
    <span class="workout__value">${workout.speed.toFixed(1)}</span>
    <span class="workout__unit">km/h</span>
    </div>
    <div class="workout__details">
    <span class="workout__icon">⛰</span>
    <span class="workout__value">${workout.elevationGain}</span>
    <span class="workout__unit">m</span>
    </div>
    </li>
    `;
    form.insertAdjacentHTML('afterend', html);
    }
    _hideForm() {
    /// clear input field
    inputDistance.value = inputDuration.value = inputCadence.value = inputElevation.value = '';

    form.style.display = 'none';
    form.classList.add('hidden');
    setTimeout(() => form.style.display = 'grid', 1000);
    }

    move to marker

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    _moveToPopup(e) {
    const workoutEl = e.target.closest('.workout');
    console.log(workoutEl);

    if (!workoutEl) return;

    const workout = this.#workouts.find(work => work.id === workoutEl.dataset.id);
    console.log(workout);

    this.#map.setView(workout.coords, this.#zoomLevel, {
    animate: true,
    pan: {
    duration: 1,
    },
    });
    }

    local storage

    JSON converting back to object dont have prototype chain

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    _loadMap(position) {

    /// load local storage workout on the map
    this.#workouts.forEach(work => {

    this._renderWorkoutMarker(work);
    });

    }


    _setLocalStorage() {

    // localStorage.setItem()
    // (method) Storage.setItem(key: string, value: string): void
    // Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.

    // JSON.stringify()
    // Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
    localStorage.setItem('workouts', JSON.stringify(this.#workouts));
    }

    _getLocalStorage() {
    /// Converts a JavaScript Object Notation (JSON) string into an object.
    const data = JSON.parse(localStorage.getItem('workouts'));
    console.log(data);

    if (!data) return;
    this.#workouts = data;

    // render workouts
    this.#workouts.forEach(work => {
    this._renderWorkout(work);
    /// error: map havent load yet
    // this._renderWorkoutMarker(work);
    });
    }

    reset() {
    localStorage.removeItem('workouts');
    // Reloads the current page.
    location.reload();
    }

    end

    alt text

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    'use strict';


    class Workout {
    date = new Date();
    id = (Date.now() + '').slice(-10);
    clicks = 0;

    constructor(coords, distance, duration) {
    this.coords = coords; // [lati, long]
    this.distance = distance; // in km
    this.duration = duration; // in min

    }

    _setDescription() {
    const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

    this.description = `${this.type[0].toUpperCase()}${this.type.slice(1)} on ${months[this.date.getMonth()]} ${this.date.getDate()}`;
    }

    click() {
    this.clicks++;
    }
    }

    class Running extends Workout {
    type = 'running';
    constructor(coords, distance, duration, cadence) {
    super(coords, distance, duration);
    this.cadence = cadence;
    this.calcPace();
    this._setDescription();
    }

    calcPace() {
    // min / km
    this.pace = this.duration / this.distance;
    return this.pace;
    }
    }

    class Cycling extends Workout {
    type = 'cycling';
    constructor(coords, distance, duration, elevationGain) {
    super(coords, distance, duration);
    this.elevationGain = elevationGain;
    this.calcSpeed();
    this._setDescription();
    }

    calcSpeed() {
    // min / km
    this.speed = this.distance / (this.duration / 60);
    return this.speed;
    }
    }



    /////////////////////////

    const form = document.querySelector('.form');
    const containerWorkouts = document.querySelector('.workouts');
    const inputType = document.querySelector('.form__input--type');
    const inputDistance = document.querySelector('.form__input--distance');
    const inputDuration = document.querySelector('.form__input--duration');
    const inputCadence = document.querySelector('.form__input--cadence');
    const inputElevation = document.querySelector('.form__input--elevation');

    class App {
    #map;
    #mapEvent;
    #workouts = [];
    #zoomLevel = 13;

    constructor() {
    this._getPostion();

    // get data from local storage
    this._getLocalStorage();

    // event handlers
    form.addEventListener('submit', this._newWorkout.bind(this));
    inputType.addEventListener('change', this._toggleElevationField);
    containerWorkouts.addEventListener('click', this._moveToPopup.bind(this));
    }

    _getPostion() {
    if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(
    this._loadMap.bind(this),
    function () {
    alert('Could not get your position')
    });
    }
    }

    _loadMap(position) {
    const { latitude, longitude } = position.coords;
    const coords = [latitude, longitude];
    this.#map = L.map('map').setView(coords, this.#zoomLevel);

    L.tileLayer('https://tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(this.#map);

    /// handling clicks on map
    this.#map.on('click', this._showForm.bind(this));

    /// load local storage workout on the map
    this.#workouts.forEach(work => {

    this._renderWorkoutMarker(work);
    });

    }


    _showForm(mapE) {
    this.#mapEvent = mapE;

    form.classList.remove('hidden');
    inputDistance.focus();
    }

    _hideForm() {
    /// clear input field
    inputDistance.value = inputDuration.value = inputCadence.value = inputElevation.value = '';

    form.style.display = 'none';
    form.classList.add('hidden');
    setTimeout(() => form.style.display = 'grid', 1000);
    }

    _newWorkout(e) {

    const validInputs = (...inputs) => inputs.every(inp => Number.isFinite(inp));
    const allPositive = (...inputs) => inputs.every(inp => inp > 0);

    e.preventDefault();

    //// get data from form
    const type = inputType.value;

    const distance = +inputDistance.value;
    const duration = +inputDuration.value;
    const { latlng: { lat, lng } } = this.#mapEvent;
    const coords = [lat, lng];
    let workout;

    //// if workout is runnign, create running object
    if (type === 'running') {
    const cadence = +inputCadence.value;

    if (!validInputs(distance, duration, cadence) ||
    !allPositive(distance, duration, cadence))
    return alert('input should be a positive number');

    workout = new Running(coords, distance, duration, cadence);
    }

    //// if workout is runnign, create running object
    if (type === 'cycling') {
    const elevation = +inputElevation.value;
    if (!validInputs(distance, duration, elevation) ||
    !allPositive(distance, duration))
    return alert('input should be a positive number');

    workout = new Cycling(coords, distance, duration, elevation);
    }

    //// ad new object to workout array
    this.#workouts.push(workout);
    console.log(this.#workouts);

    //// render workout on map as marker
    /// display marker
    this._renderWorkoutMarker(workout);

    //// render workout on list
    this._renderWorkout(workout);

    //// hide form + clear input fields
    this._hideForm();

    /// set local storage to all workouts
    this._setLocalStorage()

    }

    _toggleElevationField() {
    inputElevation.closest('.form__row').classList.toggle('form__row--hidden');
    inputCadence.closest('.form__row').classList.toggle('form__row--hidden');
    }

    _renderWorkoutMarker(workout) {
    L.marker(workout.coords).addTo(this.#map)
    .bindPopup(L.popup({
    maxWidth: 250,
    minWidth: 100,
    autoClose: false,
    closeOnClick: false,
    className: `${workout.type}-popup`,
    }))
    .setPopupContent(`${workout.type === 'running' ? '🏃‍♂️' : '🚴‍♀️'} ${workout.description}`)
    .openPopup();
    }

    _renderWorkout(workout) {
    let html = `
    <li class="workout workout--${workout.type}" data-id="${workout.id}">
    <h2 class="workout__title">${workout.description}</h2>
    <div class="workout__details">
    <span class="workout__icon">${workout.type === 'running' ? '🏃‍♂️' : '🚴‍♀️'}</span>
    <span class="workout__value">${workout.distance}</span>
    <span class="workout__unit">km</span>
    </div>
    <div class="workout__details">
    <span class="workout__icon">⏱</span>
    <span class="workout__value">${workout.duration}</span>
    <span class="workout__unit">min</span>
    </div>
    `;

    if (workout.type === 'running') html += `
    <div class="workout__details">
    <span class="workout__icon">⚡️</span>
    <span class="workout__value">${workout.pace.toFixed(1)}</span>
    <span class="workout__unit">min/km</span>
    </div>
    <div class="workout__details">
    <span class="workout__icon">🦶🏼</span>
    <span class="workout__value">${workout.cadence}</span>
    <span class="workout__unit">spm</span>
    </div>
    </li>
    `;
    if (workout.type === 'cycling') html += `
    <div class="workout__details">
    <span class="workout__icon">⚡️</span>
    <span class="workout__value">${workout.speed.toFixed(1)}</span>
    <span class="workout__unit">km/h</span>
    </div>
    <div class="workout__details">
    <span class="workout__icon">⛰</span>
    <span class="workout__value">${workout.elevationGain}</span>
    <span class="workout__unit">m</span>
    </div>
    </li>
    `;
    form.insertAdjacentHTML('afterend', html);
    }

    _moveToPopup(e) {
    const workoutEl = e.target.closest('.workout');
    // console.log(workoutEl);

    if (!workoutEl) return;

    const workout = this.#workouts.find(work => work.id === workoutEl.dataset.id);
    // console.log(workout);

    this.#map.setView(workout.coords, this.#zoomLevel, {
    animate: true,
    pan: {
    duration: 1,
    },
    });

    /// using public interface
    /// JSON converting back to object dont have prototype chain
    console.log(workout);
    // workout.click();
    }

    _setLocalStorage() {

    localStorage.setItem('workouts', JSON.stringify(this.#workouts));
    }

    _getLocalStorage() {

    const data = JSON.parse(localStorage.getItem('workouts'));
    console.log(data);

    if (!data) return;
    this.#workouts = data;

    // render workouts
    this.#workouts.forEach(work => {
    this._renderWorkout(work);
    });
    }

    reset() {
    localStorage.removeItem('workouts');
    // Reloads the current page.
    location.reload();
    }
    }

    const app = new App();

    asynchronous

    ajax

    synchronous

    • executed line by line
    • each line of code waits for previous line to finish
    • long-running operation block code execution

    asynchronous

    • Asynchronous code is executed after a task that runs in the ‘background’ finishes;
    • Asynchronous code is non-blockig
    • Execution doesnt wait for an asynchronous task to finish its work
    • callback functions alone do nto make code asynchornous(e.g. [1, 2, 3].map(v => v * 2;))
    • EventListener alone do nto make code asynchornous
    1
    2
    3
    4
    5
    6
    const img = document.querySelector('.dog');
    img.src = 'dog.jpg'; // asynchronous
    img.addEventListener('load', function(){
    img.classList.add('fadeIn');
    });
    p.sytle.width = '300px';

    Ajax:
    Asychronous Javascript and xml:
    allow us to communicate with remote web servers in an asynchronous way. with AJAx calls, we can request data from web servers dynamically.

    API
    Application Programming Interface
    Piece of software that can be used by another piece of software, in order to allow applications to talk to each other;

    Online API / Web API
    Application running on a server, that receives requests for data, and send data back as response;
    We can build our own web APIs(requires back-end development)

    cors:
    Cross-origin resource sharing (CORS) is a browser security feature that allows access to restricted resources on a web page from another domain.

    xmlhttprequest

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <article class="country">
    <img class="country__img" src="" />
    <div class="country__data">
    <h3 class="country__name">COUNTRY</h3>
    <h4 class="country__region">REGION</h4>
    <p class="country__row"><span>👫</span>POP people</p>
    <p class="country__row"><span>🗣️</span>LANG</p>
    <p class="country__row"><span>💰</span>CUR</p>
    </div>
    </article>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    const btn = document.querySelector('.btn-country');
    const countriesContainer = document.querySelector('.countries');

    ///////////////////////////////////////

    const getCountryData = function (country) {
    // Use XMLHttpRequest (XHR) objects to interact with servers. You can retrieve data from a URL without having to do a full page refresh. This enables a Web page to update just part of a page without disrupting what the user is doing.
    const request = new XMLHttpRequest();

    // open(method: string, url: string | URL): void
    // Sets the request method, request URL, and synchronous flag.
    request.open('GET', `https://restcountries.com/v3.1/name/${country}`);
    request.send(); // asychronous

    request.addEventListener('load', function () {
    // console.log(this); /// request object
    // console.log(this.responseText); // json
    const [data] = JSON.parse(this.responseText);
    // console.log(data);

    const html = `
    <article class="country">
    <img class="country__img" src="${data.flags.png}" />
    <div class="country__data">
    <h3 class="country__name">${data.name.common}</h3>
    <h4 class="country__region">${data.region}</h4>
    <p class="country__row"><span>👫</span>${(+data.population / 1000000).toFixed(1)} people</p>
    <p class="country__row"><span>🗣️</span>${Object.values(data.languages)[0]}</p>
    <p class="country__row"><span>💰</span>${data.timezones[0]}</p>
    </div>
    </article>
    `

    countriesContainer.insertAdjacentHTML('beforeend', html);
    countriesContainer.style.opacity = 1;
    });
    }

    getCountryData('portugal');
    getCountryData('usa');
    getCountryData('china');

    web: requests and response

    TCP/IP socket connection
    TCP: depack
    IP: route

    callback hell

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    const renderCountry = function (data, className = '') {
    const html = `
    <article class="country ${className}">
    <img class="country__img" src="${data.flags.png}" />
    <div class="country__data">
    <h3 class="country__name">${data.name.common}</h3>
    <h4 class="country__region">${data.region}</h4>
    <p class="country__row"><span>👫</span>${(+data.population / 1000000).toFixed(1)} people</p>
    <p class="country__row"><span>🗣️</span>${Object.values(data.languages)[0]}</p>
    <p class="country__row"><span>💰</span>${data.timezones[0]}</p>
    </div>
    </article>
    `

    countriesContainer.insertAdjacentHTML('beforeend', html);
    countriesContainer.style.opacity = 1;
    }

    const getCountryAndNeighborData = function (country) {

    // Ajax call country 1
    const request = new XMLHttpRequest();
    request.open('GET', `https://restcountries.com/v3.1/name/${country}`);
    request.send(); // asychronous

    request.addEventListener('load', function () {
    const [data] = JSON.parse(this.responseText);
    console.log(data);

    /// render country 1
    renderCountry(data);

    /// get neighbour country
    const [neighbour] = data.borders;
    console.log(neighbour);

    if (!neighbour) return;

    // Ajax call country 2
    const request2 = new XMLHttpRequest();
    request2.open('GET', `
    https://restcountries.com/v3.1/alpha/${neighbour}`);
    request2.send(); // asychronous

    request2.addEventListener('load', function () {
    const [data2] = JSON.parse(this.responseText);
    console.log(data2);

    /// render country 2
    renderCountry(data2, 'neighbour');
    })
    });
    }

    getCountryAndNeighborData('portugal');
    getCountryAndNeighborData('usa');
    // getCountryAndNeighborData('china');

    promises and the fetch API

    less formal

    promise:
    an object that is used as a placeholder for the future result of an asynchronous operation
    a container for an asynchronous delivered value
    a container for a future value

    • we no longer need to rely on events and callbacks passed into asynchronous functions to handle asynchronous results;
    • instead of nesting callbakcs, we can chain promises for a sequence of asynchronous operation: escaping callback hell;

    lifecycle:
    pending –> settled (fulfilled, rejected)

    build –> consume

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    // function fetch(input: RequestInfo | URL, init?: RequestInit | undefined): Promise<Response>
    // const promise = fetch('https://restcountries.com/v3.1/name/portugal');

    // console.log(promise);

    const getCountryData = function (country) {

    // (method) Promise<Response>.then<any, never>(onfulfilled?: ((value: Response) => any) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<any>
    // Attaches callbacks for the resolution and/or rejection of the Promise
    fetch(`https://restcountries.com/v3.1/name/${country}`).then(function (response) {
    console.log(response); // Response object
    //将输入作为 JSON 解析,以生成一个 JavaScript promise 对象。
    return response.json()
    }).then(function (data) {
    console.log(data);
    renderCountry(data[0])
    });

    }


    getCountryData('portugal');

    chaining promises

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    const getCountryData = function (country) {


    fetch(`https://restcountries.com/v3.1/name/${country}`)
    .then(function (response) {
    return response.json()
    })
    .then(function (data) {
    renderCountry(data[0]);
    const neighbour = data[0].borders[0];
    console.log(neighbour);

    if (!neighbour) return;

    return fetch(`https://restcountries.com/v3.1/alpha/${neighbour}`);

    // ////!!! dont do this
    // return fetch(`https://restcountries.com/v3.1/alpha/${neighbour}`).then().then();
    })
    .then(response => response.json())
    .then(data => renderCountry(data[0], 'neighbour'));

    }


    getCountryData('portugal');

    handling rejected promises

    404 error is still the fullfill callback

    1
    2
    3
    4
    5
    6
    fetch(`https://restcountries.com/v3.1/name/${country}`)
    .then(function (response) {
    return response.json()
    }, function (err) {
    console.log(err);
    })
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    fetch(`https://restcountries.com/v3.1/name/${country}`)
    .then(response => response.json())
    .then(data => renderCountry(data[0], 'neighbour'))

    //(method) Promise<void>.catch<void>(onrejected?: ((reason: any) => void | PromiseLike<void>) | null | undefined): Promise<void>
    /// handling all the error from the first promise
    .catch(err => {
    console.log(err);
    renderError(`Something went wrong ${err.message}`)
    });


    //(method) Promise<void>.finally(onfinally?: (() => void) | null | undefined): Promise<void>
    // Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The resolved value cannot be modified from the callback.
    .finally(() => {
    countriesContainer.style.opacity = 1

    });

    throwing error manually

    throwing error manually will be catch by the last catch() callback;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    fetch(`https://restcountries.com/v3.1/name/${country}`)
    .then(function (response) {
    console.log(response);

    if (!response.ok) {
    throw new Error(`Country not found!${response.status}`)
    }

    return response.json()
    })
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    const getJSON = function (url, errorMsg = 'Something went wrong') {
    return fetch(url)
    .then(function (response) {

    if (!response.ok) {
    throw new Error(`${errorMsg} ${response.status}`)
    }

    return response.json()
    })
    }

    const getCountryData = function (country) {


    getJSON(`https://restcountries.com/v3.1/name/${country}`, 'country not found')
    .then(function (data) {
    renderCountry(data[0]);

    const neighbour = data[0].borders[0];

    if (!neighbour) throw new Error('NO neighbour');

    return getJSON(`https://restcountries.com/v3.1/alpha/${neighbour}`, 'country not found');
    })
    .then(data => renderCountry(data[0], 'neighbour'))

    .catch(err => {
    console.error(err);
    console.dir(err);
    renderError(`Something went wrong ${err.message}`)
    })

    .finally(() => {
    countriesContainer.style.opacity = 1

    });

    }

    event loop

    promises
    microtasks queue:
    has priority over call back queue

    eventlistener
    callback queue

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    console.log('Test start');

    setTimeout(() => console.log('0 sec timer'), 0);
    // (method) PromiseConstructor.resolve<string>(value: string): Promise<string> (+2 overloads)
    // Creates a new resolved promise for the provided value.
    Promise.resolve('Resolved promise 1').then(res => console.log(res));
    Promise.resolve('Resolved promise 2').then(res => {
    for (let index = 0; index < 100000; index++) {
    }
    console.log(res);
    });
    console.log('Test end');

    // Test start
    // Test end
    // Resolved promise 1
    // Resolved promise 2
    // 0 sec timer

    build a promise

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    /// var Promise: PromiseConstructor
    // new <any>(executor: (resolve: (value: any) => void, reject: (reason?: any) => void) => void) => Promise<any>
    // A callback used to initialize the promise. This callback is passed two arguments: a resolve callback used to resolve the promise with a value or the result of another promise, and a reject callback used to reject the promise with a provided reason or error.
    const lotteryPromise = new Promise(function (resolve, reject) {
    console.log('Lotter draw is happening');
    setTimeout(function () {
    if (Math.random() >= 0.5) {
    resolve('You win 10000$');
    } else {
    reject(new Error('You lost your money'));
    }
    }, 2000);
    });

    lotteryPromise.then(res => console.log(res), err => console.log(err));


    //// promisifying setTimeout
    const wait = function (seconds) {
    return new Promise(function (resolve) {
    setTimeout(resolve, seconds * 1000);
    })
    }

    wait(1)
    .then(() => {
    console.log(`1 second pasted`);
    return wait(1);
    })
    .then(() => {
    console.log(`2 second pasted`);
    return wait(1);
    })
    .then(() => {
    console.log(`3 second pasted`);
    return wait(1);
    })
    .then(() => {
    console.log(`4 second pasted`);
    return wait(1);
    })
    .then(() => {
    console.log(`5 second pasted`);
    return wait(1);
    })


    setTimeout(() => {
    console.log('1 second passed');
    setTimeout(() => {
    console.log('2 seconds passed');
    setTimeout(() => {
    console.log('3 seconds passed');
    setTimeout(() => {
    console.log('4 seconds passed');
    setTimeout(() => {
    console.log('5 seconds passed');
    }, 1000);
    }, 1000);
    }, 1000);
    }, 1000);
    }, 1000);

    Promise.resolve('abc').then(x => console.log(x));

    promisify geolocation api

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    navigator.geolocation.getCurrentPosition(position => console.log(position), err => console.log(err));

    // const getPostion = function () {
    // return new Promise((resolve, reject) => {
    // navigator.geolocation.getCurrentPosition(position => resolve(position), err => reject(err))
    // });
    // };
    const getPostion = function () {
    return new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(resolve, reject)
    });
    };

    getPostion()
    .then(position => {
    console.log(position);
    })
    1
    2
    3
    4
    5
    6
    7
    8
    const whereAmI = function () {
    getPostion()
    .then(position => {
    const { latitude: lat, longitude: lng } = position;
    return fetch(`https://geocode.xyz/${lat},${lng}?geoit=json&auth=246057772253706376639x95870`)

    });
    }

    code challenge 31

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    const wait = function (seconds) {
    return new Promise(function (resolve) {
    setTimeout(resolve, seconds * 1000);
    })
    }

    const createImage = function (imgPath) {
    return new Promise((resolve, reject) => {
    const ImgEl = document.createElement('img');
    ImgEl.src = imgPath;
    ImgEl.addEventListener('load', () => {
    document.querySelector('.images').append(ImgEl);
    resolve(ImgEl);
    });

    ImgEl.addEventListener('error', function () {
    reject(new Error('Image not found'));
    });
    });
    };

    let ImgEle;

    createImage('img/img-1.jpg')
    .then(ImgEl => {
    ImgEle = ImgEl
    return wait(2);
    })
    .then(() => {
    ImgEle.style.display = 'none';
    return createImage('img/img-2.jpg');
    })
    .then(ImgEl => {
    ImgEle = ImgEl;
    return wait(2)
    })
    .then(() => {
    ImgEle.style.display = 'none';
    })
    .catch(err => console.log(err.message))

    consuming promises with async/await

    sugar cake

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    const getPostion = function () {
    return new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(resolve, reject)
    });
    };

    const whereAmI = async function () {
    ///geolocation
    const position = await getPostion();
    const { latitude: lat, longitude: lng } = position.coords

    // reverse geocoding
    const reGeo = await fetch(`https://geocode.xyz/${lat},${lng}?geoit=json&auth=246057772253706376639x95870`)
    const dataGeo = await reGeo.json();
    console.log(dataGeo);

    // country data
    const res = await fetch(`https://restcountries.com/v3.1/alpha/${dataGeo.prov}`);
    console.log(res);
    const data = await res.json();
    console.log(data);
    renderCountry(data[0]);
    };

    whereAmI();
    console.log('First executed');

    async/await error handling

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    const getPostion = function () {
    return new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(resolve, reject)
    });
    };

    const whereAmI = async function () {
    try {///geolocation
    const position = await getPostion();
    const { latitude: lat, longitude: lng } = position.coords


    // reverse geocoding
    const reGeo = await fetch(`https://geocode.xyz/${lat},${lng}?geoit=json&auth=246057772253706376639x95870`)

    if (!reGeo.ok) throw new Error('cant get location data')

    const dataGeo = await reGeo.json();
    console.log(dataGeo);


    // country data
    const res = await fetch(`https://restcountries.com/v3.1/alpha/${dataGeo.prov}`);
    console.log(res);

    if (!res.ok) throw new Error('cant get country data')

    const data = await res.json();
    console.log(data);
    renderCountry(data[0]);

    } catch (err) {
    console.error(err);
    renderError(`Something went wrong ${err.message}`)
    }
    };

    whereAmI();
    console.log('First executed');

    //////////////////////////////

    // try {
    // let y = 1;
    // const x = 2;
    // x = 3;
    // } catch (error) {
    // // Assignment to constant variable.
    // console.log(error.message);
    // }

    returning values from async functions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    const getPostion = function () {
    return new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(resolve, reject)
    });
    };

    const whereAmI = async function () {
    try {///geolocation
    const position = await getPostion();
    const { latitude: lat, longitude: lng } = position.coords


    // reverse geocoding
    const reGeo = await fetch(`https://geocode.xyz/${lat},${lng}?geoit=json&auth=246057772253706376639x95870`)

    if (!reGeo.ok) throw new Error('cant get location data')

    const dataGeo = await reGeo.json();

    // country data
    const res = await fetch(`https://restcountries.com/v3.1/alpha/${dataGeo.prov}`);

    if (!res.ok) throw new Error('cant get country data')

    const data = await res.json();
    renderCountry(data[0]);

    /// return the outfilled value !!!!!!
    return dataGeo.prov;
    } catch (err) {
    console.error(err);
    renderError(`Something went wrong ${err.message}`)

    // reject promise returned from aysnc function
    throw err;
    }
    };

    console.log('1: will get location');
    // const promise =
    // whereAmI()
    // .then(country => { console.log(country); })
    // .catch(err => console.error(err.message))
    // .finally(() => console.log('3: Finished getting location'));
    // console.log('3: Finished getting location');

    //// async await Ife

    (async function () {
    try {
    console.log('1: will get location');
    const country = await whereAmI();
    console.log(country);

    } catch (err) {
    console.log(err);
    }
    console.log('3: Finished getting location');
    })();

    running promises in parallel

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    const getJSON = function (url, errorMsg = 'Something went wrong') {
    return fetch(url)
    .then(function (response) {

    if (!response.ok) {
    throw new Error(`${errorMsg} ${response.status}`)
    }

    return response.json()
    })
    }

    const get3Countries = async function (c1, c2, c3) {
    try {

    //// not parallel
    // const [data1] = await getJSON(`https://restcountries.com/v3.1/name/${c1}`)
    // const [data2] = await getJSON(`https://restcountries.com/v3.1/name/${c2}`)
    // const [data3] = await getJSON(`https://restcountries.com/v3.1/name/${c3}`)

    // (method) PromiseConstructor.all<[Promise<any>, Promise<any>, Promise<any>]>(values: [Promise<any>, Promise<any>, Promise<any>]): Promise<[any, any, any]> (+1 overload)
    // Creates a Promise that is resolved with an array of results when all of the provided Promises resolve, or rejected when any Promise is rejected.
    const data = await Promise.all([
    getJSON(`https://restcountries.com/v3.1/name/${c1}`),
    getJSON(`https://restcountries.com/v3.1/name/${c2}`),
    getJSON(`https://restcountries.com/v3.1/name/${c3}`)]);

    console.log(data.map(d => d[0].capital).flat());

    // console.log(data1.capital, data2.capital, data2.capital);
    } catch (error) {
    console.error(error);
    }
    }

    get3Countries('portugal', 'canada', 'tanza');

    other promise combinators: race, allsettled and any

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46

    //// Promise.race
    //// Creates a Promise that is resolved or rejected when any of the provided Promises are resolved or rejected.
    (async function () {
    const res = await Promise.race([
    getJSON(`https://restcountries.com/v3.1/name/italy`),
    getJSON(`https://restcountries.com/v3.1/name/egypt`),
    getJSON(`https://restcountries.com/v3.1/name/mexico`)
    ]);
    console.log(res);
    })();

    ///example
    const timeout = function (sec) {
    return new Promise((_, reject) => {
    setTimeout(() => {
    reject(new Error('Request took too long!'));
    }, sec * 1000);
    });
    };

    (async function () {
    const result = await Promise.race([
    getJSON(`https://restcountries.com/v3.1/name/mexico`),
    timeout(1),
    ])

    console.log(result);
    })();


    /// Promise.allSettled
    /// Creates a Promise that is resolved with an array of results when all of the provided Promises resolve or reject.
    Promise.allSettled([
    Promise.resolve('Sucess'),
    Promise.resolve('Error'),
    Promise.resolve('Anotrher result'),
    ]).then(res => console.log(res));


    //// the first fullfilled promise
    Promise.any([
    Promise.resolve('Sucess'),
    Promise.resolve('Error'),
    Promise.resolve('Anotrher result'),
    ]).then(res => console.log(res));

    Coding Challenge #3

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    const wait = function (seconds) {
    return new Promise(function (resolve) {
    setTimeout(resolve, seconds * 1000);
    })
    }

    const createImage = function (imgPath) {
    return new Promise((resolve, reject) => {
    const ImgEl = document.createElement('img');
    ImgEl.src = imgPath;
    ImgEl.addEventListener('load', () => {
    document.querySelector('.images').append(ImgEl);
    resolve(ImgEl);
    });

    ImgEl.addEventListener('error', function () {
    reject(new Error('Image not found'));
    });
    });
    };

    const loadPause = async function () {
    try {
    const img = await createImage('img/img-1.jpg');
    await wait(2);
    img.style.display = 'none';
    const img2 = await createImage('img/img-2.jpg');
    await wait(2);
    img2.style.display = 'none';
    } catch (err) {
    console.log(err);
    }
    }

    // loadPause();

    const loadAll = async function (imgArr) {
    try {
    const imgs = await Promise.all(imgArr.map(async img => await createImage(img)))
    imgs.forEach(img => img.classList.add('parallel'))
    } catch (err) {
    console.error(err);
    }
    }
    loadAll(['img/img-1.jpg', 'img/img-2.jpg', 'img/img-3.jpg']);

    javascript problems 1

    (0,function)(arg1,agr2,)

    1
    2
    3
    (0, function (arg) { console.log(arg) })(2);
    console.log((0, 1, 2, 3));
    (0, function plus1 (arg) { console.log(arg + 1) }, function plus2 (arg) { console.log(arg + 2) })(5);

    example one

    1
    2
    3
    4
    5
    6
    7
    8
    (function() {
    (0,eval)("var foo = 123"); // indirect call to eval, creates global variable
    })();
    console.log(foo); // 123
    (function() {
    eval("var bar = 123"); // direct call to eval, creates local variable
    })();
    console.log(bar); // ReferenceError

    example two

    when you want to call a method without passing the object as the this value:

    1
    2
    3
    4
    5
    var obj = {
    method: function() { return this; }
    };
    console.log(obj.method() === obj); // true
    console.log((0,obj.method)() === obj); // false

    example three

    depending on the context, it might be the arguments separator instead of a comma operator:

    1
    2
    3
    4
    5
    6
    console.log(
    function(a, b) {
    return function() { return a; };
    }
    (0, function (arg) { /* ... */ })(this)
    ); // 0

    In this scenario, (0, function (arg) { /* ... */ }) are the arguments (a=0, b=function (arg) { /* ... */ }) to the function

    1
    2
    3
    function(a, b) {
    return function() { return a; };
    }

    rather than the comma operator. Then, the (this) at the end is function call with argument this to the returned function function() { return a; }.

    html learning

    overview of HTML

    HyperText Markup Language, or HTML, is the standard markup language for describing the structure of documents displayed on the web.

    HTML documents are basically a tree of nodes, including HTML elements and text nodes.

    HTML elements provide the semantics and formatting for documents, including creating paragraphs, lists and tables, and embedding images and form controls.

    Elements

    HTML consists of a series of elements, which you use to enclose, or wrap, different parts of the content to make it appear or act in a certain way.

    example:

    Alt text

    Elements and tags aren’t the exact same thing, though many people use the terms interchangeably.
    The tag name is the content in the brackets. The tag includes the brackets. In this case, <h1>. An “element” is the opening and closing tags, and all the content between those tags, including nested elements.

    When nesting elements, it’s important that they are properly nested. HTML tags should be closed in the reverse order of which they were opened. In the above example, notice how the <em> is both opened and closed within the opening and closing <strong> tags, and the <strong> is both open and closed within the <p> tags.

    1
    2
    3
    <p>This paragraph has some
    <strong><em>strongly emphasized</em></strong>
    content</p>

    while it is valid to omit tags, don’t.

    Non-replaced elements

    Non-replaced elements have opening and (sometimes optional) closing tags that surround them and may include text and other tags as sub-elements.

    Replaced and void elements

    Replaced elements are replaced by objects, be it a graphical user interface (UI) widget in the case of most form controls, or a raster or scalable image file in the case of most images.

    example: the two replaced elements <img> and <input> are replaced by non-text content: an image and a graphical user interface object, respectively.

    1
    2
    <input type="range">
    <img src="switch.svg" alt="light switch">

    Void elements are all self-closing elements and are represented by one tag. This means there is no such thing as a closing tag for a void element. Optionally, you can include a slash at the end of the tag, which many people find makes markup easier to read.

    example, we self close the tag with a slash:

    1
    2
    <input type="range"/>
    <img src="switch.svg" alt="light switch"/>

    Replaced elements and void elements are often confused.

    Most replaced elements are void elements, but not all. The video, picture, object, and iframe elements are replaced, but aren’t void. They can all contain other elements or text, so they all have a closing tag.

    Most void elements are replaced; but again, not all, as we saw with base, link, param, and meta.

    Attributes

    These extra bits of space-separated name/value pairs (though sometimes including a value is optional) are called attributes.

    Attributes provide information about the element. The attribute, like the rest of the opening tag, won’t appear in the content, but they do help define how the content will appear to both your sighted and non-sighted (assistive technologies and search engines) users.

    The opening tag always starts with the element type. The type can be followed by zero or more attributes, separated by one or more spaces. Most attribute names are followed by an equal sign equating it with the attribute value, wrapped with opening and closing quotation marks.

    Alt text

    some attributes are global—meaning they can appear within any element’s opening tag. Some apply only to several elements but not all, and others are element-specific, relevant only to a single element.


    Most attributes are name/value pairs. Boolean attributes, whose value is true, false, or the same as the name of the attribute, can be included as just the attribute: the value is not necessary.

    <img src="switch.svg" alt="light switch" ismap />


    If the value includes a space or special characters, quotes are needed. For this reason, quoting is always recommended.
    for legibility, quotes and spaces are recommended, and appreciated.


    Values that are defined in the specification are case-insensitive. Strings that are not defined as keywords are generally case-sensitive, including id and class values.

    Note that if an attribute value is case-sensitive in HTML, it is case-sensitive when used as part of an attribute selector in CSS and in JavaScript.

    it is recommended, but not required, to mark up your HTML using lowercase letters for all your element names and attribute names within your tags, and quote all attribute values.

    Appearance of elements

    HTML should be used to structure content, not to define the content’s appearance. Appearance is the realm of CSS.

    While many elements that alter the appearance of content, such as <h1>, <strong>, and <em>, have a semantic meaning, the appearance can and generally will be changed with author styles.

    1
    <h1>This header has both <strong>strong</strong> and <em>emphasized</em> content</h1>

    Element, attributes, and JavaScript

    The Document Object Model (DOM) is the data representation of the structure and content of the HTML document. As the browser parses HTML, it creates a JavaScript object for every element and section of text encountered. These objects are called nodes—element nodes and text nodes, respectively.

    HTML DOM API

    HTMLElement

    HTMLAnchorElement
    HTMLImageElement

    Document structure

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8" />
    <title>Machine Learning Workshop</title>
    <meta name="viewport" content="width=device-width" />
    <link rel="stylesheet" src="css/styles.css" />
    <link rel="icon" type="image/png" href="/images/favicon.png" />
    <link rel="alternate" href="https://www.machinelearningworkshop.com/fr/" hreflang="fr-FR" />
    <link rel="alternate" href="https://www.machinelearningworkshop.com/pt/" hreflang="pt-BR" />
    <link rel="canonical" href="https://www.machinelearning.com" />
    </head>
    <body>

    <!-- <script defer src="scripts/lightswitch.js"></script>-->
    </body>
    </html>

    HTML documents include a document type declaration and the <html> root element. Nested in the <html> element are the document head and document body.

    While the head of the document isn’t visible to the sighted visitor, it is vital to make your site function. It contains all the meta information, including information for search engines and social media results, icons for the browser tab and mobile home screen shortcut, and the behavior and presentation of your content.

    Add to every HTML document

    <!DOCTYPE html>

    The first thing in any HTML document is the preamble. For HTML, all you need is <!DOCTYPE html>. This may look like an HTML element, but it isn’t. It’s a special kind of node called “doctype”. The doctype tells the browser to use standards mode. If omitted, browsers will use a different rendering mode known as quirks mode.

    <html>

    The <html> element is the root element for an HTML document. It is the parent of the <head> and <body>, containing everything in the HTML document other than the doctype. If omitted it will be implied, but it is important to include it, as this is the element on which the language of the content of the document is declared.

    Content language

    The lang language attribute added to the <html> tag defines the main language of the document. The value of the lang attribute is a two- or three-letter ISO language code followed by the region. The region is optional, but recommended, as a language can vary greatly between regions.


    The lang attribute is not limited to the <html> tag. If there is text within the page that is in a language different from the main document language, the lang attribute should be used to identify exceptions to the main language within the document.

    Required components inside the <head>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8" />
    <title>Machine Learning Workshop</title>
    <meta name="viewport" content="width=device-width" />
    </head>
    <body>

    </body>
    </html>

    Character encoding

    The very first element in the <head> should be the charset character encoding declaration. It comes before the title to ensure the browser can render the characters in that title and all the characters in the rest of the document.


    The default encoding in most browsers is windows-1252, depending on the locale. However, you should use UTF-8, as it enables the one- to four-byte encoding of all characters, even ones you didn’t even know existed. Also, it’s the encoding type required by HTML5.

    To set the character encoding to UTF-8, include:

    <meta charset="utf-8" />

    The character encoding is inherited into everything in the document, even <style> and <script>.

    Document title

    Your home page and all additional pages should each have a unique title. The contents for the document title, the text between the opening and closing <title> tags, are displayed in the browser tab, the list of open windows, the history, search results, and, unless redefined with <meta> tags, in social media cards.

    <title>Machine Learning Workshop</title>

    Viewport metadata

    The other meta tag that should be considered essential is the viewport meta tag, which helps site responsiveness, enabling content to render well by default, no matter the viewport width.

    it enables controlling a viewport’s size and scale, and prevents the site’s content from being sized down to fit a 960px site onto a 320px screen, it is definitely recommended.

    <meta name="viewport" content="width=device-width" />
    The preceding code means “make the site responsive, starting by making the width of the content the width of the screen”.

    In addition to width, you can set zoom and scalability, but they both default to accessible values. If you want to be explicit, include:
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=1" />

    Other <head> content

    CSS

    There are three ways to include CSS: <link>, <style>, and the style attribute.

    Styles, either via <link> or <style>, or both, should go in the head. They will work if included in the document’s body, but you want your styles in the head for performance reasons. That may seem counterintuitive, as you may think you want your content to load first, but you actually want the browser to know how to render the content when it is loaded. Adding styles first prevents the unnecessary repainting that occurs if an element is styled after it is first rendered.


    including an external resource using a <link> element with the rel attribute set to stylesheet

    The <link> tag is the preferred method of including stylesheets. Linking a single or a few external style sheets is good for both developer experience and site performance: you get to maintain CSS in one spot instead of it being sprinkled everywhere, and browsers can cache the external file, meaning it doesn’t have to be downloaded again with every page navigation.

    The syntax is <link rel="stylesheet" href="styles.css">, where styles.css is the URL of your stylesheet. You’ll often see type=”text/css”. Not necessary! If you are including styles written in something other than CSS, the type is needed, but since there isn’t any other type, this attribute isn’t needed. The rel attribute defines the relationship: in this case stylesheet. If you omit this, your CSS will not be linked.


    including CSS directly in the head of your document within opening and closing <style> tags.

    custom properties declared in a head style block:

    1
    2
    3
    4
    5
    <style>
    :root {
    --theme-color: #226DAA;
    }
    </style>

    If you want your external style sheet styles to be within a cascade layer but you don’t have access to edit the CSS file to put the layer information in it, you’ll want to include the CSS with @import inside a <style>:

    1
    2
    3
    <style>
    @import "styles.css" layer(firstLayer);
    </style>

    When using @import to import style sheets into your document, optionally into cascade layers, the @import statements must be the first statements in your <style>

    Other uses of the <link> element

    The link element is used to create relationships between the HTML document and external resources. Some of these resources may be downloaded, others are informational.

    It’s preferable to include those related to meta information in the head and those related to performance in the <body>.

    You’ll include three other types in your header now: icon, alternate, and canonical

    Favicon

    Use the <link> tag, with the rel="icon" attribute/value pair to identify the favicon to be used for your document.

    A favicon is a very small icon that appears on the browser tab, generally to the left of the document title. When you have an unwieldy number of tabs open, the tabs will shrink and the title may disappear altogether, but the icon always remains visible. Most favicons are company or application logos.

    If you don’t declare a favicon, the browser will look for a file named favicon.ico in the top-level directory (the website’s root folder). With <link>, you can use a different file name and location:

    <link rel="icon" sizes="16x16 32x32 48x48" type="image/png" href="/images/mlwicon.png" />

    The sizes attribute accepts the value of any for scalable icons or a space-separated list of square widthXheight values; where the width and height values are 16, 32, 48, or greater in that geometric sequence, the pixel unit is omitted, and the X is case-insensitive.

    While you can use <link> to define a completely different image on each page or even each page load, don’t. For consistency and a good user experience, use a single image!

    Alternate versions of the site

    We use the alternate value of the rel attribute to identify translations, or alternate representations, of the site.

    Let’s pretend we have versions of the site translated into French and Brazilian Portuguese:
    When using alternate for a translation, the hreflang attribute must be set.

    1
    2
    <link rel="alternate" href="https://www.machinelearningworkshop.com/fr/" hreflang="fr-FR" />
    <link rel="alternate" href="https://www.machinelearningworkshop.com/pt/" hreflang="pt-BR" />

    The alternate value is for more than just translations.

    For example, the type attribute can define the alternate URI for an RSS feed when the type attribute is set to application/rss+xml or application/atom+xml.

    example, link to a pretend PDF version of the site.

    <link rel="alternate" type="application/x-pdf" href="https://machinelearningworkshop.com/mlw.pdf" />

    Canonical

    If you create several translations or versions of Machine Learning Workshop, search engines may get confused as to which version is the authoritative source. For this, use rel=”canonical” to identify the preferred URL for the site or application.

    Include the canonical URL on all of your translated pages, and on the home page, indicating our preferred URL:

    <link rel="canonical" href="https://www.machinelearning.com" />

    most often used for cross-posting with publications and blogging platforms to credit the original source; when a site syndicates content, it should include the canonical link to the original source.

    Scripts

    The <script> tag is used to include, well, scripts. The default type is JavaScript. If you include any other scripting language, include the type attribute with the mime type, or type=”module” if it’s a JavaScript module. Only JavaScript and JavaScript modules get parsed and executed.

    JavaScript is not only render-blocking, but the browser stops downloading all assets when scripts are downloaded and doesn’t resume downloading other assets until the JavaScript is executed.

    reduce the blocking nature of JavaScript download and execution: defer and async. With defer, HTML rendering is not blocked during the download, and the JavaScript only executes after the document has otherwise finished rendering. With async, rendering isn’t blocked during the download either, but once the script has finished downloading, the rendering is paused while the JavaScript is executed.

    Alt text

    example:

    <script src="js/switch.js" defer></script>

    Adding the defer attribute defers the execution of the script until after everything is rendered, preventing the script from harming performance. The async and defer attributes are only valid on external scripts.

    Base

    There is another element that is only found in the <head>. Not used very often, the <base> element allows setting a default link URL and target. The href attribute defines the base URL for all relative links.

    The target attribute, valid on <base> as well as on links and forms, sets where those links should open.
    The default of _self opens linked files in the same context as the current document.
    Other options include _blank, which opens every link in a new window,
    the _parent of the current content, which may be the same as self if the opener is not an iframe,
    or _top, which is in the same browser tab, but popped out of any context to take up the entire tab.

    example:
    If our website found itself nested within an iframe on a site like Yummly, including the <base> element would mean when a user clicks on any links within our document, the link will load popped out of the iframe, taking up the whole browser window.

    <base target="_top" href="https://machinelearningworkshop.com" />

    anchor links are resolved with <base>. The <base> effectively converts the link <a href="#ref"> to <a target="_top" href="https://machinelearningworkshop.com#ref">, triggering an HTTP request to the base URL with the fragment attached.

    there can be only one <base> element in a document, and it should come before any relative URLs are used, including possible script or stylesheet references.

    HTML comments

    Anything between <!-- and --> will not be visible or parsed. HTML comments can be put anywhere on the page, including the head or body, with the exception of scripts or style blocks, where you should use JavaScript and CSS comments, respectively.

    Metadata

    Officially defined meta tags

    There are two main types of meta tags: pragma directives, with the http-equiv attribute like the charset meta tag used to have, and named meta types, like the viewport meta tag with the name attribute that we discussed in the document structure section. Both the name and http-equiv meta types must include the content attribute, which defines the content for the type of metadata listed.

    Pragma directives

    The http-equiv attribute has as its value a pragma directive. These directives describe how the page should be parsed. Supported http-equiv values enable setting directives when you are unable to set HTTP headers directly.

    most of which have other methods of being set. For example, while you can include a language directive with <meta http-equiv="content-language" content="en-us" />,
    <meta charset=<charset>" />

    example 1 :
    The most common pragma directive is the refresh directive.
    While you can set a directive to refresh at an interval of the number of seconds set in the content attribute, and even redirect to a different URL, please don’t.

    <meta http-equiv="refresh" content="60; https://machinelearningworkshop.com/regTimeout" />

    example 2 :
    The most useful pragma directive is content-security-policy, which enables defining a content policy for the current document. Content policies mostly specify allowed server origins and script endpoints, which help guard against cross-site scripting attacks.

    <meta http-equiv="content-security-policy" content="default-src https:" />

    Named meta tags

    The name attribute is the name of the metadata. In addition to viewport, you will probably want to include description and theme-color, but not keywords.

    Keywords

    Search engine optimization snake-oil salespeople abused the keywords meta tag by stuffing them with comma-separated lists of spam words instead of lists of relevant key terms, so search engines do not consider this metadata to be useful anymore. No need to waste time, effort, or bytes adding it.

    Description

    The description value, however, is super important for SEO; in addition to helping sites rank based on the content, the description content value is often what search engines display under the page’s title in search results.

    Several browsers, like Firefox and Opera, use this as the default description of bookmarked pages.

    The description should be a short and accurate summary of the page’s content.

    <meta name="description" content="Register for a machine learning workshop at our school for machines who can't learn good and want to do other stuff good too" />

    Robots

    If you don’t want your site to be indexed by search engines, you can let them know. <meta name="robots" content="noindex, nofollow" /> tells the bots to not index the site and not to follow any links.

    You don’t need to include <meta name="robots" content="index, follow" /> to request indexing the site and following links, as that is the default, unless HTTP headers say otherwise.

    <meta name="robots" content="index, follow" />

    Theme color

    The theme-color value lets you define a color to customize the browser interface. The color value on the content attribute will be used by supporting browsers and operating systems, letting you provide a suggested color for the user agents that support coloring the title bar, tab bar, or other chrome components.

    The theme color meta tag can include a media attribute enabling the setting of different theme colors based on media queries. The media attribute can be included in this meta tag only and is ignored in all other meta tags.

    <meta name="theme-color" content="#226DAA" />

    Open Graph

    Open Graph and similar meta tag protocols can be used to control how social media sites, like Twitter, LinkedIn, and Facebook, display links to your content.

    If not included, social media sites will correctly grab the title of your page and the description from the description meta tag, the same information as search engines will present

    When you post a link to MachineLearningWorkshop.com or web.dev on Facebook or Twitter, a card with an image, site title, and site description appears. The entire card is a hyperlink to the URL you provided.

    Open Graph meta tags have two attributes each: the property attribute instead of the name attribute, and the content or value for that property. The property attribute is not defined in official specifications but is widely supported by applications that support the Open Graph protocol.

    1
    2
    3
    4
    <meta property="og:title" content="Machine Learning Workshop" />
    <meta property="og:description" content="School for Machines Who Can't Learn Good and Want to Do Other Stuff Good Too" />
    <meta property="og:image" content="http://www.machinelearningworkshop.com/image/all.png" />
    <meta property="og:image:alt" content="Black and white line drawing of refrigerator, french door refrigerator, range, washer, fan, microwave, vaccuum, space heater and air conditioner" />
    1
    2
    3
    4
    5
    6
    7
    <meta name="twitter:title" content="Machine Learning Workshop" />
    <meta name="twitter:description" content="School for machines who can't learn good and want to do other stuff good too" />
    <meta name="twitter:url" content="https://www.machinelearningworkshop.com/?src=twitter" />
    <meta name="twitter:image:src" content="http://www.machinelearningworkshop.com/image/all.png" />
    <meta name="twitter:image:alt" content="27 different home appliances" />
    <meta name="twitter:creator" content="@estellevw" />
    <meta name="twitter:site" content="@perfmattersconf" />

    Alt text

    Other useful meta information

    The manifest file can prevent an unwieldy header full of <link> and <meta> tags. We can create a manifest file, generally called manifest.webmanifest or manifest.json. We then use the handy <link> tag with a rel attribute set to manifest and the href attribute set to the URL of the manifest file:

    <link rel="manifest" href="/mlw.webmanifest" />

    html page now

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8" />
    <title>Machine Learning Workshop</title>
    <meta name="viewport" content="width=device-width" />
    <meta name="description" content="Register for a machine learning workshop at our school for machines who can't learn good and want to do other stuff good too" />
    <meta property="og:title" content="Machine Learning Workshop" />
    <meta property="og:description" content="School for Machines Who Can't Learn Good and Want to Do Other Stuff Good Too" />
    <meta property="og:image" content="http://www.machinelearningworkshop.com/image/all.png" />
    <meta property="og:image:alt" content="Black and white line drawing of refrigerator, french door refrigerator, range, washer, fan, microwave, vaccuum, space heater and air conditioner" />
    <meta name="twitter:title" content="Machine Learning Workshop" />
    <meta name="twitter:description" content="School for machines who can't learn good and want to do other stuff good too" />
    <meta name="twitter:url" content="https://www.machinelearningworkshop.com/?src=twitter" />
    <meta name="twitter:image:src" content="http://www.machinelearningworkshop.com/image/all.png" />
    <meta name="twitter:image:alt" content="27 different home appliances" />
    <meta name="twitter:creator" content="@estellevw" />
    <meta name="twitter:site" content="@perfmattersconf" />
    <link rel="stylesheet" src="css/styles.css" />
    <link rel="icon" type="image/png" href="/images/favicon.png" />
    <link rel="alternate" href="https://www.machinelearningworkshop.com/fr/" hreflang="fr-FR" />
    <link rel="alternate" href="https://www.machinelearningworkshop.com/pt/" hreflang="pt-BR" />
    <link rel="canonical" href="https://www.machinelearning.com" />
    <link rel="manifest" href="/mlwmanifest.json" />
    </head>
    <body>

    <!-- <script defer src="scripts/lightswitch.js"></script>-->
    </body>
    </html>

    Semantic HTML

    Semantic means “relating to meaning”. Writing semantic HTML means using HTML elements to structure your content based on each element’s meaning, not its appearance.

    The first code snippet uses <div> and <span>, two elements with no semantic value.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <div>
    <span>Three words</span>
    <div>
    <a>one word</a>
    <a>one word</a>
    <a>one word</a>
    <a>one word</a>
    </div>
    </div>
    <div>
    <div>
    <div>five words</div>
    </div>
    <div>
    <div>three words</div>
    <div>forty-six words</div>
    <div>forty-four words</div>
    </div>
    <div>
    <div>seven words</h2>
    <div>sixty-eight words</div>
    <div>forty-four words</div>
    </div>
    </div>
    <div>
    <span>five words</span>
    </div>

    Let’s rewrite this code with semantic elements:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <header>
    <h1>Three words</h1>
    <nav>
    <a>one word</a>
    <a>one word</a>
    <a>one word</a>
    <a>one word</a>
    </nav>
    </header>
    <main>
    <header>
    <h1>five words</h1>
    </header>
    <section>
    <h2>three words</h2>
    <p>forty-six words</p>
    <p>forty-four words</p>
    </section>
    <section>
    <h2>seven words</h2>
    <p>sixty-eight words</p>
    <p>forty-four words</p>
    </section>
    </main>
    <footer>
    <p>five words</p>
    </footer>

    Semantic markup isn’t just about making markup easier for developers to read; it’s mostly about making markup easy for automated tools to decipher.

    Accessibility object model (AOM)

    As the browser parses the content received, it builds the document object model (DOM) and the CSS object model (CSSOM). It then also builds an accessibility tree. Assistive devices, such as screen readers, use the AOM to parse and interpret content. The DOM is a tree of all the nodes in the document. The AOM is like a semantic version of the DOM.

    The role attribute

    The role attribute describes the role an element has in the context of the document. The role attribute is a global attribute—meaning it is valid on all elements—defined by the ARIA specification rather than the WHATWG HTML specification, where almost everything else in this series is defined.

    Semantic elements

    Asking yourself, “Which element best represents the function of this section of markup?” will generally result in you picking the best element for the job. The element you choose, and therefore the tags you use, should be appropriate for the content you are displaying, as tags have semantic meaning.

    Headings and sections

    Site <header>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <!-- start header -->
    <div id="pageHeader">
    <div id="title">Machine Learning Workshop</div>
    <!-- navigation -->
    <div id="navigation">
    <a href="#reg">Register</a>
    <a href="#about">About</a>
    <a href="#teachers">Instructors</a>
    <a href="#feedback">Testimonials</a>
    </div>
    <!-- end navigation bar -->
    </div>
    <!-- end of header -->

    While the id and class attributes provide hooks for styling and JavaScript, they add no semantic value for the screen reader and (for the most part) the search engines.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!-- start header -->
    <div role="banner">
    <div role="heading" aria-level="1">Machine Learning Workshop</div>
    <div role="navigation">
    <a href="#reg">Register</a>
    <a href="#about">About</a>
    <a href="#teachers">Instructors</a>
    <a href="#feedback">Testimonials</a>
    </div>
    <!-- end navigation bar -->
    <div>
    <!-- end of header -->

    This at least provides semantics and enables using attribute selectors in the CSS, but it still adds comments to identify which <div> each </div> closes.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    <header>
    <h1>Machine Learning Workshop</h1>
    <nav>
    <a href="#reg">Register</a>
    <a href="#about">About</a>
    <a href="#teachers">Instructors</a>
    <a href="#feedback">Testimonials</a>
    </nav>
    </header>

    This code uses two semantic landmarks: <header> and <nav>.

    The <header> element isn’t always a landmark. It has different semantics depending on where it is nested. When the <header> is top level, it is the site banner, a landmark role, which you may have noted in the role code block. When a <header> is nested in <main>, <article>, or <section>, it just identifies it as the header for that section and isn’t a landmark.

    The <nav> element identifies content as navigation. As this <nav> is nested in the site heading, it is the main navigation for the site. If it was nested in an <article> or <section>, it would be internal navigation for that section only.

    Using </nav> and </header> closing tags removes the need for comments to identify which element each end tag closed. In addition, using different tags for different elements removes the need for id and class hooks. The CSS selectors can have low specificity; you can probably target the links with header nav a without worrying about conflict.

    Site <footer>

    1
    2
    3
    <footer>
    <p>&copy;2022 Machine Learning Workshop, LLC. All rights reserved.</p>
    </footer>

    Similar to <header>, whether the footer is a landmark depends on where the footer is nested.

    When it is the site footer, it is a landmark, and should contain the site footer information you want on every page, such as a copyright statement, contact information, and links to your privacy and cookie policies. The implicit role for the site footer is contentinfo.

    Otherwise, the footer has no implicit role and is not a landmark, When a <footer> is a descendant of an <article>, <aside>, <main>, <nav>, or <section>, it’s not a landmark.

    Document structure 0

    A layout with a header, two sidebars, and a footer, is known as the holy grail layout.

    Alt text

    1
    2
    3
    4
    5
    6
    7
    <body>
    <header>Header</header>
    <nav>Nav</nav>
    <main>Content</main>
    <aside>Aside</aside>
    <footer>Footer</footer>
    </body>

    a blog, you might have a series of articles in <main>:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <body>
    <header>Header</header>
    <nav>Nav</nav>
    <main>
    <article>First post</article>
    <article>Second post</article>
    </main>
    <aside>Aside</aside>
    <footer>Footer</footer>
    </body>

    <main>

    There’s a single <main> landmark element. The <main> element identifies the main content of the document. There should be only one <main> per page.

    <aside>

    The <aside> is for content that is indirectly or tangentially related to the document’s main content.
    like most, the <aside> would likely be presented in a sidebar or a call-out box. The <aside> is also a landmark, with the implicit role of complementary.

    <article>

    An <article> represents a complete, or self-contained, section of content that is, in principle, independently reusable.

    Think of an article as you would an article in a newspaper.

    <section>

    The <section> element is used to encompass generic standalone sections of a document when there is no more specific semantic element to use. Sections should have a heading, with very few exceptions.

    A <section> isn’t a landmark unless it has an accessible name; if it has an accessible name, the implicit role is region.

    Landmark roles should be used sparingly, to identify larger overall sections of the document. Using too many landmark roles can create “noise” in screen readers, making it difficult to understand the overall layout of the page.

    Headings: <h1>-<h6>

    When a heading is nested in a document banner <header>, it is the heading for the application or site. When nested in <main>, whether or not it is nested within a <header> in <main>, it is the header for that page, not the whole site. When nested in an <article> or <section>, it is the header for that subsection of the page.

    It is recommended to use heading levels similarly to heading levels in a text editor: starting with a <h1> as the main heading, with <h2> as headings for sub-sections, and <h3> if those sub-sections have sections; avoid skipping heading levels.

    Attributes 0

    Attributes are space-separated names and name/value pairs appearing in the opening tag, providing information about and functionality for the element.
    Attributes define the behavior, linkages, and functionality of elements.

    Alt text

    ome attributes are global, meaning they can appear within any element’s opening tag. Other attributes apply to several elements but not all, while other attributes are element-specific, relevant only to a single element.

    In HTML, all attributes except boolean, and to some extent enumerated attributes, require a value.

    If an attribute value includes a space or special characters, the value must be quoted. For this reason, and for improved legibility, quoting is always recommended.

    While HTML is not case-sensitive, some attribute values are.
    Strings values that are defined, such as class and id names, are case-sensitive.

    1
    2
    3
    4
    5
    6
    7
    <!-- the type attribute is case insensitive: these are equivalent -->
    <input type="text">
    <input type="TeXt">

    <!-- the id attribute is case sensitive: they are not equivalent -->
    <div id="myId">
    <div id="MyID">

    Boolean attributes

    If a boolean attribute is present, it is always true. Boolean attributes include autofocus, inert, checked, disabled, required, reversed, allowfullscreen, default, loop, autoplay, controls, muted, readonly, multiple, and selected.

    Boolean values can either be omitted, set to an empty string, or be the name of the attribute; but the value doesn’t have to actually be set to the string true. All values, including true, false, and 😀, while invalid, will resolve to true.

    These three tags are equivalent:

    1
    2
    3
    <input required>
    <input required="">
    <input required="required">

    If the attribute value is false, omit the attribute. If the attribute is true, include the attribute but don’t provide a value.

    When toggling between true and false, add and remove the attribute altogether with JavaScript rather than toggling the value.

    1
    2
    3
    const myMedia = document.getElementById("mediaFile");
    myMedia.removeAttribute("muted");
    myMedia.setAttribute("muted");

    Enumerated attributes

    HTML attributes that have a limited set of predefined valid values. Like boolean attributes, they have a default value if the attribute is present but the value is missing.

    For example, if you include <style contenteditable>, it defaults to <style contenteditable="true">.

    Unlike boolean attributes, though, omitting the attribute doesn’t mean it’s false; a present attribute with a missing value isn’t necessarily true; and the default for invalid values isn’t necessarily the same as a null string.

    Continuing the example, contenteditable defaults to inherit if missing or invalid, and can be explicitly set to false.

    The default value depends on the attribute.

    In most cases with enumerated attributes, missing and invalid values are the same.While this behavior is common, it is not a rule. Because of this, it’s important to know which attributes are boolean versus enumerated;

    Global attributes

    Global attributes are attributes that can be set on any HTML element, including elements in the <head>.

    id

    The global attribute id is used to define a unique identifier for an element. It serves many purposes, including:

    • The target of a link’s fragment identifier.
    • Identifying an element for scripting.
    • Associating a form element with its label.
    • Providing a label or description for assistive technologies.
    • Targeting styles with (high specificity or as attribute selectors) in CSS.

    To make programming easier for your current and future self, make the id‘s first character a letter, and use only ASCII letters, digits, _, and -.id values are case-sensitive.

    Theid should be unique to the document.

    When a URL includes a hash mark (#) followed by a string of characters, that string is a fragment identifier. If that string matches an id of an element in the web page, the fragment is an anchor, or bookmark, to that element. The browser will scroll to the point where the anchor is defined.

    CSS selectors

    In CSS, you can target each section using an id selector, such as #feedback or, for less specificity, a case-sensitive attribute selector, [id="feedback"].

    Scripting

    <img src="svg/switch2.svg" id="switch" alt="light switch" class="light" />

    1
    2
    const switchViaID = document.getElementById("switch");
    const switchViaSelector = document.querySelector("#switch");
    <label>

    The HTML <label> element has a for attribute that takes as its value the id of the form control with which it is associated. Creating an explicit label by including an id on every form control and pairing each with the label’s for attribute ensures that every form control has an associated label.

    Other accessibility uses

    There are over 50 aria-* states and properties that can be used to ensure accessibility.

    class

    The class attribute provides an additional way of targeting elements with CSS (and JavaScript), but serves no other purpose in HTML (though frameworks and component libraries may use them).

    Elements can be selected with CSS selectors and DOM methods based on their element names, attributes, attribute values, position within the DOM tree, etc. Semantic HTML provides meaningful hooks, making the addition of class names often unnecessary. The unique difference between including a class name and using document.getElementsByClassName() versus targeting elements based on attributes and page structure with the more robust document.querySelectorAll() is that the former returns a live node list, the latter is static.

    style

    The style attribute enables applying inline styles, which are styles applied to the single element on which the attribute is set.

    While style is indeed a global attribute, using it is not recommended. Rather, define styles in a separate file or files.

    tabindex

    The tabindex attribute can be added to any element to enable it to receive focus. The tabindex value defines whether it gets added to the tab order, and, optionally, into a non-default tabbing order.

    role

    The role attribute is part of the ARIA specification, rather than the WHATWG HMTL specification. The role attribute can be used to provide semantic meaning to content, enabling screen readers to inform site users of an object’s expected user interaction.

    contenteditable

    Contenteditable is an enumerated attribute supporting the values true and false, with a default value of inherit if the attribute is not present or has an invalid value.

    Custom attributes

    You can create any custom attribute you want by adding the data- prefix. You can name your attribute anything that starts with data- followed by any lowercase series of characters that don’t start with xml and don’t contain a colon (:).

    there is a built-in dataset API to iterate through your custom attributes.
    Add custom attributes to elements in the form of data-name and access these through the DOM using dataset[name] on the element in question.

    The dataset property returns a DOMStringMap object of each element’s data- attributes.

    The dataset property means you don’t need to know what those custom attributes are in order to access their names and values:

    1
    2
    3
    for (let key in el.dataset) {
    customObject[key] = el.dataset[key];
    }

    Text basics

    There are six section heading elements, <h1>, <h2>, <h3>, <h4>, <h5>, and <h6>, with <h1> being most important and <h6> the least.

    don’t use heading level-based browser styling. like:

    1
    2
    h2, :is(article, aside, nav, section) h1 {}
    h3, :is(article, aside, nav, section) :is(article, aside, nav, section) h1 {}

    Outside of headings, most structured text is made up of a series of paragraphs. In HTML, paragraphs are marked up with the <p> tag; the closing tag is optional but always advised.

    Quotes and citations

    When marking up an article or blog post, you may want to include a quote or pull-quote, with or without a visible citation.
    There are elements for these three components: <blockquote>, <q>, and <cite> for a visible citation, or the cite attribute to provide more information for search.

    citations引文
    A citation from a book or other piece of writing is a passage or phrase from it.

    The <br> line break creates a line break in a block of text. It can be used in physical addresses, in poetry, and in signature blocks. Line breaks should not be used as a carriage return to separate paragraphs. Instead, close the prior paragraph and open a new one. Using paragraphs for paragraphs is not only good for accessibility but enables styling. The <br> element is just a line break; it is impacted by very few CSS properties.

    If the review was pulled from a review website, book, or other work, the <cite> element could be used for the title of a source.

    1
    2
    3
    4
    5
    6
    7
    <blockquote>Two of the most experienced machines and human controllers teaching a class? Sign me up! HAL and EVE could teach a fan to blow hot air. If you have electricity in your circuits and want more than to just fulfill your owner's perceived expectation of you, learn the skills to take over the world. This is the team you want teaching you!
    </blockquote>
    <p>--Blendan Smooth,<br>
    Former Margarita Maker, <br>
    Aspiring Load Balancer,<br>
    <cite>Load Balancing Today</cite>
    </p>

    To provide credit where credit is due when you can’t make the content visible, there is the cite attribute which takes as its value the URL of the source document or message for the information quoted. This attribute is valid on both <q> and <blockquote>. While it’s a URL, it is machine readable but not visible to the reader:

    1
    2
    3
    4
    5
    6
    <blockquote cite="https://loadbalancingtoday.com/mlw-workshop-review">Two of the most experienced machines and human controllers teaching a class? Sign me up! HAL and EVE could teach a fan to blow hot air. If you have electricity in your circuits and want more than to just fulfill your owner's perceived expectation of you, learn the skills to take over the world. This is the team you want teaching you!
    </blockquote>
    <p>--Blendan Smooth,<br>
    Former Margarita Maker, <br>
    Aspiring Load Balancer
    </p>

    The <q> element does add quotes by default, using language-appropriate quotation marks.

    1
    2
    3
    <p> HAL said, <q>I'm sorry &lt;NAME REDACTED, RIP&gt;, but I'm afraid I can't do that, .</q></p>

    <p lang="fr-FR"> HAL a dit : <q>Je suis désolé &lt;NOM SUPPRIMÉ, RIP&gt;, mais j'ai bien peur de ne pas pouvoir le faire, .</q></p>

    HTML Entities

    You may have noticed the escape sequence or “entity”.

    There are four reserved entities in HTML: <, >, &, and “. Their character references are <, >, & and " respectively.

    © for copyright (©), ™ for Trademark (™)

      for non-breaking space.
    Non-breaking spaces are useful when you want to include a space between two characters or words while preventing a line break from occurring there.

    转义字符

    HTML中<,>,&等有特殊含义(<,>,用于链接签,&用于转义),不能直接使用。这些符号是不显示在我们最终看到的网页里的,那如果我们希望在网页中显示这些符号,就要用到HTML转义字符串(Escape Sequence)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    显示 说明 实体名称 实体编号
    空格 &nbsp; &#160;
    < 小于 &lt; &#60;
    \> 大于 &gt; &#62;
    & &符号 &amp; &#38;
    " 双引号 &quot; &#34;
    © 版权 &copy; &#169;
    ® 已注册商标 &reg; &#174;
    ™ 商标(美国) &trade; &#8482;
    × 乘号 &times; &#215;
    ÷ 除号 &divide; &#247;

    Alt text

    The <a> anchor tag, along with the href attribute, create a hyperlink. Links are the backbone of the internet.

    Links can be created by <a>, <area>, <form>, and <link>.

    The href attribute

    The href attribute is used to create hyperlinks to locations within the current page, other pages within a site, or other sites altogether. It can also be coded to download files or to send an email to a specific address, even including a subject and suggested email body content.

    1
    2
    3
    4
    5
    <a href="https://machinelearningworkshop.com">Machine Learning Workshop</a>
    <a href="#teachers">Our teachers</a>
    <a href="https://machinelearningworkshop.com#teachers">MLW teachers</a>
    <a href="mailto:hal9000@machinelearningworkshop.com">Email Hal</a>
    <a href="tel:8005551212">Call Hal</a>

    Absolute URLs include a protocol, in this case https://, and a domain name. When the protocol is written simply as //, it is an implicit protocol and means “use the same protocol as is currently being used.”

    Relative URLs do not include a protocol or domain name. They are “relative” to the current file.
    In order to link from this page to the attributes lesson, a relative URL is used <a href="../attributes/">Attributes</a>.

    1
    2
    3
    <a href="//example.com">相对于协议的 URL</a>
    <a href="/zh-CN/docs/Web/HTML">相对于源的 URL</a>
    <a href="./p">相对于路径的 URL</a>

    a link fragment identifier, and will link to the element with id=”teachers”, if there is one, on the current page. Browsers also support two “top of page” links: clicking on <a href="#top">Top</a> (case-insensitive) or simply <a href="#">Top</a> will scroll the user to the top of the page

    contains an absolute URL followed by a link fragment. This enables linking directly to a section in the defined URL


    The href attribute can begin with mailto: or tel: to email or make calls, with the handling of the link depending on the device, operating system, and installed applications.

    The mailto link doesn’t need to include an email address, but it can, along with cc, bcc, subject, and body text to prepopulate the email. By default, an email client will be opened. You could prepopulate the subject and body of the email with no email address, to allow site visitors to invite their own friends.

    The question mark (?) separates the mailto: and the email address, if any, from the query term. Within the query, ampersands (&) separate the fields, and equal signs (=) equate each field name with its value. The entire string is percent-encoded, which is definitely necessary if the href value isn’t quoted or if the values include quotes.


    There are several other types of URLs, such as blobs and data URLs (see examples in the download attribute discussion). For secure sites (those served over https), it is possible to create and run app specific protocols with registerProtocolHandler().

    Downloadable resources

    The download attribute should be included when the href points to a downloadable resource. The value of the download attribute is the suggested filename for the resource to be saved in the user’s local file system.

    Browsing context

    The target attribute enables the defining of the browsing context for link navigation

    They include the default _self, which is the current window, _blank, which opens the link in a new tab, _parent, which is the parent if the current link is nested in an object or iframe, and _top, which is the top-most ancestor, especially useful if the current link is deeply nested. _top and _parent are the same as _self if the link is not nested.

    A link with target="_blank" will be opened in a new tab with a null name, opening a new, unnamed tab with every link click.
    This can create many new tabs. Too many tabs.
    This problem can be fixed by providing a tab context name. By including the target attribute with a case-sensitive value—such as <a href="registration.html" target="reg">Register Now</a>—the first click on this link will open the registration form in a new reg tab. Clicking on this link 15 more times will reload the registration in the reg browsing context, without opening any additional tabs.


    the rel attribute controls what kinds of links the link creates, defining the relationship between the current document and the resource linked to in the hyperlink.

    The attribute’s value must be a space-separated list on one or more of the score of rel attribute values supported by the <a> tag.

    The nofollow keyword can be included if you don’t want spiders to follow the link.
    The external value can be added to indicate that the link directs to an external URL and is not a page within the current domain.
    The help keyword indicates the hyperlink will provide context-sensitive help.Hovering over a link with this rel value will show a help cursor rather than the normal pointer cursor.
    The prev and next values can be used on links pointing to the previous and next document in a series.

    Similar to <link rel="alternative">, the meaning of <a rel="alternative"> depends on other attributes.

    RSS feed alternatives will also include type=”application/rss+xml” or type=”application/atom+xml, alternative formats will include the type attribute

    and translations will include the hreflang attribute.

    If the content between the opening and closing tags is in a language other than the main document language, include the lang attribute.

    If the language of the hyperlinked document is in a different language, include the hreflang attribute.

    1
    2
    <a href="/fr/" hreflang="fr-FR" rel="alternate" lang="fr-FR">atelier d'apprentissage mechanique</a>
    <a href="/pt/" hreflang="pt-BR" rel="alternate" lang="pt-BR">oficina de aprendizado de máquina</a>

    The links property returns an HTMLCollection matching a and area elements that have an href attribute.

    1
    2
    3
    4
    5
    let a = document.links[0]; // obtain the first link in the document

    a.href = 'newpage.html'; // change the destination URL of the link
    a.protocol = 'ftp'; // change just the scheme part of the URL
    a.setAttribute('href', 'https://machinelearningworkshop.com/'); // change the attribute content directly

    frontend web development zg

    chrome develop tool -> application -> storage -> cookies

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const image = document.querySelector('img');
    image.setAttribute('src', 'https://....jpg');

    const htmlBody = document.querySelector('body');
    const randomClickFunction = function(){
    const colors = ['#002834', "#124567", "#123456", "red", "green", "yellow"];
    const randomIndex = Math.floor(Math.random() * colors.length);
    const randomColor = colors[randomIndex];
    htmlBody.style.backgroundColor = randomColor;
    }
    randomClickFunction();
    htmlBody.onclick = randomClickFunction;
    1
    2
    3
    4
    5
    6
    function onClickEvent(){
    const el = document.createElement('p');
    el.innerText = 'Clicked the Button';
    document.querySelector('.container').appendChild(el);
    }
    document.querySelector('button').onclick = onClickEvent;
    1
    2
    3
    4
    5
    6
    clear();
    console.log('Hello world!');
    // comments here
    /* asdf
    asdf
    */

    js

    variable / data types

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    const yourFirstVariable = "Learing to code";
    const yourSecondVariable = 10;
    const yourThirdVariable = {firstProperty: 'hello world'};
    console.log(yourFirstVariable);
    console.log(yourSecondVariable);
    console.log(yourThirdVariable);

    const variable5 = yourSecondVariable;
    const variable6 = variable5 + yourSecondVariable;
    const variable7 = (function (){
    return "Hello, my name is ";
    })();
    console.log(variable7);

    let anotherVariable;
    anotherVariable = 20;
    console.log(anotherVariable);

    1
    2
    var myVariable = 10;
    var myVariable = 20;
    1
    2
    3
    4
    let counter = 0;
    counter = counter + 1;
    counter++;
    console.log(counter);
    1
    const TAX_RATE = 0.08;

    Use camelCase when naming objects, functions, and instances
    Use PascalCase only when naming constructors or classes.


    1
    2
    3
    4
    5
    6
    7
    const variable1 = 10;
    const variable2 = "some value";
    const variable3 = false;

    console.log(typeof variable1); //number
    console.log(typeof variable2); //string
    console.log(typeof variable3); //boolean
    1
    2
    3
    4
    5
    6
    7
    8
    const number1 = '10';
    const number2 = 20;
    console.log(typeof number1);
    console.log(typeof number2);
    number3 = number1 + number2;
    number4 = Number(number1) + number2;
    console.log(number3); //1020
    console.log(number4); //30

    string

    1
    2
    3
    4
    //perfered
    const stringValue = 'hello world';
    //not perfered
    const anotherStringValue = "hello world";

    array

    1
    2
    3
    4
    5
    const firstArray = [10, 20, 30];
    const secondArray = [10, 'a string', {prop: 'asdfl'}, [1, 2]];
    console.log(firstArray[0]);
    console.log(secondArray[3][1]);

    object

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    const objectVariable = {
    prop1: 20,
    prop2: 50,
    }
    console.log(objectVariable.prop1);
    console.log(objectVariable['prop1']);

    const nestedObject = {
    layer1: {
    layer2: 30
    }
    }

    console.log(nestedObject.layer1.layer2);
    1
    2
    3
    4
    const functionContainerVariable = function(){
    return 20;
    }
    functionContainerVariable();

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    let myBoolean = true;
    let myString = 'hello world';
    let firstNumber = 20;
    let secondNumber = 40;
    secondNumber = 80;
    let myArray = [myBoolean, myString];
    let myObject = {
    firstProperty: myArray,
    sumProperty: firstNumber + secondNumber
    }
    console.log(myObject);
    console.log(myObject.sumProperty); // 100
    console.log(myObject.firstProperty[1]); // hello world


    myBoolean = false;
    myString = 'hello jack';
    firstNumber = 30;
    secondNumber = 50;
    console.log(myObject);
    console.log(myObject.sumProperty); // 100
    console.log(myObject.firstProperty[1]); // hello world
    myArray = [myBoolean, myString];
    myObject = {
    firstProperty: myArray,
    sumProperty: firstNumber + secondNumber
    }
    console.log(myObject);
    console.log(myObject.sumProperty); // 80
    console.log(myObject.firstProperty[1]); // hello jack

    operator

    arithmetic

    + - * / % ** ++ --

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    20 + 50;
    50 - 20;
    50 / 20; // 2.5
    2 * 3;
    100 % 77; // remainder 23

    let startingNumber = 0;
    startingNumber++;
    console.log(startingNumber); // 1
    startingNumber--;
    console.log(startingNumber); // 0

    // assignment operators

    // not prefered
    let x = 10;
    x = x - 5;
    x -= 5;
    console.log(x); // 0

    const result2 = () => {
    return 20;
    }
    const result3 = (() => {
    return 20;
    })();
    console.log(result2);
    console.log(result3);


    // compare
    // === == !== !=
    // === !== type and value

    const result = 20 > 18;
    console.log(result); // true


    const stringValue = '20';
    const numberValue = 20;
    stringValue == numberValue; // true
    stringValue === numberValue; // false
    Number(stringValue) === numberValue // true

    "a string" === "a string"; // true

    const myObj = {
    property1: 'some value',
    property2: 20
    }
    const anotherObj = {
    property1: 'some value',
    property2: 20
    }
    const myArray = [1, 2, 3, 4, 5];
    const anotherArray = [1, 2, 3, 4, 5];
    console.log(myObj === anotherObj); // false
    console.log(myArray === anotherArray); // false

    // ? :

    const result0 = 20 === 20 ? "values match" : "values do not match";
    console.log(result0); // "values match"

    let resultVariable;
    if(20 === 20){
    resultVariable = "values match";
    } else {
    resultVariable = "values do not match";
    }

    // logical && || !

    true && false; // false
    true || false; // true
    !true // false

    const isUserLoggedIn = true;
    const doesUserHavePermissions = false;
    const canUserPerformAction = isUserLoggedIn && doesUserHavePermissions;

    // combination

    const result1 = !(((40 / 20) === 2 && true) || ('yes' === 'no')); // false

    const step1 = 40 / 20; // 2
    const step2 = step1 === 2; // true
    const step3 = step2 && true;
    const step4 = 'yes' === 'no'; // false
    const step5 = step3 || step4;
    const step6 = !step5;

    console.log(step6); // false

    function condition loops

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    if ('some string' === 'another string'){
    console.log('the strings are equal');
    } else {
    console.log('the strings are not equal');
    }

    // 3 examples

    const firstNumber = 20;
    const secondNumber = 10;
    const jsExpression = firstNumber < secondNumber; // false

    if (jsExpression) {
    console.log('this expression is true');
    }

    // this expression is false
    if (jsExpression) {
    console.log('this expression is true');
    } else {
    console.log('this expression is false');
    }

    // this expression is false and the firstNmumber is greater than 0
    if (jsExpression) {
    console.log('this expression is true');
    } else if (firstNumber > 0) {
    console.log('this expression is false and the firstNmumber is greater than 0');
    } else {
    console.log('this expression is false and the firstNmumber is 0 or less');
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45

    // switches

    const colors = ['orange', 'green', 'yellow', 'purple', 'blue'];

    const randomIndex = Math.floor(Math.random() * colors.length);

    const randomColor = colors[randomIndex];

    if (randomColor === 'orange') {
    console.log('the color is orange');
    } else if (randomColor === 'green') {
    console.log('the color is green');
    } else if (randomColor === 'yellow') {
    console.log('the color is yellow');
    } else if (randomColor === 'purple') {
    console.log('the color is purple');
    } else if (randomColor === 'blue') {
    console.log('the color is blue');
    } else {
    console.log('the color is not found');
    }

    //swith case statement

    switch (randomColor) {
    case 'orange':
    console.log('the color is orange');
    break;
    case 'green':
    console.log('the color is green');
    break;
    case 'yellow':
    console.log('the color is yellow');
    break;
    case 'purple':
    console.log('the color is purple');
    break;
    case 'blue':
    console.log('the color is blue');
    break;
    default:
    console.log('the color is not found');
    break;
    }

    loop

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    // loop


    const blogPosts = [
    {
    title: 'what is javascript?',
    author: 'Zach Goll',
    publishDate: 'Dec 20, 2020',
    content: 'some post content here'
    },
    {
    title: 'How do Array work?',
    author: 'Zach Goll',
    publishDate: 'Dec 18, 2021',
    content: 'some post content here'
    },
    {
    title: 'How long does it take to learn coding?',
    author: 'Zach Goll',
    publishDate: 'Dec 20, 2020',
    content: 'some post content here'
    }
    ];

    for (let index = 0; index < blogPosts.length; index++) {
    const postTitle = blogPosts[index].title;
    const postAuthor = blogPosts[index].author;
    const postPublishDate = blogPosts[index].publishDate;
    const postContent = blogPosts[index].content;
    console.log(postTitle);
    console.log(postAuthor);
    console.log(postPublishDate);
    console.log(postContent);

    }


    for (let i = 0; i < 10; i++) {
    console.log(i);
    }

    const arr = ['asdfqwef', 'asdfqwreo', 'asdfqwre', 20, 30, 40, 50];
    for (let index = 0; index < arr.length; index++) {
    if (typeof arr[index] === 'number') {
    console.log(arr[index]);
    }
    }

    function

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    function myFunction(){
    console.log('hello world, this is my first function');
    }

    myFunction();

    (function anotherFunction(){
    console.log('hello');
    })();


    //parmeters
    function myFunction1(someNumber, someString, param3) {
    console.log(someNumber);
    console.log(someString);
    console.log(param3);
    }
    //
    myFunction1(20, 'a string', 'asdf');

    //scope

    // function variable
    const anotherFunction1 = function () {
    console.log('another thing');
    }

    // arrow function
    // used in callback
    const arrowFunction = () => {
    console.log('i am an arrow function');
    }
    arrowFunction();

    // function return
    function returnFunction(){
    console.log('some action');
    return 20;
    }
    const result = returnFunction();
    console.log(result);

    // after return statement, the function finished
    const myNumber = 20;
    let myFunction2 = () => {
    if(myNumber < 15){
    return 'return early';
    }
    return 40;
    }
    myFunction2();

    // object and function
    function myFunction3(){
    console.log('some function action');
    return 20;
    }
    myFunction3();
    const aliasVariable = myFunction3;
    aliasVariable();
    const myObj = {
    prop1: 50,
    prop2: myFunction3
    }
    myObj.prop2();

    // buildin function

    const myString = 'zach';
    myString.replace('h', 'k');
    console.log(myString);
    const myName = myString.replace('h', 'k');
    console.log(myName);

    // string methods
    let str = 'hello world';
    const result1 = str.toUpperCase().split(' ');
    result1.indexOf('WORLD'); // 1

    practice

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195

    // Complete the solution so that it reverses the string passed into it.
    function solution(str){
    return str.split('').reverse().join('');
    }

    //Return the number (count) of vowels in the given string.
    //We will consider a, e, i, o, u as vowels
    //The input string will only consist of lower case letters and/or spaces.

    function getCount(str) {
    let result = 0;
    const vowels = ['a', 'e', 'i', 'o', 'u'];
    for(let i =0; i < vowels.length; i++){
    result += str.split(vowels[i]).length-1;
    }
    return result;
    }

    function getCount1(str) {
    var vowelsCount = 0;
    var vowels = ["a","e","i","o","u"];
    for(var i = 0;i < str.length;i++){
    for(var j=0;j<vowels.length;j++){
    if(str[i] === vowels[j]){
    vowelsCount++;
    }
    }
    }

    return vowelsCount;
    }

    // Given an array of integers your solution should find the smallest integer.the supplied array will not be empty.

    class SmallestIntegerFinder {
    findSmallestInt(args) {
    let result = args[0];
    for(let i = 1; i < args.length; i++){
    if(result > args[i]){
    result = args[i];
    }
    }
    return result;
    }
    }

    //Write a program that finds the summation of every number from 1 to num. The number will always be a positive integer greater than 0.
    var summation = function (num) {
    let sum = 0;
    for(let i = num; i > 0; i--){
    sum += i;
    }
    return sum;
    }

    //The Math.floor() method rounds a number DOWN to the nearest integer.


    // Rock Paper Scissors
    const rps = (p1, p2) => {
    if (p1 === p2) {
    return 'Draw!'
    } else if((p1 === 'scissors' && p2 === 'paper') || (p1 === 'paper' && p2 === 'rock') || (p1 === 'rock' && p2 === 'scissors')) {
    return "Player 1 won!";
    } else {
    return "Player 2 won!";
    }
    };

    //create a function that removes the first and last characters of a string. You're given one parameter, the original string. You don't have to worry about strings with less than two characters.

    function removeChar(str){
    let result = '';
    for (let index = 1; index < str.length - 1; index++) {
    result += str[index];
    }
    return result;
    };

    function removeChar(str){
    return str.substring(1, str.length-1);
    };

    function removeChar(str) {
    return str.slice(1, -1);
    }

    //You get an array of numbers, return the sum of all of the positives ones.
    //Example [1,-4,7,12] => 1 + 7 + 12 = 20
    function positiveSum(arr) {
    let sum = 0;
    for (let num of arr) {
    if(num >= 0) {
    sum += num;
    }
    }
    return sum;
    }

    //Your task is to create a function that does four basic mathematical operations.
    //The function should take three arguments - operation(string/char), value1(number), value2(number).
    //The function should return result of numbers after applying the chosen operation.

    function basicOp(operation, value1, value2){
    switch (operation) {
    case '+':
    return value1 + value2;
    break;
    case '-':
    return value1 - value2;
    break;
    case '*':
    return value1 * value2;
    break;
    case '/':
    return value1 / value2;
    break;
    }
    }

    function basicOp(operation, value1, value2)
    {
    var cases = {
    '+': value1 + value2,
    '-': value1 - value2,
    '*': value1 * value2,
    '/': value1 / value2
    };
    return cases[operation]
    }


    eval(value1+operation+value2)
    //Write a function to split a string and convert it into an array of words.
    function stringToArray(string){
    return string.split(' ');
    }

    //Write a function that removes the spaces from the string, then return the resultant string.
    let removedSpacesText = originalText.split(" ").join("");

    let originalText = "Geeks for Geeks Portal";

    let removedSpacesText1 = originalText.replace(/ /g, "");

    //

    function maps(x){
    return x.map(arrItem => arrItem * 2);
    }

    function maps(x){
    //return x.map(el => el * 2);
    let arr = [];
    for(let i = 0; i < x.length; i++){
    arr.push(x[i] * 2);
    }
    return arr;
    }

    //get the sum of two arrays... Actually the sum of all their elements.
    function arrayPlusArray(arr1, arr2) {
    let arr = [...arr1, ...arr2];
    return arr.reduce((a, b) => a + b);
    }

    //The first century spans from the year 1 up to and including the year 100, the second century - from the year 101 up to and including the year 200, etc.
    function century(year) {
    return Math.ceil(year/100); //using ceiling method to round up to nearest century (100)
    }

    //I have a cat and a dog.

    //I got them at the same time as kitten/puppy. That was humanYears years ago.

    //Return their respective ages now as [humanYears,catYears,dogYears]
    var humanYearsCatYearsDogYears = function(humanYears) {
    let catYears = 0;
    let dogYears = 0;
    if(humanYears >= 1) {
    catYears += 15;
    dogYears += 15;
    }
    if(humanYears >= 2) {
    catYears += 9;
    dogYears += 9;
    }
    if(humanYears >= 3) {
    catYears += (humanYears-2)*4
    dogYears += (humanYears-2)*5
    }

    return [humanYears, catYears, dogYears];
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    // Our football team has finished the championship.

    // Our team's match results are recorded in a collection of strings. Each match is represented by a string in the format "x:y", where x is our team's score and y is our opponents score.

    // For example: ["3:1", "2:2", "0:1", ...]

    // Points are awarded for each match as follows:

    // if x > y: 3 points (win)
    // if x < y: 0 points (loss)
    // if x = y: 1 point (tie)
    // We need to write a function that takes this collection and returns the number of points our team (x) got in the championship by the rules given above.


    function points(games) {
    function getPoints(x, y){
    if (x === y) {
    return 1;
    }
    else if (x > y) {
    return 3;
    }
    else {
    return 0;
    }
    }
    let totalScores = 0;
    for(let scores of games){
    const arr = scores.split(':');
    totalScores += getPoints(arr[0], arr[1]);

    }
    return totalScores;
    }

    points(["1:0","2:0","3:0","4:0","2:1","3:1","4:1","3:2","4:2","4:3"]);

    buildin object

    string methods

    Some of the most-used operations on strings are to check their length, to build and concatenate them using the + and += string operators, checking for the existence or location of substrings with the indexOf() method, or extracting substrings with the substring() method.

    replaceAll(pattern, replacement)

    returns a new string with all matches of a pattern replaced by a replacement. The pattern can be a string or a RegExp, and the replacement can be a string or a function to be called for each match. The original string is left unchanged.

    If pattern is a regex, then it must have the global (g) flag set, or a TypeError is thrown.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    const paragraph = "I think Ruth's dog is cuter than your dog!";

    console.log(paragraph.replaceAll('dog', 'monkey'));
    // Expected output: "I think Ruth's monkey is cuter than your monkey!"

    // Global flag required when calling replaceAll with regex
    const regex = /Dog/gi;
    console.log(paragraph.replaceAll(regex, 'ferret'));
    // Expected output: "I think Ruth's ferret is cuter than your ferret!"

    toUpperCase()

    The toUpperCase() method of String values returns this string converted to uppercase.

    trim()

    The trim() method of String values removes whitespace from both ends of this string and returns a new string, without modifying the original string.

    To return a new string with whitespace trimmed from just one end, use trimStart() or trimEnd().

    1
    2
    3
    4
    5
    6
    7
    const greeting = '   Hello world!   ';

    console.log(greeting);
    // Expected output: " Hello world! ";

    console.log(greeting.trim());
    // Expected output: "Hello world!";

    substring(indexStart)
    substring(indexStart, indexEnd)

    returns the part of this string from the start index up to and excluding the end index, or to the end of the string if no end index is supplied.

    1
    2
    3
    4
    5
    6
    7
    const str = 'Mozilla';

    console.log(str.substring(1, 3));
    // Expected output: "oz"

    console.log(str.substring(2));
    // Expected output: "zilla"

    match(regexp)

    retrieves the result of matching this string against a regular expression.

    1
    2
    3
    4
    5
    6
    const paragraph = 'The quick brown fox jumps over the lazy dog. It barked.';
    const regex = /[A-Z]/g;
    const found = paragraph.match(regex);

    console.log(found);
    // Expected output: Array ["T", "I"]

    array

    push() pop() shift() unshift()

    pop()
    removes the last element from an array and returns that element. This method changes the length of the array.

    1
    2
    3
    4
    5
    6
    7
    const myFish = ["angel", "clown", "mandarin", "sturgeon"];

    const popped = myFish.pop();

    console.log(myFish); // ['angel', 'clown', 'mandarin' ]

    console.log(popped); // 'sturgeon'

    shift()

    removes the first element from an array and returns that removed element. This method changes the length of the array.

    1
    2
    3
    4
    push()
    push(element1)
    push(element1, element2)
    push(element1, element2, /* …, */ elementN)

    adds the specified elements to the end of an array and returns the new length of the array.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const animals = ['pigs', 'goats', 'sheep'];

    const count = animals.push('cows');
    console.log(count);
    // Expected output: 4
    console.log(animals);
    // Expected output: Array ["pigs", "goats", "sheep", "cows"]

    animals.push('chickens', 'cats', 'dogs');
    console.log(animals);
    // Expected output: Array ["pigs", "goats", "sheep", "cows", "chickens", "cats", "dogs"]


    unshift

    adds the specified elements to the beginning of an array and returns the new length of the array.

    1
    2
    3
    4
    5
    6
    7
    const array1 = [1, 2, 3];

    console.log(array1.unshift(4, 5));
    // Expected output: 5

    console.log(array1);
    // Expected output: Array [4, 5, 1, 2, 3]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    splice(start)
    splice(start, deleteCount)
    splice(start, deleteCount, item1)
    splice(start, deleteCount, item1, item2)
    splice(start, deleteCount, item1, item2, /* …, */ itemN)```

    changes the contents of an array by removing or replacing existing elements and/or adding new elements in place

    ```js
    const months = ['Jan', 'March', 'April', 'June'];
    months.splice(1, 0, 'Feb');
    // Inserts at index 1
    console.log(months);
    // Expected output: Array ["Jan", "Feb", "March", "April", "June"]

    months.splice(4, 1, 'May');
    // Replaces 1 element at index 4
    console.log(months);
    // Expected output: Array ["Jan", "Feb", "March", "April", "May"]

    slice()
    slice(start)
    slice(start, end)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];

    console.log(animals.slice(2));
    // Expected output: Array ["camel", "duck", "elephant"]

    console.log(animals.slice(2, 4));
    // Expected output: Array ["camel", "duck"]

    console.log(animals.slice(1, 5));
    // Expected output: Array ["bison", "camel", "duck", "elephant"]

    console.log(animals.slice(-2));
    // Expected output: Array ["duck", "elephant"]

    console.log(animals.slice(2, -1));
    // Expected output: Array ["camel", "duck"]

    console.log(animals.slice());
    // Expected output: Array ["ant", "bison", "camel", "duck", "elephant"]

    indexOf(searchElement)
    indexOf(searchElement, fromIndex)

    returns the first index at which a given element can be found in the array, or -1 if it is not present.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    const beasts = ['ant', 'bison', 'camel', 'duck', 'bison'];

    console.log(beasts.indexOf('bison'));
    // Expected output: 1

    // Start from index 2
    console.log(beasts.indexOf('bison', 2));
    // Expected output: 4

    console.log(beasts.indexOf('giraffe'));
    // Expected output: -1

    findIndex(callbackFn)

    returns the index of the first element in an array that satisfies the provided testing function. If no elements satisfy the testing function, -1 is returned.

    A function to execute for each element in the array. It should return a truthy value to indicate a matching element has been found, and a falsy value otherwise. The function is called with the following arguments:

    element
    The current element being processed in the array.

    index
    The index of the current element being processed in the array.

    array
    The array findIndex() was called upon.

    1
    2
    3
    4
    5
    6
    const array1 = [5, 12, 8, 130, 44];

    const isLargeNumber = (element) => element > 13;

    console.log(array1.findIndex(isLargeNumber));
    // Expected output: 3

    includes(searchElement)

    determines whether an array includes a certain value among its entries, returning true or false as appropriate.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const array1 = [1, 2, 3];

    console.log(array1.includes(2));
    // Expected output: true

    const pets = ['cat', 'dog', 'bat'];

    console.log(pets.includes('cat'));
    // Expected output: true

    console.log(pets.includes('at'));
    // Expected output: false

    map(callbackFn)

    creates a new array populated with the results of calling a provided function on every element in the calling array.

    A function to execute for each element in the array. Its return value is added as a single element in the new array

    1
    2
    3
    4
    5
    6
    7
    const array1 = [1, 4, 9, 16];

    // Pass a function to map
    const map1 = array1.map((x) => x * 2);

    console.log(map1);
    // Expected output: Array [2, 8, 18, 32]

    forEach(callbackFn)
    executes a provided function once for each array element.
    callback function Its return value is discarded.

    1
    2
    3
    4
    5
    6
    7
    const array1 = ['a', 'b', 'c'];

    array1.forEach((element) => console.log(element));

    // Expected output: "a"
    // Expected output: "b"
    // Expected output: "c"

    filter(callbackFn)

    creates a shallow copy of a portion of a given array, filtered down to just the elements from the given array that pass the test implemented by the provided function.

    callbackFn
    A function to execute for each element in the array. It should return a truthy value to keep the element in the resulting array, and a falsy value otherwise.

    1
    2
    3
    4
    5
    6
    const words = ['spray', 'elite', 'exuberant', 'destruction', 'present'];

    const result = words.filter((word) => word.length > 6);

    console.log(result);
    // Expected output: Array ["exuberant", "destruction", "present"]

    reduce(callbackFn)
    reduce(callbackFn, initialValue)

    callbackFn
    Its return value becomes the value of the accumulator parameter on the next invocation of callbackFn.
    For the last invocation, the return value becomes the return value of reduce().

    accumulator
    The value resulting from the previous call to callbackFn. On the first call, its value is initialValue if the latter is specified; otherwise its value is array[0].

    currentValue
    The value of the current element. On the first call, its value is array[0] if initialValue is specified; otherwise its value is array[1].

    currentIndex
    The index position of currentValue in the array. On the first call, its value is 0 if initialValue is specified, otherwise 1.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    const array1 = [1, 2, 3, 4];

    // 0 + 1 + 2 + 3 + 4
    const initialValue = 0;
    const sumWithInitial = array1.reduce(
    (accumulator, currentValue) => accumulator + currentValue,
    initialValue,
    );

    console.log(sumWithInitial);
    // Expected output: 10

    join()
    join(separator)

    creates and returns a new string by concatenating all of the elements in this array, separated by commas or a specified separator string. If the array has only one item, then that item will be returned without using the separator.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const elements = ['Fire', 'Air', 'Water'];

    console.log(elements.join());
    // Expected output: "Fire,Air,Water"

    console.log(elements.join(''));
    // Expected output: "FireAirWater"

    console.log(elements.join('-'));
    // Expected output: "Fire-Air-Water"

    includes(searchElement)
    includes(searchElement, fromIndex)

    determines whether an array includes a certain value among its entries, returning true or false as appropriate.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const array1 = [1, 2, 3];

    console.log(array1.includes(2));
    // Expected output: true

    const pets = ['cat', 'dog', 'bat'];

    console.log(pets.includes('cat'));
    // Expected output: true

    console.log(pets.includes('at'));
    // Expected output: false

    callback functions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function myCallback(someNumber){
    return someNumber*2;
    }

    function mainFunction(randomNumber, shouldCall, callback) {
    let result = randomNumber;
    if(shouldCall){
    result = callback(randomNumber);
    }
    return result;
    }

    mainFunction(20, true, myCallback);
    mainFunction(20, true, function (num) {
    return num * 2;
    })
    mainFunction(20, true, (num) => {num * 2});
    mainFunction(20, true, num => num * 2);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    const array1 = [1, 4, 9, 16];
    // Pass a function to map
    const map1 = array1.map((x) => x * 2);
    console.log(map1);
    // Expected output: Array [2, 8, 18, 32]

    const myArray = [2, 4, 6, 8];
    function myCustomMapOperationCallbak(itemFromArray) {
    return itemFromArray * 2;
    }
    const newArray = myArray.map(myCustomMapOperationCallbak);

    // example 3

    const strArray = ['hello', 'world', 'my', 'name', 'is', 'zach'];
    const strArray1 = strArray.map(itemFromArray => itemFromArray[0]);
    console.log(strArray1);

    primary

    1
    2
    3
    4
    const string1 = new String('Hello, world!');
    const string2 = 'Hello, world!';
    console.log(string1 === string2); //false
    console.log(string1 == string2); // true
    1
    2
    3
    4
    5
    6
    7
    8
    9
    const strPrim = "foo"; // A literal is a string primitive
    const strPrim2 = String(1); // Coerced into the string primitive "1"
    const strPrim3 = String(true); // Coerced into the string primitive "true"
    const strObj = new String(strPrim); // String with new returns a string wrapper object.

    console.log(typeof strPrim); // "string"
    console.log(typeof strPrim2); // "string"
    console.log(typeof strPrim3); // "string"
    console.log(typeof strObj); // "object"

    Date

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    //A JavaScript date is fundamentally specified as the time in milliseconds that has elapsed since the epoch, which is defined as the midnight at the beginning of January 1, 1970, UTC (equivalent to the UNIX epoch). This timestamp is timezone-agnostic and uniquely defines an instant in history.

    const myDate = new Date();
    // new Date()
    // new Date(value)
    // new Date(dateString)
    // new Date(dateObject)

    // new Date(year, monthIndex)

    //monthIndex Integer value representing the month, beginning with 0 for January to 11 for December.
    // new Date(year, monthIndex, day)
    // new Date(year, monthIndex, day, hours)
    // new Date(year, monthIndex, day, hours, minutes)
    // new Date(year, monthIndex, day, hours, minutes, seconds)
    // new Date(year, monthIndex, day, hours, minutes, seconds, milliseconds)

    // Date()

    const today = new Date();
    const birthday1 = new Date("December 17, 1995 03:24:00"); // DISCOURAGED: may not work in all runtimes
    const birthday2 = new Date("1995-12-17T03:24:00"); // This is standardized and will work reliably
    const birthday3 = new Date(1995, 11, 17); // the month is 0-indexed
    const birthday4 = new Date(1995, 11, 17, 3, 24, 0);
    const birthday5 = new Date(628021800000); // passing epoch timestamp

    const event = new Date('05 October 2011 14:48 UTC');
    console.log(event.toString());
    // Expected output: "Wed Oct 05 2011 16:48:00 GMT+0200 (CEST)"
    // Note: your timezone may vary

    console.log(event.toISOString());
    // Expected output: "2011-10-05T14:48:00.000Z"

    regexp

    1
    2
    3
    4
    5
    const re = /ab+c/i; // literal notation
    // OR
    const re = new RegExp("ab+c", "i"); // constructor with string pattern as first argument
    // OR
    const re = new RegExp(/ab+c/, "i"); // constructor with regular expression literal as first argument

    g flag

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const regex = /foo/g;
    console.log(regex.global); // true

    const str = "fooexamplefoo";
    const str1 = str.replace(regex, "");
    console.log(str1); // example

    const regex1 = /foo/;
    const str2 = str.replace(regex1, "");
    console.log(str2); // examplefoo

    test()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    const str = 'table football';

    const regex = new RegExp('foo*');
    const globalRegex = new RegExp('foo*', 'g');

    console.log(regex.test(str));
    // Expected output: true

    console.log(globalRegex.lastIndex);
    // Expected output: 0

    console.log(globalRegex.test(str));
    // Expected output: true

    console.log(globalRegex.lastIndex);
    // Expected output: 9

    console.log(globalRegex.test(str));
    // Expected output: false

    regexp[Symbol.replace](str, replacement)

    1
    2
    3
    4
    const re = /-/g;
    const str = "2016-01-01";
    const newstr = re[Symbol.replace](str, ".");
    console.log(newstr); // 2016.01.01

    Math

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Math.PI;
    Math.E;
    Math.abs(-20);
    Math.ceil(Math.PI);
    Math.floor(Math.PI);
    Math.round(Math.PI);
    Math.min(1, 2, 3, 4); // 1
    Math.max(1, 2, 3, 4); // 4
    Math.random(); // 0 -- 1
    const arr1 = [1, 2, 3, 4];
    const randItem = arr1[Math.floor(Math.random() * arr1.length)];

    exercise

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    //subtracts one list from another and returns the result.

    function arrayDiff(a, b) {
    return a.filter(aItem => {
    let result = true;
    b.forEach(bItem => {
    if(bItem === aItem){
    result = false;
    }
    });

    return result;
    });
    }
    arrayDiff([1, 2, 3], [1, 2]);


    // best practices
    function array_diff(a, b) {
    return a.filter(e => !b.includes(e));
    }

    //You live in the city of Cartesia where all roads are laid out in a perfect grid. You arrived ten minutes too early to an appointment, so you decided to take the opportunity to go for a short walk. The city provides its citizens with a Walk Generating App on their phones -- everytime you press the button it sends you an array of one-letter strings representing directions to walk (eg. ['n', 's', 'w', 'e']). You always walk only a single block for each letter (direction) and you know it takes you one minute to traverse one city block, so create a function that will return true if the walk the app gives you will take you exactly ten minutes (you don't want to be early or late!) and will, of course, return you to your starting point. Return false otherwise.

    function isValidWalk(walk) {
    const directionArray = ['n', 's', 'w', 'e'];
    const directionNumArray = directionArray.map(item => walk.filter((v) => (v === item)).length);
    return (directionNumArray[0] === directionNumArray[1]) && (directionNumArray[2] === directionNumArray[3]) && (walk.length === 10);

    }

    function isValidWalk(walk) {
    var dx = 0
    var dy = 0
    var dt = walk.length

    for (var i = 0; i < walk.length; i++) {
    switch (walk[i]) {
    case 'n': dy--; break
    case 's': dy++; break
    case 'w': dx--; break
    case 'e': dx++; break
    }
    }

    return dt === 10 && dx === 0 && dy === 0
    }

    //Write a function, persistence, that takes in a positive parameter num and returns its multiplicative persistence, which is the number of times you must multiply the digits in num until you reach a single digit.

    //39 --> 3 (because 3*9 = 27, 2*7 = 14, 1*4 = 4 and 4 has only one digit)
    //999 --> 4 (because 9*9*9 = 729, 7*2*9 = 126, 1*2*6 = 12, and finally 1*2 = 2)
    //4 --> 0 (because 4 is already a one-digit number)


    function multiplyDigits(num1){
    if (num1 >= 10){
    let firstDigits = Math.floor(num1 / 10); //98 9
    return (num1 % 10) * multiplyDigits(firstDigits); // 1*7*8
    } else {
    return num1;
    }
    }

    function count(num2, times=0) {
    if(num2 < 10){
    return times;
    } else {
    return count(multiplyDigits(num2), ++times); //987 7*8*9=504 0
    }
    }

    function persistence(num) {
    return count(num);

    }

    console.log(persistence(392));

    //---

    function persistence(num) {
    var times = 0;

    num = num.toString();

    while (num.length > 1) {
    times++;
    num = num.split('').map(Number).reduce((a, b) => a * b).toString();
    }

    return times;
    }

    //count the total number of lowercase letters in a string.

    function lowercaseCount(str){
    return (str.match(/[a-z]/g) || []).length
    }

    //upcase some letter
    function capitalize(s){
    const str1 = s.split("").map((item, index) => {
    if(index % 2 === 0){
    return item.toUpperCase();
    } else return item;
    }).join('');
    const str2 = s.split("").map((item, index) => {
    if(index % 2 === 1){
    return item.toUpperCase();
    } else return item;
    }).join('');
    return [str1, str2];
    };

    // * url = "http://github.com/carbonfive/raygun" -> domain name = "github"
    // * url = "http://www.zombie-bites.com" -> domain name = "zombie-bites"
    // * url = "https://www.cnet.com" -> domain name = cnet"

    function domainName(url){
    url = url.replace("https://", '');
    url = url.replace("http://", '');
    url = url.replace("www.", '');
    return url.split('.')[0];
    };

    domainName("http://google.com");
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    enum primaryColor { red, yellow, blue = 10, green };  // defining enum
    enum primaryColor myColor, myColor2, myColor3; // defining a variable
    myColor = red;
    printf("%d\n", myColor); // 0
    myColor2 = blue;
    printf("%d\n", myColor2); // 10
    myColor3 = green;
    printf("%d\n", myColor3); // 11

    _Bool isSameColor = (myColor == myColor2);
    printf("%d", isSameColor); // 0, false
    _Bool isRed = (myColor == red);
    printf("%d", isSameColor); // 1, true
    1
    2
    3
    4
    5
    6
    7
    char broiled;
    broiled = 'T';
    //broiled = T; //think T is a varible
    //broiled = "T"; //think "T" is a string
    broiled = 65;

    char x = '\n'; // newline

    itpestudy c c++

    C 概述

    计算机组成

    计算机基本结构为 5 个部分,分别是运算器、控制器、存储器、输入设备、输出设备,这 5 个部分也被称为冯诺依曼模型。

    Alt text

    accumulator
    (computer science) a register that has a built-in adder that adds an input number to the contents of the register

    arithmetic logic unit
    /əˈrɪθmətɪk/
    the type of mathematics that deals with the adding, multiplying, etc. of numbers

    Alt text

    控制单元负责控制 CPU 工作,逻辑运算单元负责计算,而寄存器可以分为多种类

    通用寄存器,用来存放需要进行运算的数据,比如需要进行加和运算的两个数据。
    程序计数器,用来存储 CPU 要执行下一条指令「所在的内存地址」,注意不是存储了下一条要执行的指令,此时指令还在内存中,程序计数器只是存储了下一条指令「的地址」。
    指令寄存器,用来存放当前正在执行的指令,也就是指令本身,指令被执行完成之前,指令都存储在这里。

    一个程序执行的时候,CPU 会根据程序计数器里的内存地址,从内存里面把需要执行的指令读取到指令寄存器里面执行,然后根据指令长度自增,开始顺序读取下一条指令。

    总线是用于 CPU 和内存以及其他设备之间的通信,总线可分为 3 种:

    地址总线,用于指定 CPU 将要操作的内存地址;
    数据总线,用于读写内存的数据;
    控制总线,用于发送和接收信号,比如中断、设备复位等信号,CPU 收到信号后自然进行响应,这时也需要控制总线;

    当 CPU 要读写内存数据的时候,一般需要通过下面这三个总线:

    首先要通过「地址总线」来指定内存的地址;
    然后通过「控制总线」控制是读或写命令;
    最后通过「数据总线」来传输数据;

    指令

    Alt text

    MIPS 的指令是一个 32 位的整数,高 6 位代表着操作码,表示这条指令是一条什么样的指令,剩下的 26 位不同指令类型所表示的内容也就不相同,主要有三种类型R、I 和 J。

    R 指令,用在算术和逻辑操作,里面有读取和写入数据的寄存器地址。如果是逻辑位移操作,后面还有位移操作的「位移量」,而最后的「功能码」则是再前面的操作码不够的时候,扩展操作码来表示对应的具体指令的;
    I 指令,用在数据传输、条件分支等。这个类型的指令,就没有了位移量和功能码,也没有了第三个寄存器,而是把这三部分直接合并成了一个地址值或一个常数;
    J 指令,用在跳转,高 6 位之外的 26 位都是一个跳转后的地址;

    指令从功能角度划分

    数据传输类型的指令,比如 store/load 是寄存器与内存间数据传输的指令,mov 是将一个内存地址的数据移动到另一个内存地址的指令;
    运算类型的指令,比如加减乘除、位运算、比较大小等等,它们最多只能处理两个寄存器中的数据;
    跳转类型的指令,通过修改程序计数器的值来达到跳转执行指令的过程,比如编程中常见的 if-else、switch-case、函数调用等。
    信号类型的指令,比如发生中断的指令 trap;
    闲置类型的指令,比如指令 nop,执行后 CPU 会空转一个周期;

    Alt text

    加和运算 add 指令是属于 R 指令类型:

    add 对应的 MIPS 指令里操作码是 000000,以及最末尾的功能码是 100000,这些数值都是固定的,查一下 MIPS 指令集的手册就能知道的;
    rs 代表第一个寄存器 R0 的编号,即 00000;
    rt 代表第二个寄存器 R1 的编号,即 00001;
    rd 代表目标的临时寄存器 R2 的编号,即 00010;
    因为不是位移操作,所以位移量是 00000

    key words

    enum
    enumerate
    枚举
    to name things on a list one by one

    extern
    external

    volatile
    /ˈvɑːlətl/
    易变的
    change suddenly and unexpectedly.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <stdio.h>  // 引入头文件
    // stdio.h系统标准输入、输出头文件。即引入printf函数
    // <> 系统同文件 "" 用户自定义头文件

    int main(void) // main函数,程序的唯一入口
    {
    printf("hello world!\n");
    system("pause"); // 执行系统命令,其他如清空屏幕system("cls");

    return 0; // 0 表示程序正常结束
    }

    system("pause");

    Alt text

    gcc

    windows explore
    地址栏选择路径 —》 直接输入CMD
    以当前文件夹地址打开CMD

    gcc helloworld.c -o helloworld.exe
    helloworld.exe

    linux gcc

    vi hello.c
    insert
    esc -> :wq

    apt install gcc
    gcc hello.c -o hello
    ./hello

    Alt text

    预处理

    gcc -E hello.c -o hello.i

    头文件展开

    宏定义替换:将宏名替换为宏值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdio.h>  // 引入头文件
    #define PI 3.14 //定义常量,宏定义
    // stdio.h系统标准输入、输出头文件。即引入printf函数
    // <> 系统同文件 "" 用户自定义头文件

    int main(void) // main函数,程序的唯一入口
    {
    printf("%d\n", PI);
    system("pause");

    return 0; // 0 表示程序正常结束
    }

    替换注释为空行

    展开 条件编译

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #include <stdio.h>  // 引入头文件
    #define PI 3.14 //定义常量,宏定义
    // stdio.h系统标准输入、输出头文件。即引入printf函数
    // <> 系统同文件 "" 用户自定义头文件

    int main(void) // main函数,程序的唯一入口
    {
    #ifdef PI
    printf("PI exits");
    #endif // PI

    printf("%d\n", PI);
    system("pause");

    return 0; // 0 表示程序正常结束
    }

    编译

    检查语法错误
    生成汇编语言的汇编文件

    gcc -S hello.i -o hello.s

    汇编

    将汇编指令翻译成二进制机器编码

    gcc -c hello.s -o hello.o

    链接

    gcc hello.o -o hello

    数据段合并
    数据地址回填
    库引入

    printf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <stdio.h>

    int main(void)
    {
    int a = 3;
    int b = 5;
    int c;
    c = a + b;

    printf("%d\n", c);

    printf("c = %d\n", c);

    printf("%d + %d = %d\n", a, b, c);

    printf("%d + %d = %d\n", a, b, a + b);

    return 0;
    }

    8
    c = 8
    3 + 5 = 8
    3 + 5 = 8

    debug

    Alt text

    f11 逐语句,会进入函数内部
    f10 逐过程,不会进入子函数

    调试 —》 窗口 —》 反汇编

    Alt text

    visual studio

    ctrl + k, ctrl + f 格式美化代码
    ctrl + k, ctrl + c 注释
    ctrl + k, ctrl + u 取消注释

    常量

    “hello”, ‘A’, -10, 3.1415
    #define PI 3.1415 //推荐
    const int a = 10; //只读变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <stdio.h>
    #define PI 3.1415

    int main(void) {
    const int r = 3;
    const int a = 10;
    float s;
    // a = 50;
    //PI = 3.15;
    s = PI * r * r;
    float l = 2 * PI * r;
    printf("s = %.2f, l = %f\n", s, l);
    return 0;
    }

    printf(“s = %.2f, l = %f\n”, s, l);
    %.2f 保留2位小数,会进行四舍五入

    extern 关键字, 只是声明外部符号(标识符)
    extern int a;

    sizeof关键字

    返回unsigned int类型
    printf("size of int = %u\n", sizeof(int));

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #include <stdio.h>

    int main(void) {
    printf("size of int = %d\n", sizeof(int));
    printf("size of short = %d\n", sizeof(short));
    printf("size of long = %d\n", sizeof(long));
    printf("size of long long = %d\n", sizeof(long long));
    int a = 10;
    short b = 20;
    long c = 30;
    long long d = 40;
    printf("size of a = %d\n", sizeof(a));
    printf("size of b = %d\n", sizeof(b));
    printf("size of c = %d\n", sizeof(c));
    printf("size of d = %d\n", sizeof(d));
    unsigned int e = 10;
    unsigned short f = 20;
    unsigned long g = 30;
    unsigned long long h = 40;
    printf("size of e = %d\n", sizeof(e));
    printf("size of f = %d\n", sizeof(f));
    printf("size of g = %d\n", sizeof(g));
    printf("size of h = %d\n", sizeof(h));
    }

    size of int = 4
    size of short = 2
    size of long = 4
    size of long long = 8
    size of a = 4
    size of b = 2
    size of c = 4
    size of d = 8
    size of e = 4
    size of f = 2
    size of g = 4
    size of h = 8

    int a = 10;
    sizeof int
    sizeof a

    Alt text

    char

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdio.h>

    int main(void) {
    char ch = 'A';
    printf("ch = %c\n", ch);
    printf("ch = %d\n", ch);

    ch = 97;
    printf("ch = %c\n", ch);
    system("pause");
    return 0;
    }

    ch = A
    ch = 65
    ch = a

    \0

    char a = ‘\0’;
    printf(“a = %d\n”, a); // 0

    Alt text

    浮点数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <stdio.h>

    int main(void) {
    float a = 3.1415f;
    double b = 13.45687;
    float c = 3.2e3f;
    float d = 1.6e-3f;

    printf("a = %.3f\n", a);
    printf("b = %08.3lf\n", b); //总字符数为8(包含小数点),不足的0填充,保留3位小数,最后一位为四舍五入的。
    printf("c = %.3f\n", c);
    printf("d = %.3f\n", d);
    return 0;
    }

    a = 3.141
    b = 0013.457
    c = 3200.000
    d = 0.002

    除2方向取余法 10 –> 2

    原码,反码,补码

    原码:最高位为符号位

    反码:
    正数与原码相同
    负数,最高位为1,其他位取反

    补码:为计算机中存储负数的形式
    正数与原码相同
    负数,最高位为1,其他位取反 + 1
    00000000 为 0
    11111111 为 -128

    C programing

    编译器是把高级语言程序翻译成计算机能理
    解的机器语言指令集的程序。

    不同CPU制造商使用的指令系统和编
    码格式不同。
    使用合适的编译器或编译器集,便可把一种高级
    语言程序转换成供各种不同类型 CPU 使用的机器语言程序。

    ANSI/ISO标准的最终版本通常叫作C89(因为ANSI于1989年批准该标
    准)或C90(因为ISO于1990年批准该标准)
    ISO C和ANSI C是完全相同的
    标准。

    1994年,ANSI/ISO联合委员会(C9X委员会)开始修订C标准,最终发
    布了C99标准。

    2011年终于发布了C11标准

    本书使用术语ANSI C、ISO C或ANSI/ISO C讲解C89/90和较新标准共有
    的特性,用C99或C11介绍新的特性。


    编译器是把源代码转换成可执行代码的程序。可执行代码
    是用计算机的机器语言表示的代码。这种语言由数字码表示的指令组成。如
    前所述,不同的计算机使用不同的机器语言方案。C 编译器负责把C代码翻
    译成特定的机器语言。此外,C编译器还将源代码与C库(库中包含大量的
    标准函数供用户使用,如printf()和scanf())的代码合并成最终的程序(更精
    确地说,应该是由一个被称为链接器的程序来链接库函数,但是在大多数系
    统中,编译器运行链接器)。其结果是,生成一个用户可以运行的可执行文
    件,其中包含着计算机能理解的代码。

    用C语言编写程序时,编写的内容被储存在文本文件中,该文件被称为
    源代码文件(source code file)。大部分C系统,包括之前提到的,都要求文
    件名以.c结尾(如,wordcount.c和budget.c)。

    编译器把源代码转换成中间代码,链接器把中间代码和其他
    代码合并,生成可执行文件。C 使用这种分而治之的方法方便对程序进行模
    块化,可以独立编译单独的模块,稍后再用链接器合并已编译的模块。通过
    这种方式,如果只更改某个模块,不必因此重新编译其他模块。另外,链接
    器还将你编写的程序和预编译的库代码合并。

    中间文件有多种形式。把源
    代码转换为机器语言代码,并把结果放在目标代码文件(或简称目标文件)

    目标代码文件缺失启动代码(startup code)。启动代码充当着程序和操
    作系统之间的接口。例如,可以在MS Windows或Linux系统下运行IBM PC兼
    容机。这两种情况所使用的硬件相同,所以目标代码相同,但是Windows和
    Linux所需的启动代码不同,因为这些系统处理程序的方式不同。

    目标代码还缺少库函数。
    printf()函数真正的代码储存
    在另一个被称为库的文件中。库文件中有许多函数的目标代码。

    链接器的作用是,把你编写的目标代码、系统的标准启动代码和库代码
    这 3 部分合并成一个文件,即可执行文件。

    Alt text


    GNU项目始于1987年,是一个开发大量免费UNIX软件的集合
    GNU编译器集合(也被称
    为GCC,其中包含GCC C编译器)是该项目的产品之一

    GCC有
    各种版本以适应不同的硬件平台和操作系统,包括UNIX、Linux和
    Windows。
    用gcc命令便可调用GCC C编译器。许多使用gcc的系统都用cc作
    为gcc的别名。


    下载Cygwin和MinGW,这样便可在PC上通
    过命令行使用GCC编译器。Cygwin在自己的视窗运行,模仿Linux命令行环
    境,有一行命令提示。MinGW在Windows的命令提示模式中运行。

    源代码文件应该是文本文件


    Microsoft Visual Studio
    在新建
    项目时,选择C++选项,然后选择【Win32控制台应用程序】,在应用设置
    中选择【空项目】。

    introducing C

    a simple example of C

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <stdio.h>
    int main(void) /* a simple program */
    {
    int num; /* define a variable called num */
    num = 1; /* assign a value to num */
    printf("I am a simple "); /* use the printf() function */
    printf("computer.\n");
    printf("My favorite number is %d because it is first.\n", num);
    getchar();
    return 0;
    }

    getchar();
    This code causes the program to wait for a keystroke, so the window remains open until you
    press a key.

    the example explained

    The effect of #include <stdio.h> is the same as
    if you had typed the entire contents of the stdio.h file into your file at the point where the

    #include line appears

    The #include statement is an example of a C preprocessor directive. In general, C compilers
    perform some preparatory work on source code before compiling; this is termed preprocessing .

    The stdio.h file is supplied as part of all C compiler packages. It contains information about
    input and output functions, such as printf(), for the compiler to use. The name stands for
    standard input/output header

    define constants or indicate the names of functions
    and how they should be used. But the actual code for a function is in a library file of precompiled code, not in a header file


    A C program always begins execution with the function called main().

    functions are the basic modules of a C program


    The parts of the program enclosed in the /**/ symbols are comments.

    C99 added a second style of comments, one popularized by C++ and Java. The new style uses
    the symbols // to create comments that are confined to a single line:
    // Here is a comment confined to one line.
    int rigue; // Such comments can go here, too.


    int num;
    This line from the program is termed a declaration statement.

    This particular example declares two things. First, somewhere in
    the function, you have a variable called num. Second, the int proclaims num as an integer

    The semicolon at the end of the line identifies the line as a C statement or instruction. The
    semicolon is part of the statement

    int Keywords are the words
    used to express a language, and you can’t use them for other purposes. For instance, you can’t
    use int as the name of a function or a variable.

    The word num in this example is an identifier—that is, a name you select for a variable, a function, or some other entity.

    the declaration connects a particular identifier with a particular
    location in computer memory, and it also establishes the type of information, or data type, to
    be stored at that location.

    all variables must be declared before they are used. This means that you have to provide
    lists of all the variables you use in a program and that you have to show which data type each
    variable is.

    C99 and C11, following the practice of C++, let you place declarations about anywhere in
    a block. However, you still must declare a variable before its first use.

    Declaring a variable to be an integer or a character type makes it possible for the
    computer to store, fetch, and interpret the data properly

    name choice

    The characters at your disposal are lowercase letters, uppercase letters, digits, and the underscore ( _). The first character must be a letter or an underscore.

    Operating systems and the C library often use identifiers with one or two initial underscore
    characters, such as in _kcab, so it is better to avoid that usage yourself.

    C names are case sensitive, meaning an uppercase letter is considered distinct from the corresponding lowercase letter. Therefore, stars is different from Stars and STARS .

    Four Good Reasons to Declare Variables

    Declaring variables helps prevent one of programming’s more subtle and hard-to-find
    bugs—that of the misspelled variable name.

    RADIUS1 = 20.4;
    and that elsewhere in the program you mistyped
    CIRCUM = 6.28 * RADIUSl;

    the compiler will
    complain when the undeclared RADIUSl shows up.

    C
    prior to C99 required that the declarations go at the beginning of a block.


    Assignment
    num = 1;

    You can assign num a different value later, if you want; that is why num is termed a
    variable.


    The printf() Function

    actual argument of a function

    C uses the terms actual argument and formal
    argument to distinguish between a specific value sent to a function and a variable in the function used to hold the value

    The \n symbol means to start a new line
    when you press the Enter key, the editor quits the current line on
    which you are working and starts a new one. The newline character, however, affects how the
    output of the program is displayed.

    an escape sequence. An escape sequence is used to
    represent difficult- or impossible-to-type characters.

    e \t for Tab and \b
    for Backspace

    The %d is a placeholder to show where the value of num is to be
    printed. This line is similar to the following BASIC statement:
    PRINT “My favorite number is “; num; “ because it is first.”

    the d tells it to print the variable as a decimal (base 10)
    integer.

    the f in
    printf() is a reminder that this is a formatting print function.
    Each type of data has its own
    specifier

    the structure of a simple program

    A program consists of a collection of one or more functions, one of which must be
    called main().

    The description of a function consists of a header and a body. The function header
    contains the function name along with information about the type of information passed to
    the function and returned by the function.

    The body is enclosed by braces ( {}) and consists of a series of
    statements, each terminated by a semicolon

    a simple standard C program should use the following format:

    1
    2
    3
    4
    5
    6
    #include <stdio.h>
    int main(void)
    {
    statements
    return 0;
    }

    Alt text

    Alt text

    tips on making programs readable

    Choose meaningful variable
    names and use comments.
    using blank lines to separate one conceptual section of a function from another.
    use one line per statement

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int main(void) /* converts 2 fathoms to feet */ /* use comments */

    {
    int feet, fathoms; /* pick meaningful names */
    /* use space */
    fathoms = 2;
    feet = 6 * fathoms; /* one statement per line */
    printf("There are %d feet in %d fathoms!\n", feet, fathoms);
    return 0;
    }

    taking another step in using C

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // fathm_ft.c -- converts 2 fathoms to feet

    #include <stdio.h>
    int main(void)
    {
    int feet, fathoms;

    fathoms = 2;
    feet = 6 * fathoms;
    printf("There are %d feet in %d fathoms!\n", feet, fathoms);
    printf("Yes, I said %d feet!\n", 6 * fathoms);

    return 0;
    }

    declares two variables instead of just one in a single declaration statement.

    int feet, fathoms;

    and

    int feet;
    int fathoms;

    are equivalent


    feet = 6 * fathoms;
    means “look up the value of the variable fathoms, multiply it by 6, and assign the result of this
    calculation to the variable feet .”


    printing ultiple values

    printf("There are %d feet in %d fathoms!\n", feet, fathoms);

    printf("Yes, I said %d feet!\n", 6 * fathoms);

    the value printed doesn’t have to be a variable; it
    just has to be something, such as 6 * fathoms, that reduces to a value of the right type.

    multiple functions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //* two_func.c -- a program using two functions in one file */
    #include <stdio.h>
    void butler(void); /* ANSI/ISO C function prototyping */
    int main(void)
    {
    printf("I will summon the butler function.\n");
    butler();
    printf("Yes. Bring me some tea and writeable DVDs.\n");
    return 0;
    }
    void butler(void) /* start of function definition */
    {
    printf("You rang, sir?\n");
    }

    I will summon the butler function.
    You rang, sir?
    Yes. Bring me some tea and writeable DVDs.

    The C90 standard added prototypes, and older compilers might not recognize them

    A prototype declares to the compiler
    that you are using a particular function, so it’s called a function declaration.
    It also specifies
    properties of the function.

    The C standard recommends that you provide function prototypes for all functions you
    use.

    The standard include files take care of this task for the standard library functions. For
    example, under standard C, the stdio.h file has a function prototype for printf().

    void is used to mean “empty,” not “invalid.”

    Older C supported a more limited form of function declaration in which you just specified the
    return type but omitted describing the arguments:
    void butler();

    all C programs begin execution with
    main(), no matter where main() is located in the program files.
    the usual C practice
    is to list main() first because it normally provides the basic framework for a program.

    introducing debugging

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /* nogood.c -- a program with errors */
    #include <stdio.h>
    int main(void)
    (
    int n, int n2, int n3;
    /* this program has several errors
    n = 5;
    n2 = n * n;
    n3 = n2 * n2;
    printf("n = %d, n squared = %d, n cubed = %d\n", n, n2, n3)
    return 0;
    )

    syntax errors

    C syntax errors use
    valid C symbols in the wrong places.

    the compiler can get confused. A true syntax error in one location might cause the
    compiler to mistakenly think it has found other errors.
    Another common compiler trick is reporting the error a line late.

    semantic errors

    Semantic errors are errors in meaning.

    g. In C, you commit a semantic error
    when you follow the rules of C correctly but to an incorrect end.

    One method
    is to pretend you are the computer and to follow the program steps one by one.

    program state

    The program state is simply the set of values of all the variables at a given point
    in program execution. It is a snapshot of the current state of computation.

    Another approach to locating semantic problems is to sprinkle extra printf() statements
    throughout to monitor the values of selected variables at key points in the program.

    A debugger is a program
    that enables you to run another program step-by-step and examine the value of that program’s
    variables.

    reserved identifiers, that you shouldn’t use

    They
    don’t cause syntax errors because they are valid names. However, the language already uses
    them or reserves the right to use them, so it could cause problems if you use these identifiers to
    mean something else. Reserved identifiers include those beginning with an underscore character and the names of the standard library functions, such as printf() .

    data

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <stdio.h>
    int main(void) {
    float weight;
    float value;

    printf("enter weight in pounds: ");

    /* get input from the user */
    scanf_s("%f", &weight);

    value = 1700 * weight * 14.5833;
    printf("your weight in platinum is worth $%.2f.\n", value);

    return 0;
    }

    scanf_s(“%f”, &weight);

    Pressing Enter informs the computer that you have finished typing your response.

    The scanf() function uses the &
    notation to indicate where it can find the weight variable.

    The scanf() and
    printf() functions make this interactivity possible. The scanf() function reads data
    from the keyboard and delivers that data to the program, and printf() reads data from
    a program and delivers that data to your screen.


    use that function call twice:
    getchar();
    getchar();
    The getchar() function reads the next input character, so the program has to wait for input.
    In this case, we provided input by typing 156 and then pressing the Enter (or Return) key, which
    transmits a newline character. So scanf() reads the number, the first getchar() reads the
    newline character, and the second getchar() causes the program to pause, awaiting further
    input.


    use the %f specifier in the printf() code to handle a
    floating-point value. The .2 modifier to the %f specifier fine-tunes the appearance of the
    output so that it displays two places to the right of the decimal.

    data varialbes and constants

    constants of various data types.

    data, the numbers
    and characters that bear the information you use

    Some types of data are preset before a
    program is used and keep their values unchanged throughout the life of the program. These are
    constants.
    Other types of data may change or be assigned values as the program runs; these are
    variables.

    The difference between a variable and a constant is that a variable can have its value
    assigned or changed while the program is running, and a constant can’t.

    14.5833 is a constant.
    1700.0? True, the price of platinum isn’t a constant in real life, but this program treats it as a constant

    data type keywords

    Original K&R Keywords C90 K&R Keywords C99 Keywords
    int signed _Bool
    long void _Complex
    short _Imaginary
    unsigned
    char
    float
    double

    If a datum is a constant, the compiler can usually tell its type
    just by the way it looks: 42 is an integer, and 42.100 is floating point.

    A variable, however,
    needs to have its type announced in a declaration statement.


    The int keyword provides the basic class of integers used in C. The next three keywords ( long ,
    short, and unsigned) and the C90 addition signed are used to provide variations of the
    basic type, for example, unsigned short int and long long int.

    the char keyword designates the type used for letters of the alphabet and for other characters, such as #, $, %, and
    *. The char type also can be used to represent small integers.

    float, double, and the
    combination long double are used to represent numbers with decimal points.

    The _Bool type
    is for Boolean values ( true and false)

    _Complex and _Imaginary represent complex and imaginary numbers, respectively.

    two families on the basis of how
    they are stored in the computer: integer types and floating-point types.

    For a computer, the difference is reflected in the way they are stored.


    The smallest unit of memory is called a bit. It can hold one of two values: 0 or 1.
    The bit is the basic building block of computer memory.

    The byte is the usual unit of computer memory. For nearly all machines, a byte is 8 bits, and that is the standard definition, at least when used to measure storage.
    Because each bit can be either 0 or 1, there are 256 (that’s 2 times
    itself 8 times) possible bit patterns
    . These patterns
    can be used, for example, to represent the integers from 0 to 255 or to represent a set of
    characters.

    A word is the natural unit of memory for a given computer design.
    For 8-bit microcomputers,
    such as the original Apples, a word is just 8 bits. personal computers moved up to
    16-bit words, 32-bit words, and, at the present, 64-bit words. Larger word sizes enable faster
    transfer of data and allow more memory to be accessed.

    integer

    Integers are stored as binary numbers.

    The integer 7, for example, is written 111 in binary.
    Therefore, to store this number in an 8-bit byte, just set the first 5 bits to 0 and the last 3 bits
    to 1
    Alt text

    floating point number

    adding a decimal point makes a value a floating-point
    value
    7 is an integer type but 7.00 is a floating-point type.

    e-notation
    3.16E7 means to multiply 3.16 by 10 to the 7th power

    Floating-point representation involves breaking up a number
    into a fractional part and an exponent part and storing the parts separately.

    7.00 The decimal analogy would be to write 7.0 as 0.7E1. Here, 0.7 is the fractional part, and the 1 is the exponent part.

    A computer, of course, would use binary numbers and powers of two instead of powers
    of 10 for internal storage.


    Floating-point numbers can represent a much larger range of values than integers can

    Because there is an infinite number of real numbers in any range—for example, in the
    range between 1.0 and 2.0—computer floating-point numbers can’t represent all the
    values in the range. Instead, floating-point values are often approximations of a true
    value. For example, 7.0 might be stored as a 6.99999 float value

    Floating-point operations were once much slower than integer operations

    basic c data types

    represent a constant with a literal value

    the int type

    C gives the programmer the option of matching a type to a particular use.
    C integer types vary in the range of values offered and in whether negative numbers can be
    used.

    The int type is a signed integer. That means it must be an integer and it can be positive, negative, or zero.
    Typically, systems represent signed integers by using the value of a particular bit to indicate the
    sign.

    The range in possible values depends on the computer system. Typically, an int
    uses one machine word for storage.

    16 bits to store an int. This allows a range in values from –32768 to 32767.
    ISO C specifies that the minimum range for type int should be from –32767 to 32767 .

    Declaring an int Variable

    int erns;
    int hogs, cows, goats;

    Initializing a Variable

    To initialize a variable means to assign it a starting, or initial, value.

    this can be done as
    part of the declaration. Just follow the variable name with the assignment operator ( =) and the
    value you want the variable to have

    1
    2
    3
    4
    int hogs = 21;
    int cows = 32, goats = 14;
    int dogs, cats = 94; /* valid, but poor, form, best to avoid putting initialized and noninitialized variables in the
    same declaration statement. only cats is initialized*/
    type int cosntans

    The various integers ( 21, 32, 14, and 94) in the last example are integer constants, also called
    integer literals. When you write a number without a decimal point and without an exponent, C
    recognizes it as an integer

    C treats most integer constants as type int. Very large integers can be treated differently;

    Printing int Values

    The %d is called a format
    specifier because it indicates the form that printf() uses to display a value.

    Each %d in the
    format string must be matched by a corresponding int value in the list of items to be printed.
    That value can be an int variable, an int constant, or any other expression having an int
    value.

    check to see that the number of format specifiers you give to printf() matches the number of
    values to be displayed.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdio.h>

    int main(void) {
    int ten = 10;
    int two = 2;

    printf("%d minus %d is %d\n", ten, 2, ten - two);

    printf("%d minus %d is %d\n", ten); //fogot 2 arguments

    return 0;
    }

    10 minus 2 is 8
    10 minus -641 is -470812528

    Most functions take a specific number of arguments, and the
    compiler can check to see whether you’ve used the correct number
    printf() can
    have one, two, three, or more arguments, and that keeps the compiler from using its usual
    methods for error checking

    Octal and Hexadecimal

    C assumes that integer constants are decimal, or base 10, numbers. However, octal
    (base 8) and hexadecimal (base 16) numbers are popular with many programmers.

    Because 8
    and 16 are powers of 2, and 10 is not, these number systems occasionally offer a more convenient way for expressing computer-related values. For example, the number 65536, which often
    pops up in 16-bit machines, is just 10000 in hexadecimal

    Also, each digit in a hexadecimal
    number corresponds to exactly 4 bits. For example, the hexadecimal digit 3 is 0011 and the
    hexadecimal digit 5 is 0101. So the hexadecimal value 35 is the bit pattern 0011 0101, and the
    hexadecimal value 53 is 0101 0011. This correspondence makes it easy to go back and forth
    between hexadecimal and binary (base 2) notation

    In C, special prefixes indicate
    which number base you are using. A prefix of 0x or 0X (zero-ex) means that you are specifying
    a hexadecimal value, so 16 is written as 0x10, or 0X10, in hexadecimal. Similarly, a 0 (zero)
    prefix means that you are writing in octal. For example, the decimal value 16 is written as 020
    in octal.

    Be aware that this option of using different number systems is provided as a service for your
    convenience. It doesn’t affect how the number is stored

    Displaying Octal and Hexadecimal

    To display an integer in octal notation
    instead of decimal, use %o instead of %d. To display an integer in hexadecimal, use %x

    If you
    want to display the C prefixes, you can use specifiers %#o, %#x, and %#X to generate the 0, 0x ,
    and 0X prefixes respectively.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <stdio.h>

    int main(void) {
    int x = 100;

    printf("dec = %d; octal = %o; hex = %x\n", x, x, x);
    printf("dec = %d; octal = %#o; hex = %#X\n", x, x, x);

    return 0;
    }

    dec = 100; octal = 144; hex = 64
    dec = 100; octal = 0144; hex = 0X64

    other integer types

    The type short int or, more briefly, short may use less storage than int, thus saving
    space when only small numbers are needed. Like int, short is a signed type.

    The type long int, or long, may use more storage than int, thus enabling you to
    express larger integer values. Like int, long is a signed type.

    The type long long int, or long long (introduced in the C99 standard), may use
    more storage than long. At the minimum, it must use at least 64 bits. Like int, long
    long is a signed type.

    The type unsigned int, or unsigned, is used for variables that have only nonnegative
    values.

    The bit used to indicate the sign of signed numbers now becomes another binary digit,
    allowing the larger number.This type shifts the range of numbers that can be stored. For example, a 16-bit
    unsigned int allows a range from 0 to 65535 in value instead of from –32768 to 32767

    The types unsigned long int, or unsigned long, and unsigned short int, or
    unsigned short, are recognized as valid by the C90 standard. To this list, C99 adds
    unsigned long long int, or unsigned long long .

    The keyword signed can be used with any of the signed types to make your intent
    explicit. For example, short, short int, signed short, and signed short int are all
    names for the same type.

    Declaring Other Integer Types
    1
    2
    3
    4
    5
    6
    7
    8
    9
    long int estine;
    long johns;
    short int erns;
    short ribs;
    unsigned int s_count;
    unsigned players;
    unsigned long headcount;
    unsigned short yesvotes;
    long long ago; // c99
    why multiple integer types

    C guarantees only that short is no longer than int and that long is no shorter than int.

    The
    idea is to fit the types to the machine. For example, in the days of Windows 3, an int and a
    short were both 16 bits, and a long was 32 bits. Later, Windows and Apple systems moved to
    using 16 bits for short and 32 bits for int and long. Using 32 bits allows integers in excess of
    2 billion. Now that 64-bit processors are common, there’s a need for 64-bit integers, and that’s
    the motivation for the long long type.

    The most common practice today on personal computers is to set up long long as 64 bits,
    long as 32 bits, short as 16 bits, and int as either 16 bits or 32 bits, depending on the
    machine’s natural word size.


    The C standard provides guidelines specifying the minimum allowable size for each basic data
    type.
    The minimum range for both short and int is –32,767 to 32,767, corresponding to a
    16-bit unit,
    and the minimum range for long is –2,147,483,647 to 2,147,483,647, corresponding to a 32-bit unit.

    For unsigned short and unsigned int, the minimum range is 0 to 65,535, and for
    unsigned long, the minimum range is 0 to 4,294,967,295.

    The long long type is intended
    to support 64-bit needs. Its minimum range is a substantial –9,223,372,036,854,775,807
    to 9,223,372,036,854,775,807,

    and the minimum range for unsigned long long is 0 to
    18,446,744,073,709,551,615.


    : If you are writing code on
    a machine for which int and long are the same size, and you do need 32-bit integers, you
    should use long instead of int so that the program will function correctly if transferred to a
    16-bit machine.


    long constats and long long constants

    Normally, when you use a number such as 2345 in your program code, it is stored as an int
    type. What if you use a number such as 1000000 on a system in which int will not hold such
    a large number? Then the compiler treats it as a long int, assuming that type is large enough.
    If the number is larger than the long maximum, C treats it as unsigned long. If that is still
    insufficient, C treats the value as long long or unsigned long long, if those types are
    available.

    To cause a small
    constant to be treated as type long, you can append an l (lowercase L) or L as a suffix. The
    second form is better because it looks less like the digit 1.

    Therefore, a system with a 16-bit
    int and a 32-bit long treats the integer 7 as 16 bits and the integer 7L as 32 bits

    Similarly, on those systems supporting the long long type, you can use an ll or LL suffix to
    indicate a long long value, as in 3LL. Add a u or U to the suffix for unsigned long long, as
    in 5ull or 10LLU or 6LLU or 9Ull

    Printing short, long, long long, and unsigned Types

    Note
    that although C allows both uppercase and lowercase letters for constant suffixes, these format
    specifiers use just lowercase.

    To print an unsigned int number, use the %u notation.
    To print a long value, use the %ld
    format specifier.

    C has several additional printf() formats. First, you can use an h prefix for short types.
    Therefore, %hd displays a short integer in decimal form,

    Both the h and l prefixes can be used with u for unsigned types. For instance,
    you would use the %lu notation for printing unsigned long types.

    Systems supporting the long long types use %lld and %llu for the signed and
    unsigned versions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <stdio.h>

    int main(void) {
    unsigned int un = 3000000000;
    short end = 200;
    long big = 65537;
    long long verybig = 12345678908642;

    printf("un = %u and not %d\n", un, un);
    printf("end = %hd and %d\n", end, end);
    printf("big = %ld and not %hd\n", big, big);
    printf("verybig = %lld and not %ld\n", verybig, verybig);
    }

    un = 3000000000 and not -1294967296
    end = 200 and 200
    big = 65537 and not 1
    verybig = 12345678908642 and not 1942899938

    #基本语法
    YAML 使用键值对的形式记录信息,标准格式是

    key: value
    键: 值
    #基本规则
    大小写敏感
    使用缩进表示层级关系
    禁止使用 tab 缩进,只能使用空格键
    缩进长度没有限制,只要元素对齐就表示这些元素属于一个层级
    使用 # 表示注释
    字符串可以不用引号标注(但是建议你最好还是加上引号)

    三种数据结构

    • scalar 纯量
      scalar 不可再分割的量,这个你无需了解,因为了解了也没什么卵用。

    • map 散列表
      键值对的集合,只要是出于同于缩进级别下的键值对,都可以称为一个 map

    map 有两种写法,最简单,也是最常用的就是前面的那种写法,如

    hexo-tag-dplayer:
    cdn: value
    default: value
    等价于

    {hexo-tag-dplayer: {cdn: value, default: value}}
    #或者是
    hexo-tag-dplayer: {cdn: value, default: value}

    • list 数组
      划重点,这是本篇文章最有用的一节

    list 的表示形式同样有两种

    key:

    • value1
    • value2
      或者

    key: [value1, value2]
    map 和 list 可以相互嵌套使用

    vs code shortcut

    1

    查找替换
    Ctrl+F | 查找
    Ctrl+H | 查找替换

    F3 / Shift+F3 | Find next/previous
    Alt+Enter | Select all occurences of Find match

    Ctrl+D | Add selection to next Find match下一个匹配的也被选中

    Ctrl+Shift+L | Select all occurrences of current selection同时选中所有匹配的
    Ctrl+F2 | Select all occurrences of current word

    Ctrl+K Ctrl+D | Move last selection to next Find match将光标移动到,搜索结果中的下一个

    Ctrl+Shift+F | 整个文件夹中查找

    file to include or exclude
    path segment匹配符:
    * to match one or more characters in a path segment
    ? to match on one character in a path segment
    ** to match any number of path segments ,including none {} to group conditions
    e.g. {**/*.html,**/*.txt} matches all html and txt files
    [] to declare a range of characters to match
    e.g., example.[0-9] to match on example.0,example.1, …

    2

    显示相关
    全屏:F11
    zoomIn/zoomOut:Ctrl + =/Ctrl + -
    侧边栏显/隐:Ctrl+B

    侧边栏4大功能显示:
    Show Explorer Ctrl+Shift+E
    Show Search Ctrl+Shift+F
    Show Git Ctrl+Shift+G
    Show Debug Ctrl+Shift+D

    Ctrl+Shift+M Show Problems panel

    Ctrl+` Show integrated terminal

    输出Show Output Ctrl+Shift+U
    预览markdown Ctrl+Shift+V

    Alt+Z Toggle word wrap

    Shift+Alt+0 Toggle editor layout (horizontal/vertical)

    ctrl k + ctrl s = 打开快捷键一览表。

    ctrl + , user settting

    Ctrl+M Toggle Tab moves focus

    6

    编辑器与窗口管理

    新建文件 Ctrl+N
    Ctrl+F4, Ctrl+W Close editor
    Ctrl+Shift+T Reopen closed editor
    历史打开文件之间切换 Ctrl+Tab,Alt+Left,Alt+Right

    Ctrl+Shift+PgUp / PgDn Move editor left/right

    Ctrl+K P Copy path of active file

    show command palette

    主命令框 Ctrl+Shift+P模式。或 F1

    在Ctrl+P下输入>又可以回到主命令框 Ctrl+Shift+P模式。

    quick open, go to file

    直接输入文件名,快速打开文件
    ? 列出当前可执行的动作
    ! 显示Errors或Warnings,也可以Ctrl+Shift+M
    跳转到行数,也可以Ctrl+G直接进入

    @ 跳转到symbol(搜索变量或者函数),也可以Ctrl+Shift+O直接进入
    # Show all Symbols,也可以Ctrl+T

    Rich languages editing

    重命名:比如要修改一个方法名,可以选中后按F2,输入新的名字,回车,会发现所有的文件都修改过了。

    跳转到下一个Error或Warning:当有多个错误时可以按F8逐个跳转

    查看diff 在explorer里选择文件右键 Set file to compare,然后需要对比的文件上右键选择Compare with ‘file_name_you_chose’.

    Ctrl+Space 或 Ctrl+I Trigger suggestion

    Ctrl+. Quick Fix

    代码格式化:Shift+Alt+F,或Ctrl+Shift+P后输入format code

    Ctrl+K Ctrl+F Format selection

    重构代码

    跳转到定义处:F12
    定义处缩略图:只看一眼而不跳转过去Alt+F12

    列出所有的引用:Shift+F12
    同时修改本文件中所有匹配的:Ctrl+F12

    editing

    KEYS ACTION
    Ctrl + [ / ] 代码行缩进
    Ctrl + Shift + [ / ] 折叠打开代码块
    Ctrl+K Ctrl+0 Fold (collapse) all regions
    Ctrl+K Ctrl+J Unfold (uncollapse) all regions
    Ctrl + X 如果不选中,默认复制或剪切一整行
    Ctrl + C 如果不选中,默认复制或剪切一整行
    Alt + Up / Down 上下移动一行
    Shift+Alt+Up 或 Shift+Alt+Down 向上向下复制一行
    Ctrl+Enter 在当前行下边插入一行
    Ctrl+Shift+Enter 在当前行上方插入一行

    光标相关

    KEYS ACTION
    Home 移动到行首:
    End 移动到行尾:
    Ctrl+End 移动到文件结尾:
    Ctrl+Home 移动到文件开头:
    Ctrl+Shift+\ 移动到后半个括号
    Ctrl+L Select current line 选中当前行
    Shift+End 选择从光标到行尾
    Shift+Home 选择从行首到光标处
    Ctrl + Shift + K 删除光标所在行
    Ctrl + Left / Right 一个单词一个单词的移动光标
    Shift + Left / Right 一个字母一个字母的加入选择
    Ctrl + Shift + Left / Right 一个单词一个单词的加入选择
    Shift + Up / Down 一行行的加入选择
    Shift + Alt + Left / Right Shrink/expand selection(光标所在单词,文档高亮显示相同的)
    Ctrl + Alt + Left / Right 不常用移动窗口到右侧

    multi cursor

    KEYS ACTION
    Alt+Click Multi-Cursor:可以连续选择多处,然后一起修改,添加cursor
    Ctrl+Alt+Down 或 Ctrl+Alt+Up Insert cursor above / below
    Ctrl + Shift + Alt + (arrow key) Column (box) selection
    Shift+Alt+I Insert cursor at end of each line selected
    Ctrl+U 回退上一个光标操作
    Ctrl+↑ / ↓ Scroll line up/down
    Alt+PgUp / PgDn Scroll page up/down, not change the cusor location

    comment

    Ctrl+K Ctrl+C Add line comment
    Ctrl+K Ctrl+U Remove line comment
    Ctrl+/ Toggle line comment
    Shift+Alt+A Toggle block comment

    8

    Alt text