“Web Front-end to Real” is a customized front-end learning course for those who have no foundation. Through the learning of this tutorial, partners can systematically master a set of Web front-end development system to meet the needs of daily development, and have the ability to systematically analyze and solve problems.

Learning takes place in two stages:

  1. Systematic learning (approximately 75% of total learning time)
  2. The project on

Systematic learning path

Stage 1 (the most important, solid learning can quickly start the project development)

  1. html
  2. css
  3. Homework: Make a static page
  4. js(es5)
  5. react
  6. redux

Stage 2 (Web Front-end Stack necessary knowledge supplement)

  1. dom
  2. bom
  3. html5
  4. css3
  5. es6
  6. webpack

preparation

  1. VS Code, the Code editor
  2. NVM (Node Version Manager, you can change the Node.js Version). After installing node.js, use NVM to install Node.js V12.16.2.
  3. Chrome

html

I met the HTML

HTML full name is Hypertext Markup Language. All the text pictures and organizational structures in the web page are written by HTML. Of course, HTML can accomplish more than these.

HTML is not a programming language. It does not have variables, functions, etc., like c/ C ++/ Java programming languages. It simply consists of tags such as

.

The HTML tag is the root tag, and all other tags are written in this tag. The next two structures are the head tag and the body tag ,. The head is for the browser, the body is the main part of the page, and everything we display is in the body tag.

Let’s take a look at some basic HTML. Open the VS Code editor and create a test.html file with the following contents:

<! DOCTYPEhtml>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>hello world</title>
</head>
<body>test</body>
</html>
Copy the code

Open your browser and you’ll see the word “test.”

Among them:

Doctype is a document type, which has two categories: hybrid mode and standard mode. Different modes mainly affect the presentation of CSS content. Generally, HTML5 standard mode is used.

<! DOCTYPE html>Copy the code

The lang attribute tells search engine crawlers what language our site is in, such as < HTML lang=”en”> for Chinese and < HTML lang=”en”> for English.

The
tag can be encoded. This tag does not need to be a closed tag. Encoding sets mainly include GB2312, GBK, Unicode, UTF-8, etc. Utf-8 is generally used.

The

tag represents the page title, and each page has its own name, which is set through the tag.

Tags in HTML

Tags in HTML fall into two main categories:

Display: inline; display: inline; The characteristics of this category of elements (tags) are:

  1. Instead of taking up the entire line, the amount of space an element takes up is entirely determined by its content
  2. Width and height cannot be changed

A em span strong

2. Block level elements (tags), display: block; This category of elements is characterized by:

  1. Fill the entire line, no matter how much
  2. You can change the width and height

For example: Address div form H1-h6 p ul OL li

There is also a class of tags that are neither row-level nor block-level elements, that do not monopolize a row and can vary the width and height at will, such as IMG and SELECT.

The number of tags in HTML is large and growing. We don’t have to remember all of these tags. Here are some common tags in HTML4 that HTML5 will cover in a later chapter.

P label (block level)

is a paragraph tag, and anything written in

is treated as a paragraph. It is characterized by a single line, with some spacing between paragraphs.

Title tags H1-H6 (Block level)

The title tag is used to highlight the text. It is usually used for headings. It magnifies the text to a single line. The default size for H4 is normal text size, but in bold.

Strong tag (row level)

The tag is used to bold the text inside.

Em tag (row level)

is used to italicize the text inside.

Del tag (row level)

is the delete tag, which draws a line through the middle of the text inside.

Address tag (block level)

is the address tag that italics the contents and takes a single line.

Div, span,

These are very basic tags, and their effect is obvious. There are also structured tags that have no special effect, but are used as containers to wrap other tags.

One of the functions of structured tags is to style the child elements within them. If an attribute is not styled by the developer, it automatically inherits the style of the parent element.

For example, if we want the text inside the three P tags to be red, it is very troublesome to write color:red for all the three P tags. The simplest method is to put the three P tags inside a structured tag, and then set the style of color:red for the structured tag, and all the three P tags will have this style.

The first thing we think about before we write a page is structure, so we usually write structured tags first.

Let’s look at two of the most common structured tags.

1.div

The

tag is a common container tag in front-end development.

2.span

The tag is also a common container tag, most often containing text or ICONS.

Ol, LI (ol, LI are block level)

< OL >

  • is a set of tags, both of which come in pairs and are meaningless on their own.

    This set of labels is called an ordered list. Ol is the outer list box, li is the inner child, and each li child is preceded by an ordinal number.

    Ol can set some properties:

    1. Type, which sets the content displayed in front of each child item. By default, the order is numeric. If we change type=”a”, the order will be lowercase. The type attribute value can also be set to A(sorted by uppercase), I(Roman numerals, lowercase), and I(Roman numerals, uppercase). In addition, setting anything else is wrong, in which case OL will sort by default.

    2. Reversed. In reversed=”reversed”, the sequence numbers of the subitems will be reversed.

    3. The start property sets the number of ordinals from which the child items are displayed. When we write start=”2″, the ordinals become 2, 3, 4 instead of the default 1, 2, 3. The same is true for letters.

    However, we rarely see these numbers and letters in front of text on web pages, so we usually use ul and LI tags instead of OL and LI.

    Ul, LI (ul, LI are block level)

    This group of labels is an unordered list, and the sequence number before it becomes a dot (•).

    Ul also has a type attribute, which sets the value of the symbol displayed in front of each subitem. The default value is disc, square, and circle.

    In the same way, we rarely see dots or squares in front of text on web pages, so when we use ul and LI tags, we will change the ul default list-style to None, which is part of the CSS.

    An unordered list is usually used as a navigation bar, where the structure is the same.

    A (row-level element)

    The tag is a very important tag that has a mandatory attribute called href (hyperText reference).

    There are two main functions of a label:

    1. Fixed-point jump we specify the id of the element position.

    2. Hyperlinks. We set the href value to a local or online link, such as www.baidu.com/, and click on the A TAB to take us to the page.

    3. Protocol qualifier. Href =”javascript:while(1){alert(” you’re sick “)}”, click the A tag and the browser will pop up a dialog box. 13266419102 Send email: [email protected] Call: 13266419102

    The default style of the A tag is blue and underlined, and we usually use CSS to override the default style of the A tag.

    Img (row-level block element)

    The tag stands for image, and it has a required attribute called SRC. The value of the SRC attribute is the address of our image, either absolute or relative.

    Image tags also have two properties.

    1. The Alt attribute. This property sets up image placeholders and displays Alt values when images fail to load due to network speed or link errors.

    2. The title attribute. Image prompt, which displays the value of the title property set next to the image when we hover over the image.

    Table, tr, TD tags (table is block level, tr, TD is row level)

    needs to be used with < TD >
    .

    Table is a table, TR is a table of rows, TD is a table of data units, we can understand as columns.

    <table>
      <tr>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
      </tr>
    </table>
    Copy the code

    The general structure of the table tag looks like this, with several attributes.

    1. The cellPADDING property allows you to set the padding for each cell, such as cellPADDING =”10px” (on the table).
    2. Cellspacing sets the spacing between cells, and when we set it to 0 we can get rid of borders. (set on table)
    3. Colspan property, set one TD to several units, default one TD to one unit, can achieve the effect of merging cells. (Add to TD, value to number)
    <table border="1">
      <tr>
        <th>1</th>
        <th>2</th>
      </tr>
      <tr>
        <td colspan="2">3</td>
      </tr>
      <tr>
        <td colspan="2">4</td>
      </tr>
    </table>
    Copy the code

    Instead of using this tag for layout, we use div + CSS for layout.

    The reason is:

    Using a nested table to lay out a web page frame will slow down the speed of web browsing, because the contents of the table are self-adaptive. In order to adapt, it needs to calculate the deepest nested nodes to meet the self-adaptation, so there may be a period of time when there is a blank.

    The advantage of using DIV + CSS to layout web pages is that the pages produced are faster, and the content and style are separated, which is easy to maintain and expand. The disadvantage is that the table mode is more complex. Web pages now tend to use div + CSS layouts.

    Forms (block-level elements)

    This element allows us to implement front-end and back-end data interaction.

    Forms come in groups with various elements.

    Let’s look at the attributes that form elements have:

    1. The action property fills in the server address, which means the server address to which we send data
    2. Method Method for transferring attributes. The most common methods are POST and GET

    Let’s take a look at the child elements that forms have:

    The input tag

    This label is a single label and does not need to be closed. The tag has a type attribute, the value of which determines the type of the input tag.

    1. Text input box, we can enter text information.
    2. Password In the password box, the entered text information is displayed in the form of…
    3. Submit If type=”submit”, the input tag is a submit button, and clicking the submit button sends the entire form data to the backend server.

    We send data with a key and value. The value is the value of the value attribute we set (or input) to the input tag. The name of the data requires us to write a name attribute inside the input tag to indicate what the name of the data is.

    Here we write a simple form:

    <form action="https://www.baidu.com/" method="get">
      <p>username: <input type="text" name="username" /></p>
      <p>password: <input type="password" name="password" /></p>
      <input type="submit" value="Submit" />
    </form>
    Copy the code

    When we enter a random username and password and click the submit button, the browser displays something like this:

    www.baidu.com/?username=t…

    The data we passed after the web address? The username = test&password = test.

    Input also has other forms of data:

    1. type=”radio”
    2. type=”checkbox”

    Radio stands for checkbox. When we set the radio type to an input, it becomes a dot. We can select this dot, but when we write a lot of checkboxes, they all seem to be checked, and they don’t function as radio boxes, because we haven’t named this group of checkboxes yet. When we assign the same name to several radios, they become checkboxes that can only select one.

    <form action="https://www.baidu.com/" method="get">
      <input type="radio" name="sex" value="male" checked>Male
      <br>
      <input type="radio" name="sex" value="female">female<input type="submit" value="Submit" />
    </form>
    Copy the code

    We can check a number of boxes at the same time.

    <form action="https://www.baidu.com/" method="get">
      <input type="checkbox" name="vehicle" value="Bike">I have a bike
      <br>
      <input type="checkbox" name="vehicle" value="Car" checked>I have a car 
      <input type="submit" value="Submit">
    </form> 
    Copy the code

    www.baidu.com/?vehicle=Bi…

    As you can see, we can use the Checked property to set the default checked values for the two checkboxes.

    Select tag (row-level block element)

    The SELECT tag is a list of selections

    <form action="https://www.baidu.com/" method="get">
      <select name="province">
        <option>shandong</option>
        <option>heilongjiang</option>
        <option>Beijing</option>
      </select>
      <input type="submit" value="Submit">
    </form> 
    Copy the code

    The name attribute of the drop-down list is written in the

    The first option is selected by default in the drop-down list, if we can set its default value by adding the selected=”selected” attribute.

    Text delimiters and encoding sets

    We add a div to the body tag, style it, and add some text in the middle.

    <div style="width: 50px; height:50px; </div>

    We notice that the text wraps itself around the boundaries of the div tag, meaning that the div tag defines a range within which text and other tags are displayed by default.

    But when we write a string of English characters in the middle instead of Chinese, such as aaaaaaaaaaaa, we find that the string of English characters does not have a newline at the div boundary. Why?

    Reason is we each Chinese character, the computer will recognize this is a single word, every Chinese characters by default and other Chinese characters separated, but not English letters by default separated, because the computer don’t know how many English letters is a word, so we need to manually add the separator for it.

    This delimiter is also familiar to us, namely Spaces. If we add a few Spaces in the middle of this string of characters, the characters separated by Spaces will be treated as one word and separated from other words.

    Now the question is, since Spaces are used as separators, not as “blank Spaces” as we might think, how do we write real blank Spaces in HTML?

    Here we come to the term encoding set. When we write HTML, there are a lot of special symbols that can’t be written, so we have to use encoding to make the browser recognize the symbols that we want, and the encoding format is ampersand; . The code for space is   , we can see the space in the page.

    Second, the Angle brackets (<>) that are used as tags are not properly displayed by symbols, and we also need to use the code set for the browser to recognize them. The < < code is < The meaning of, less than, by the same token, the > is greater than the number of coding is & gt; “Great than. We just write these two codes in HTML, and the greater-than and less-than signs will display normally.

    Carriage return is also a delimiter, so carriage return doesn’t work in HTML, and if we want to make text look like carriage return line feed on a web page, there’s no way to encode it. We need a tag called

    tag, and this tag is just a line feed. The

    tag is empty (meaning it has no end tag, so



    is wrong), or the end tag can be placed inside the start tag, which is

    .

    》》》》》》》》》

    css

    Cascading Style Sheets (CSS) Its main function is to add various style effects to HTML tags.

    This chapter is about CSS2.0. Css3.0 will be introduced in later chapters.

    How to introduce CSS

    There are four ways to introduce the CSS:

    2. Page-level CSS, add a style tag inside the head tag

    <head>
      <style>
        div {
          color: red;
        }
      </style>
    </head>
    Copy the code

    3. External CSS file (recommended), we create an external file with the suffix. CSS and then import the external CSS file into the HTML.

    Add a link tag inside the head tag.

    <head>
      <link rel="stylesheet" href="index.css">
    </head>
    Copy the code

    4. Introduction of import (deprecated)

    There are two ways to write it:

    1. Write a style tag inside the head tag. In the first line write @import URL ().

    2. Use it in the CSS

    @import URL (CSS file path)

    This method of introduction has several disadvantages that cause it to be deprecated now:

    1. Import rules must be written before any other CSS rules except @charset. If there are more than one CSS rules, they will be invalid.

    The following will not work:

    <style type="text/css">
      div {
        color: orange;
      }
      @import "import.css";
    </style>
    Copy the code

    2. When the program reads an import, it ignores the import and waits until all the HTML content, including images, has been loaded before loading the IMPORT CSS file. That is, the CSS files imported by import are loaded synchronously with the HTML.

    It is recommended to use the link tag to import external CSS files

    The advantages are as follows:

    1. It’s good for SEO. Referencing external CSS files makes HTML pages much less source code and search engines much faster.

    2. The browser can enable multi-threading at the same time to download HTML and CSS, the loading speed is generally faster.

    3. Style file separation, more convenient to modify the style, especially the CSS style shared by the whole site, just modify the common CSS file on the line.

    CSS selectors

    The CSS selector lets you find the element you want to style, and then style it.

    There are many kinds of selectors:

    1. The id selector

    We add an ID attribute to the element. This ID is a unique identifier. An element can only have one ID, and an ID can only be given to one element in principle. This element can then be selected in the CSS file by #id {}.

    <style>
      #demo {
        color: red;
      }
    </style>
    
    <div id="demo"></div>
    Copy the code

    Class class selector

    We add a class attribute to an element. This attribute adds a class name to the element. Each element can have multiple class names, and the same class name can be assigned to multiple elements. We can then select the element with the class name in the CSS file by using.class {}.

    <style>
      .demo {
        color: red;
      }
    </style>
    
    <div class="Demo"></div>
    Copy the code

    3. Label selector

    The tag name allows you to select elements directly.

    <style>
      div {
        color: red;
      }
    </style>
    
    <div></div>
    Copy the code

    4. Wildcard selector *{}

    All tags will be selected.

    5. Property selector

    [class=”demo”] {} [class=”demo”] {}

    6. Parent selector (derived selector)

    div p {}

    Style the p below div.

    In practical development, parent-child selectors are usually no more than 4 layers because of the performance of the selectors.

    No more than four layers like.wrapper.box. Content. Name.

    7. Direct child element selector

    Div >strong, the direct child of div must be strong to be selected.

    <div>
      <strong></strong>
    </div><div>
      <em>
        <strong></strong>
      </em>
    </div>
    ×
    Copy the code

    The previous examples are all parent selectors for tag combinations. You can also use parent selectors for id, class, etc.

    8. Parallel selectors

    <p class="select"></p>
    <div class="select"></div>
    Copy the code

    How do I select a div whose class name is SELECT?

    We can use div.select {} to select

    Div and.select are selected only if they are applied to the same element.

    9. Grouping selector

    <p></p>
    <strong></strong>
    <em></em>
    <div></div>
    Copy the code

    Div, p, em, strong {} is used to select all four tags and apply the same style.

    The priority of the selector

    If we add! To the separate style! Important, the style will be given the highest priority and will not be overwritten or modified by any subsequent additions. Background-color: red! important; Background-color is always red.

    This shows that selectors have priority, and a higher-priority selector overrides the styles of a lower-priority selector.

    Common selectors have a priority of:! Important > header styles (through the label style attribute set) > id > class | > * attribute > tag

    We also need to remember the weight value of each selector

    CSS selector weights

    ! Important infinity

    Interline style 1000

    id 100

    Class, property, pseudo class 10

    Tag, pseudo-element 1

    The wildcard 0

    Unlike math, CSS selector weights are infinite + 1 > infinity.

    With the selector weights, we can calculate the weights of the parent and child selectors.

    div p{}Copy the code

    The weight of this selector is the sum of div + P (the two label selectors).

    One final note:

    1. Instead of adding an ID to the tag, we select the tag by adding the class name, because id is a unique identifier, and we use the ID to tag the tag.
    2. When we write class names, we must pay attention to the semantics of the name, do not use a meaningless class name such as ABC.

    Simple text styles

    There are so many STYLES of CSS that it’s impossible to remember them all. We recommend keeping a few common styles in mind and looking up others when you need them.

    First, styles are made up of property names and property values, separated by (colon), and properties and properties separated by (colon). (semicolon) to separate.

    Let’s start with a few typeface related styles.

    p {
      font-size: 20px; // Font sizefont-weight: bold; // Font sizefont-family: "Times New Roman", Georgia, Serif; // Font seriesfont-style: italic; // Font stylecolor: red; // Font color}Copy the code

    1.font-size

    Set the size of the text. The default is 16px. This property sets the height of the text, not the width.

    2.font-weight

    The default value is normal. When bold is set to bold, the P tag is no different from the strong tag. This is why we don’t use many tags, because we can change the style to look like any other tag.

    Its values are:

    Normal Default value Bold characters. Bolder a bolder character. Lighter is a thinner character. 100, 200, 300, 400, 500, 600, 700, 800, 900 define characters from thin to bold. 400 is the same as normal, and 700 is the same as bold.

    3.font-family

    Set the style of the text, be it bold, 宋体, or something else, the default is arial.

    4.font-style

    Set whether the text is italic, italic means italic, by setting this property we can make the P tag to achieve the same effect as em tag. It can use italic, slant, or normal fonts.

    5. Color attributes

    Sets the color of the text

    Color values can be expressed in three ways.

    1. English words, such as red, black, blue, etc.

    2. Three hexadecimal optical primary colors red, green and blue, each with the value 00-ff, 00 represents empty, ff represents full, for example, #000000 means black. If the two digits in a row are the same, and all three groups of numbers are the same, we can combine them by two and write only one value, such as # FFFFFF — > # FFF, # 55FFcc — > #5fc.

    3. Use RGB (xx,xx, XX) attribute value to set the color, in fact, and the second is the same meaning, but changed the hexadecimal decimal, RGB is the abbreviation of red, green, blue, three values each range is 0-255, for example, red is RGB (255, 0, 0).

    Let’s look at some other simple styles.

    6.text-indent

    Set the indentation of the first line of text in two units: px and em.

    Here’s the difference between EM and PX.

    Although px is not an absolute unit of length, and may be displayed differently on different devices, it can be interpreted simply as a unit of roughly fixed length.

    Em is a unit of length relative to the size of the text in the current element, i.e. 1em = 1 * font-size. If we set font size to 20px, 1em is 20px. Just set text-indent to 2em to make the first line indent 2 text size.

    7.border

    border: 1px solid red; , sets the element border style.

    This is actually a composite properties, it is by the border width, border style, the border – color three properties of composite, respectively, set the width of the border, border style, the color of the border. Among them, there are many types of bounding styles, including solid (solid line), dotted (short line) and dashed (long dashed line).

    Border-width is also a compound property that sets the width of the four borders in terms of top, right, bottom, and left.

    8.text-align

    Sets the position of the text. There are three values: center(center), left(left aligned), and right(right aligned).

    9.line-height

    Sets the height of a line of text. Default is the same as the font size.

    When we want to center a single line inside the container, we simply set height = line-height.

    10.text-decoration

    For the meaning of text decoration, you can set whether the text has underline, underscore and underscore. The corresponding property values are underline, overline and line-through respectively.

    11.cursor

    Sets what our mouse will look like when we hover over this element.

    Cursor: pointer; cursor: pointer; This property, which allows us to move the mouse over the element into a clickable hand state.

    Now we can simulate the style of the A tag.

    <style>
      p {
        color: rgb(0.0.238); 
        text-decoration: underline;
        cursor: pointer;
      }
    </style>
    
    <p>www.baidu.com</p>
    Copy the code

    pseudo-classes

    Let’s talk about pseudo classes.

    We can do this by adding pseudo classes after the tag name.

    1. The hover pseudo class

    This pseudo-class sets the style of the element when the mouse moves over it.

    <style>
      a:hover { 
        font-size: 20px;
        color: # 424242; 
      }
    </style>
    
    <a href="www.baidu.com">www.baidu.com</a>
    Copy the code

    By setting such a pseudo-class for the A tag, we can make the text zoom in (the color doesn’t change) when the mouse moves over the A tag.

    Pseudo class of course more than hover one, there are a lot of other pseudo class, here is not an introduction.

    Pseudo-classes also have weights, which have the same weight value as class, 10.

    The cursor will only enlarge the text and not change color, because the weight value of the line style is 1000, and the a+hover value is only 1+10=11.

    The box model

    We need to know that an element is composed of four parts: margin, border, padding, content, respectively, are the margin, border, inside margin, content area. Content is not made up of properties, it’s made up of what we write and the width and height properties.

    Margin: This sets the distance of this element from other elements outside it or from the browser border. Margin-top, margin-right, margin-bottom, margin-left: this is a compound property, which is actually made up of margin-top, margin-right, margin-bottom, and margin-left. Of course, you can set the value of each property separately.

    The value of this compound attribute can be written in four ways:

    1.margin: 10px 20px 30px 50px; Set the four margins in the order of top, right, bottom, and left.

    2.margin: 10px 20px 30px; Set the four margins in the order of up, left, and down, with the middle property setting the left and right margins.

    3.margin: 10px 20px; Set the four margins in the order of up, down, left, and right.

    4.margin: 10px; That’s the value in all four directions.

    Margin actually does not belong to the model part of a box. The box model of an element only includes border, padding and content.

    To view the style of the element, right-click on the element and click Check or View, or hold down F12 (Windows). The element’s box model also appears at the bottom.

    Margin merge and collapse

    CSS also has its drawbacks. There are more or less “bugs” in CSS, some of which we may never encounter, and some of which we may encounter frequently. This section introduces two classic “bugs”.

    Margin merging

    We write two span tags and apply margin-right and margin-left styles to each of them.

    <style>
    .left {
      margin-right: 10px;
      background-color: red;
    }
    .right {
      margin-left: 10px;
      background-color: yellow;
    }
    </style>
    
    <span class="left">left</span>
    <span class="right">right</span>
    Copy the code

    The distance between the two spans is exactly what we want it to be 20px,

    Let’s write two divs and apply margin-bottom and margin-top styles to them.

    <style>
    .top {
      margin-bottom: 10px;
      background-color: red;
    }
    
    .bottom {
      margin-top: 10px;
      background-color: yellow;
    }
    </style>
    
    <div class="top">top</div>
    <div class="bottom">bottom</div>
    Copy the code

    This time we were surprised to find that the distance between the top and bottom of the two divs was only 10px, not 20px as we thought.

    This phenomenon is margin merging.

    If we try to change the margin-top or margin-bottom value of each div, we will find that the distance between them is the maximum of the two values.

    Margin collapse

    This bug occurs when we set margin-top to two parent divs.

    <style>
      .wrapper {
        width: 100px;
        height: 100px;
        margin-top: 100px;
        margin-left: 100px;
        background-color: yellow;
      }
    
      .content {
        width: 50px;
        height: 50px;
        margin-top: 50px;
        margin-left: 50px;
        background-color: red;
      }
    </style>
    
    <div class="Wrapper">
      <div class="Content"></div>
    </div>
    Copy the code

    We wrote this code to want a div of 100100 size and a child div of 5050 size inside. This div is in the lower right corner of the parent div, and the parent div is 100px away from the browser border.

    However, the actual result is not like this, the margin-left of the child div is displayed normally, but the margin-top effect is not what we expected, the distance from the parent div is 50px.

    Since the child div is 50px away from the browser border, the parent div itself has a margin-top value, so the effect of our child’s margin-top is not visible. If we change the margin-top value of the parent div to 200px, we are surprised to find that the child div does not have a distance from the parent div, but drives the parent div to move down together! This is margin collapse.

    solution

    The answer is to trigger the BFC.

    BFC is block Format Context. We have some CSS syntax that triggers the BFC, and the rendering rules of the elements that trigger the BFC will be different from the rendering rules of ordinary elements, which can solve the collapse problem.

    We can use the Overflow property to trigger the BFC.

    Overflow is a CSS property that sets what to do when the content area exceeds the current element’s area, and this property can also trigger a BFC.

    We now add a property to the parent div.wrapper: overflow:hidden;

    This property means overflow hiding. Now we see that the child div and parent div are unbound and probably moving normally, without changing their appearance! Generally, we can adopt this approach to solve the problem of margin collapse.

    Although the overflow: hidden; Once we change the location of the child div with JS code, part of the content of the child div will be hidden because of overflow.

    After understanding the solution of margin collapse, we can easily understand the solution of margin merge.

    We add a parent wrapper to each div and overflow:hidden;

    <style>
    .wrapper{
      overflow: hidden;
    }
    
    .top {
      margin-bottom: 100px;
      background-color: red;
    }
    
    .bottom {
      margin-top: 100px;
      background-color: red;
    }
    </style>
    
    <div class="wrapper">
      <div class="top">top</div>
    </div>
    <div class="wrapper">
      <div class="bottom">bottom</div>
    </div>
    Copy the code

    This solves the problem of margin merging by triggering the BFC via the parent div.

    Location and layer model

    Layer model

    The hierarchical model of elements in CSS is primarily determined by the position property.

    Position is static, absolute, relative and fixed.

    1.static

    Static is the default, and the element’s default position is static when we don’t write position.

    2.absolute

    Absolute: An element is removed from its original position. When an element is removed from its original position, other elements cannot see the element. Absolute can also trigger BFC.

    When we change the positioning, the element has four attributes to use: left, right, top, and bottom. These four attributes set the distance of the current element to the left, right, top, and bottom, respectively. These four attributes rarely appear together, usually in pairs, where left and top are a pair and right and bottom are a pair.

    <style>
      div {
        width: 100px;
        height:100px;
        backgroud-color: red;
        position: absolute;
        left: 100px;
        top: 100px;
      }
    </style>
    Copy the code

    The div will be removed from its original position and placed 100px away from the top and left edges of the browser.

    Absolute The reference is to its nearest positioned (non-static) parent. When no parent is positioned, the element is positioned relative to the browser border.

    3.relative

    “Relative” means relative position, and it allows an element to remain in its original position before being positioned, so that subsequent elements can see their original position.

    When position is changed to relative, the positions of left, top, right and bottom will be shifted relative to their own positions. The reference for relative positioning is the element itself.

    When we only set position:relative to the element without setting the left, right, top, and bottom attributes, the element’s positioning does not change at all. Because of this feature, relative is generally used as the setting reference in development. To move an absolute element relative to that element, set relative to that element.

    Let’s look at the difference between absolute and relative by example.

    We now have a structure like this:

    <style>
      .wrapper {
          width: 200px;
          height: 200px;
          background-color: orange;
          margin-top: 100px;
          margin-left: 100px;
      }
      .box{
          width:100px;
          height: 100px;
          background-color: black;      
          margin-left:100px;
      }
      .content{
          width: 50px;
          height: 50px;
          background-color: yellow;
      }
    </style>
    
    <div class="wrapper">
      <div class="box">
        <div class="content"></div>
      </div>
    </div>
    Copy the code

    Now let’s style content with absolute positioning.

    <style>
      .content{
        position: absolute;
        left: 50px;
        width: 50px;
        height: 50px;
        background-color: yellow;
      }
    </style>
    Copy the code

    At this point the little yellow square content is going to go outside the orange square.

    This is because when we set position: Absolute to the content, the content is positioned relative to the browser border since no parent element is positioned, so the content’s left attribute is 50px relative to the left side of the browser border.

    If we change the position of “content” to “relative”, the yellow square is in the upper left corner of the black square, and “relative” is positioned relative to its position, the “left” attribute means that it has moved 50px to the right from where it was in the upper left corner of the black square.

    So, to summarize the characteristics of absolute and relative:

    Absolute:

    1. Move out of the original position

    2. Position relative to the nearest positioned parent or, if not, relative to the browser border.

    Relative:

    1. Retain the original position

    2. Positioning relative to their original position is generally used to set reference objects

    4.fixed

    Fixed positioning is relative to the viewport positioning, we have seen on the web page on both sides of the left and right do not scroll with the mouse wheel and change the position of the advertising bar, is fixed positioning.

    <style>
      .fixed {
        position: fixed;
        right: 0px;
        top: 200px;
        height: 200px;
        width: 50px;
        background-color: red;
      }
    </style>
    
    <div class="fixed"></div>
    Copy the code

    Fixed the fixed element will remain to the right of the viewport and will not change position relative to the viewport as the scroll wheel moves.

    With positioning in mind, we can center elements horizontally and vertically.

    <style>
      div {
        width: 100px;
        height: 100px;
        position: absolute;
        left: 50%;
        top: 50%;
        margin-left: -50px;
        margin-top: -50px;
        background-color: red;
      }
    </style>
    Copy the code

    The div will be centered horizontally and vertically within the positioned parent.

    We can also implement a multi-column layout.

    <style>
      * {
        margin: 0px;
        padding: 0px;
      }
      div {
        height: 100px;
      }
      .left {      
        position: absolute;
        left: 0;
        width: 100px;
        background-color: yellow;
      }
      .right {
        position: absolute;
        right: 0;
        width: 100px;
        background-color: green;
      }
      .mid {
        margin-left: 100px;
        margin-right: 100px;
        background-color: red;
      }
    </style>
    
    <div class="left"></div>
    <div class="right"></div>
    <div class="mid"></div>
    Copy the code

    We first fixed the two divs on the left and right, and then asked the middle div to leave a fixed margin for the left and right, so that we can adapt to the screen size to achieve a three-column layout effect.

    Floating model

    Floating model

    Let’s first write a secondary structure:

    <style>
      .wrapper {     
        width:400px;      
        height: 100px;      
        border: 1px solid red;
      }
      .content {      
        width: 100px;      
        height: 100px;
        background-color: black;
        color: white;
      }
    </style>
    
    <div class="wrapper">
      <div class="content">1</div>
      <div class="content">2</div>
      <div class="content">3</div>
    </div>
    Copy the code

    Now we add a special property to the Content: float

    <style>
      .content {      
        width: 100px;      
        height: 100px;
        float: left;
        background-color: black;
        color: white;
      }
    </style>
    Copy the code

    The.content elements are queued like stations, which is what the float property does.

    Let’s formally introduce the float property

    The float property allows elements to float like a queue. It causes elements that fill an entire row to line up within the parent level only by content and size. When there is not enough space for one more element in the row, the element wraps and floats on the next line. When the container is not large enough, the contents will go out of the container, but they will still follow the same formation.

    Float elements are removed from the document flow like absolute elements, but not from the text flow.

    Let’s take an example:

    <style>
      .top {      
        width: 100px;      
        height: 100px;      
        background-color: red;      
        float: left;
      }
      .bottom {      
        width: 200px;      
        height: 200px;
        background-color: black;
        color: white;
      }
    </style>
    
    <div class="top"></div>
    <div class="bottom">I am the text, I can see the text flow yo ~</div>
    Copy the code

    Out of the flow means that normal elements can’t see it, which is very similar to the absolute property. In out of the flow means that elements whose display property is inline or inline-block can still see it, and the text itself is inline.

    Next, let’s say the bottom div display is inline-block, and let’s see what that looks like.

    <style>
      .bottom {      
        width: 200px;      
        height: 200px;
        background-color: black;
        color: white;
        display: inline-block;
      }
    </style>
    Copy the code

    We notice that the black square below is not moved to the next row, but is aligned with the red floating square, but we have no floating effect on the black square.

    This is because the float property automatically changes the element’s display to inline-block. That is, as long as the float property is present, the element’s display is inline-block, which is why the red float box does not have an exclusive row.

    The float property has only two values: left and right, and the default state is None.

    The effect of right is to line up from the right, and the opposite is true of left.

    Let’s summarize the float property

    1. You can float elements like absolute, creating your own unique floating flow.

    2. Out of the standard document flow, but not out of the text flow. Normal elements cannot see it, but elements with text attributes inline or inline-block can see it.

    3. Internally change the element to display: inline-block.

    In development, you can generally use the float property for mesh layout. When we do not know how many children will be in the container, but they are arranged in the same format, we can set the float to flow the layout. The float property also allows us to create a newspaper-like effect with text surrounding the image.

    So how do you clean up floating flows?

    We said that once the element is floating, the normal element cannot see it, and the parent cannot see it either. We want the parent to adjust the width and height according to the floating child elements. If we do not clear the float, the parent will only have one line left.

    So how do you clear the float?

    1. Let’s explain the principle in a non-standard way first. We add a P tag at the end of the content area in the parent level.

    <div class="wrapper">
      <div class="content">1</div>
      <div class="content">2</div>
      <div class="content">3</div>
      <p class="clear"></p>
    </div>
    Copy the code

    Let’s add a clear float style to the P tag:

    <style>
      .clear {
        /* The clear property is used to clear floats, although there are also left and right values, we usually write both values to clear floats. * /
        clear: both;
      }
    </style>
    Copy the code

    At this point, the parent wrapper has already wrapped the child element properly.

    But in fact, instead of the parent clearing the floating stream, it is propped apart by P, so the P.clear tag can see the floating element above, and the Wrapper can see the p tag without floating, so it wraps the P tag inside, and that’s it.

    We should know that the HTML tag is to do structural planning, the P tag is only to clear floating function, does not have the paragraph semantics of the P tag, this code is not standard in HTML, so it is not applicable.

    So we use the method of adding pseudo-elements

    Let’s start with pseudo-elements.

    A pseudo-element is an element that cannot exist alone and must be attached to other element tags. There are two commonly used pseudo-elements: after and before.

    <style>
      span {
        background-color: yellow;
      }
      span::before {
        content: 'before';
        background-color: red;
      }
      span::after {
        content:'after';
        background-color: black;
      }
    </style>
    
    <span>test</span>
    Copy the code

    The after and before elements are useful when we want to add something to the HTML without changing the structure.

    Notice that if you’re writing pseudo-elements, even if the content is empty, you have to add the content property content:””.

    We can change the display of a pseudo-element to a block, so that we can change the style of a large block element.

    Now that we know about pseudo-elements, we can use the first method to add an after pseudo-element to the parent element, which is specifically designed to clear floats:

    <style>
      .wrapper::after {
        content: ' ';
        clear: both;
        display: block;
      }
    </style>
    Copy the code

    This is the method we usually use to clear the float.

    However, in IE6, IE7 there is no such thing as false elements, how to do?

    HasLayout is a unique feature of IE6 and IE7. Simply triggering hasLayout has the same effect as triggering the BFC, which can be triggered using the Zoom property.

      .wrapper {
        /* If the viewport is scaled up or down, 1 is the same */
        zoom: 1;
      }
    Copy the code

    When we write this element, IE6 and IE7 can also clear the float.

    This property is only for IE6 and IE7. In this case, we need a bit of CSS hack. We add a * in front of zoom. This symbol can only be recognized by Internet Explorer 6 and Internet Explorer 7, other browsers are not recognized, so you can let Internet Explorer 6 and Internet Explorer 7 to read this line of attributes, other browsers directly ignore. By the way, with “_” in front of the attribute, only IE6 can recognize it (_zoom: 1).

    We can also trigger the BFC to clear the float

    There are many attributes that can trigger a BFC:

    ① Add overflow:hidden to.wrapper; You can have a parent wrap around a floating child element.

    ② Add display: inline-block to.wrapper; You can have the parent completely wrap the floating child element.

    ③ Add position to.wrapper :absolute; You can have the parent completely wrap the floating child element.

    While all three methods clear floats, they all change the style and don’t conform to development specifications, so we basically don’t use them.

    After we learn the floating model, we can also use this way to achieve a three-column layout

    <style>
      .left {
        width: 50px;
        height: 50px;
        background-color: red;
        float: left;
      }
      .right {
        width: 50px;
        height: 50px;
        background-color: yellow;
        float: right;
      }
      .mid {
        margin-left: 50px;
        margin-right: 50px;
        height: 50px;
        background-color: green;
      }
    </style>
    
    <div class="left"></div>
    <div class="right"></div>
    <div class="mid"></div>
    Copy the code

    CSS background images and others

    Single line text overflow dot

    Overflow is when the text exceeds our specified range, the following text begins with “…” In the form of.

    It is accomplished by combining three properties:

    <style>
      div {
        width: 300px;
        height: 20px;
        background-color: red;
    
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
    </style>
    <div>Single line text overflow Test Single line text overflow test Single line text overflow test Single line text overflow test</div>
    Copy the code

    We can see the text overflow dot.

    Now let’s introduce these three properties

    1.overflow: hidden; Hide the parts of the text that overflow the container.

    2.white-space: nowrap; Keep the text line free. Text is newline by default.

    3.text-overflow: ellipsis; How to handle text overflow. The processing here is in dots.

    These three attributes can be used together to achieve a single line of text overflow dot function.

    Multi-line text overflow dot

    Multi-line text overflow dot CSS compatibility is not very good, requires the support of later versions of the browser, so some by calculating the text width and height, and then handwritten “…” The implementation.

    If we wanted to implement it as an attribute, we could write:

    <style>
      div {
        width: 100px;
        overflow: hidden;
        text-overflow: ellipsis;
        display: -webkit-box;
        -webkit-line-clamp: 3;
        -webkit-box-orient: vertical;
        background-color: red;
        color: black;
      }
    </style>
    Copy the code

    The -webkit- prefix here means the browser private properties of the WebKit kernel.

    The background image

    We know that the tag can display images, but if we want to write on the image, this tag is not very useful, so we need to use an attribute called background-image.

    background-image: url(a);Copy the code

    The url contains the image address, so that we can set the background image of an element, and then write the normal text inside the element.

    There are a few other attributes that modify the background image style:

    background-size

    Set the background image size.

    It has many values:

    1.cover

    We can tell the browser to fill our container with as many images as possible, cutting off the excess when the image is large.

    The filling mechanism is to scale up (or down) an image until its width or height equals the width or height of the element, see which way you can fill the entire element with one image, and then trim out the extra parts.

    2.contain

    Show as much information as possible about the image, and fill in the same image if there is room.

    Its filling mechanism is: after one edge is fixed, the other edge can be fully displayed, and the remaining part is filled with the same image.

    3. Set x and y pixel values

    background-size: 50px 50px;
    Copy the code

    This will force the browser to display the image as 50 by 50.

    The percentage of 4.

    background-size: 50% 50%;
    Copy the code

    Will make the image 50% of the width and height of the container, and the percentage of the child elements relative to the value of the attribute in the parent. For example, if the height of the parent is 100px, then 50% of the child is 50px.

    background-repeat

    Sets whether the background image can be repeated. The default is repeat. By default, when the container is much empty, the same image will fill the remaining space of the container.

    When the value is no-repeat, no image copy is filled regardless of how much space is left in the container.

    background-position

    Set the starting position of the background image, which also has a variety of values:

    1. The pixel

    background-position: 50px 50px;
    Copy the code

    The background image will be displayed from 50px x and 50px y on the container.

    2. The percentage

    .background-position: 50% 50%;
    Copy the code

    When 50% 50% is written, the image will appear right in the center of the container.

    》》》》》》》》

    js(ECMAScript 5)

    First JavaScript

    JavaScript first appeared in 1996 as part of the Netscape Navigator browser and was originally designed to improve the user experience of web pages.

    In order to unify JS, ECMA introduced the ECMA standard, so JS language can also be called ECMAScript. This chapter covers ECMAScript 5; ES6 will be covered in later chapters.

    Js has two characteristics

    1. Interpreted language, no code compilation, cross-platform.

    2. Single thread

    In browsers, JS has three main parts: ECMAScript, DOM, and BOM.

    1. ECMAScript: a javascript language that complies with the ECMA standard.

    2. DOM: Document Object Model, which can manipulate web pages.

    3. BOM: Browser Object Model. You can operate the Browser.

    The introduction of JavaScript

    There are two ways to introduce JavaScript into a web page.

    1. Script tags are embedded in the page

    We can either put a tag inside the tag or the tag that has a type attribute, which we assign to “text/javascript”, or we can leave the type attribute out, The browser defaults to this.

    After writing the tag, we can write js code in the tag.

    2. Import external JS files

    The script tag has a SRC attribute that can be imported into external JS files.

    A script tag can only write code in it or import external JS files, not both.

    We generally adopt the second method of introducing external JS files, structure (HTML), style (CSS), behavior (JS) separate, convenient maintenance.

    When the browser loads the HTML file, it asynchronously loads the link tag, but blocks the loading of the following content when the script tag is encountered, until the JS file is downloaded and executed.

    This leads to two problems

    1. If js manipulates the DOM, the page’s DOM has not been parsed, and JS manipulates the DOM in an error.

    2. If the JS file is large and the execution is slow, no content is displayed on the page.

    Therefore, we usually put the script tag on the last line of the body tag.

    Basic JavaScript syntax

    Variable declarations

    Js is a weakly data typed language. Variables of any type can be declared with the keyword var

    var  arr = [1.2.3];
    var num = 123;
    var string = "abc";
    Copy the code

    You can declare it first and assign it later

    var num;
    num = 123;
    Copy the code

    When we declare more than one variable, we usually use the following notation to save code

    var num1 = 123,
        num1= 123,
        num2 = 123;
    Copy the code

    Variable naming rules

    1. Start with a letter, underscore, or $.

    2. Variable names can include numbers.

    3. Do not use keywords or reserved words as variable names.

    Keywords are words whose syntax is defined by the system, such as var, window, if, else, etc.

    Reserved words are reserved words that may become keywords in the future, such as enum and abstract.

    Value types

    The values of JS data are mainly divided into two categories:

    1. The original value

    Number, String, Boolean, undefined, null

    Undefined means undefined and null means null.

    var demo = null;
    console.log(demo); //null
    var a;
    console.log(a); //undefined
    Copy the code

    2. The reference value

    There are: array array, object, function

    var arr = [1.2.3.4];
    var object = {
      name: "demo",}console.log(arr);/ / 1, 2, 3, 4
    console.log(object);// [Object Object]
    console.log(object.name);// demo
    Copy the code

    What’s the difference between these two data types?

    Here’s an example:

    var num = 123,
        num1 = num;
    num = 234;
    console.log(num);/ / 234
    console.log(num1);/ / 123
    
    // Num changes have no effect on num1 at all.
    
    var arr = [1.2.3],
        arr1 = arr;
    arr.push(4);
    arr.push(5);
    console.log(arr);/ / 1, 2, 3, 4, 5
    console.log(arr1);/ / 1, 2, 3, 4, 5
    Copy the code

    We find that we only change the value of ARR, but arR1 also changes, which is the first difference between the two data types.

    If we reassign arR to a new array, then arr1 is not the new array.

    arr = [1.2.3];// A heap space is recreated
    console.log(arr1);// [1, 2, 3, 4, 5]
    Copy the code

    Since the original value is stored on the stack and the reference value is stored on the heap, the assignment of the original value is to assign the contents of the value to another variable, but the reference value is not. Reference value of the variable name, existing in the stack, but the value is the inside of the heap, stack variable name is pointed to a heap, the heap memory that we assign a value at the beginning, when we write arr1 = arr is stacked arr1 pointing and arr point to the same space, so that when we change the content of the arr If you change the contents of the heap space, you change the value of arr1 that points to the heap space as well.

    Even if we reassign num to 234, we have created a new space in the stack and assigned 234. There is still room for 123, but there is no pointer to it.

    The second difference between the two data types is that the original value cannot be changed, and the reference value can be changed.

    var arr = [1.2.3.4];
    arr.length = 2;
    console.log(arr);/ / 1, 2
    var str = "1234";
    str.length = 2;
    console.log(str);/ / 1234
    Copy the code

    There is a wrapper class concept involved, which we will refer to later.

    Arithmetic operator

    1. The + operator

    Function:

    1. The function of addition in mathematics

    2. Concatenate strings

    A string added to any data becomes a string

    var num = 1 + 2 + "3";
    console.log(num);/ / 33
    Copy the code

    2. – operator

    The mathematical function of subtraction

    3. * operator

    Mathematical multiplication

    4. / operator

    The mathematical function of division

    5. % operator

    The function of taking remainder in mathematics

    6. = operator

    The assignment operator

    7. The = = operator

    Equal in the comparison operator is not strict equal, strict is equal to “===” three equal signs

    8. () operator

    As in mathematics, the bracketed parts take precedence

    var num = 1 + "2" + (1 + 1);
    console.log(num);/ / 122
    Copy the code

    9. The + + operator

    Self-incrementing, when written in front of a variable it increments by 1 before performing the operation, and when written after a variable it increments by 1.

    var num = 1;
    console.log(num ++);/ / 1
    console.log(num);/ / 2
    console.log(++num);/ / 3
    console.log(num);/ / 3
    Copy the code

    A similar operation is the — operator

    The + = operator

    How much to add to the variable

    var num = 1;
    num += 10;
    console.log(num);/ / 11
    Copy the code

    Similarly, -=, /=, *-, %=, etc

    Comparison operator

    The comparison operators are >, <, >=, <=,! =, ==, not strictly equal to, === strictly equal to.

    Here’s the difference between not strictly equal and strictly equal

    Not strict means that when we compare two data, they are converted into the same type of data before comparison, while strict means that two data are equal without data transformation.

    "2"= = =2//false
    "2"= =2//true
    Copy the code

    NaN is not equal to any data, including itself, but undefined is.

    NaN= =NaN//false
    NaN= = =NaN//false
    undefined= =undefined//true
    undefined= = =undefined//true
    var demo = !!"abc";//true
    Copy the code

    In this case, the demo is going to convert the data to a Boolean value, first to a Boolean value of false and then to a Boolean value of true.

    Logical operator

    Logical operators are && and | | (and and or)

    var demo = 1 < 2 && 3;/ / 3
    Copy the code

    The && will only be executed if it is true. If the first expression is wrong, the second expression will not be executed at all. If the previous expression returns true, then && is the result of the last expression (demo 3).

    | | role is as long as there is an expression is true, then the end, will not go behind, returned as a result, the correct expression as a result, if the previous expression is false, then return the result is the result of the last expression.

    var demo = 2 < 1| | -1= =1);//true
    Copy the code

    Am& can be used as a short circuit statement. For example, we can write simple if statements as am&, because the second expression will only be run if the first condition is true.

    if(flag) { console.log("hello"); };
    flag && console.log("hello");
    Copy the code

    | | has the effect of an initial value, sometimes we hope function parameters have an initial value, in the case of not use ES6 syntax, you can use or statement.

    function demo (example) {
      var example = example || 100;
    }
    Copy the code

    The default assignment in ES6 avoids this problem by ignoring the value of the argument we pass as a Boolean value that is false.

    function demo (example = 100) {}Copy the code

    The default value is false

    All values can be converted to true or false, there are so many values that can be converted to true, we just need to remember the values that can be converted to false, everything else is true.

    The default values are false: false, undefined, null, “”, NaN, 0(+0, -0).

    console.log(Boolean(undefined));//false
    console.log(Boolean(null));//false
    console.log(Boolean(""));//false
    console.log(Boolean(NaN));//false
    console.log(Boolean(0));//false
    console.log(Boolean(false));//false
    Copy the code

    Display type conversion

    The typeof operator detects the typeof data.

    console.log(typeof(123));//number
    Copy the code

    Typeof can return only 6 types:

    Number, string, Boolean, undefined, object, function

    • Both arrays and null types belong to object. Null is usually used as a placeholder for objects, so it falls under Object.

    • NaN is of type number. Nonnumber is also a type of number.

    • Typeof returns a string as a result

    1.Number(mix)

    This method converts other types of data to numeric types of data

    Number("123") / / 123
    Number(true) / / 1
    Number(undefined) // NaN
    Copy the code

    2.parseInt(string, radix)

    This method converts strings to integer numbers. The radix base is an optional parameter, which ranges from 2 to 36.

    When the argument string contains both a numeric string and other strings, it sees other strings and does not continue to convert numeric strings.

    parseInt("123abc345")/ / 123
    parseInt("abc123")//NaN
    parseInt("123")/ / 123
    parseInt("abc")//NaN
    parseInt(true)//NaN
    Copy the code

    The second parameter radix works by converting the number of the first parameter to decimal as if it were a number of base digits.

    var demo = 11;
    console.log(parseInt(demo, 16));/ / 17
    Copy the code

    3.parseFloat(string)

    This method is similar to the parseInt method, which converts a string to a floating point number. Again, it stops at the first non-numeric character, but since floating point data has a decimal point, it recognizes the first decimal point and the following digits, but does not recognize the second decimal point.

    parseFloat("123.2.3")/ / 123.2
    parseFloat("123.2" ABC "");/ / 123.2
    parseFloat("123.abc")/ / 123
    Copy the code

    4.toString(radix)

    This method is a method on an object that can be used by most data types (undefined and NULL have no toString methods), and it converts data to a string type, which involves some wrapping class knowledge. Radix is an optional parameter.

    var demo = 123;
    demo.toString();/ / '123'
    true.toString()//'true'
    Copy the code

    When we write the radix base, it means that we need to convert this number into a numeric string of several bases.

    var demo = 10;
    demo.toString(16)//a
    Copy the code

    5.String(mix)

    Converts any type to a string type.

    typeof(String(123));//string
    Copy the code

    6.Boolean(mix)

    Converts any type to a Boolean type

    Boolean(0);//false
    Boolean(undefined);//false
    Boolean(null);//false
    Boolean("");//false
    Boolean(NaN);//false
    Copy the code

    Implicit type conversion

    1.isNaN()

    This method checks if the data is non-numeric.

    isNaN(NaN);//true
    isNaN("abc");//true
    isNaN(123);//false
    Copy the code

    There’s an implicit conversion that calls the Number method for the argument you passed, and then sees if the result is NaN.

    2. Arithmetic operators

    ++ calls Number once and increments itself.

    var demo = "abc";
    demo ++;//NaN
    demo = "123";
    ++demo;/ / 124
    demo = "123"; demo++;/ / 123 rather than the "123"
    Copy the code

    The ++ is followed by the increment of one after the execution, but before the execution the Number is called for type conversion.

    3. Unary operators

    +, -, *, and/are all converted to numeric types before execution.

    var num = false;
    +num;/ / 0
    var demo = true;
    -demo;/ / 1
    var demo = "abc";
    +demo;//NaN
    1 * "2";/ / 2
    true * false;/ / 0
    false / false;//NaN
    true / false;/ / infinity infinity
    -true / false;//-infinity
    Copy the code

    4. Logical operators

    && and | | is the Boolean expressions call first, again with Boolean value judgment is true or false, but the result returned is itself the result of the expression.

    5.! Take the inverse operator

    The returned result is also the result of calling the Boolean method

    !"abc";//false
    Copy the code

    There are also comparison operators that do not convert

    === strictly equal to

    ! == strictly does not equal

    "123"= = =123;//false
    true= = ="true";// false
    1! = ="1";// true
    1! = =1;// false
    Copy the code

    Object creation method

    Objects can be created in one of three ways:

    1. Object literals

    var obj = {};
    Copy the code

    This approach, called literals, is the simplest and most common way to create objects.

    Properties are separated by commas. Each property has a property name and a property value, which are separated by colons.

    2. Constructor

    There are two kinds of constructors: the system’s built-in constructors and our custom constructors.

    Let’s start with the system’s built-in constructor

    The constructor for creating an Object is Object

    var obj = new Object(a);Copy the code

    With this statement, we create an empty object.

    This is the same as var obj = {}; The function of theta is the same.

    There are many other built-in constructors, such as Number, String, Boolean, and Array.

    We use custom constructors again

    Custom constructors are normal functions, and to distinguish them, we usually capitalize the first letter of the constructor.

    Here we declare a constructor, Person.

    function Person() {}
    Copy the code

    Now that we have the constructor, we can use the new operator to create objects.

    var person = new Person();
    typeof oPerson;//object
    Copy the code

    Here we created an object person, but now that object is empty because our constructor didn’t write anything, and we didn’t add any properties to the object.

    In addition, objects created with the new operator are not related to each other, even though they all use the same constructor.

    var person1 = new Person();
    var person2 = new Person();
    person1.name = "111";
    console.log(person2.name);//undefined
    Copy the code

    Person1 and person2 are not related; they are two separate objects.

    Inside the constructor we write some properties that the object has by default

    function Person() {
      this.name = "scarlett".this.age = 17
    }
    var person = new Person();
    person.name;//scarlett
    Copy the code

    Of course, constructors are functions, so they can pass arguments.

    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
    var person = new Person("scarlett".18);
    person.age;/ / 18
    Copy the code

    When you create an object, you only have this when you use the new operator.

    Why can we create mutually independent objects with the new operator?

    In fact, when we call the new operator, the new implicitly creates a this object in our constructor and finally returns this object, which is why we can create an object with new.

    function Person(name) {
      //var this = {};
      this.name = name;
      //retrun this;
    }
    Copy the code

    If we manually create an object at the beginning of the constructor, such as that, and then return that at the end, then the “this” in the constructor will be useless and we will assign the property to that instead.

    function Person (name) {
      var that = {
        name: "scarlett"
      };
      that.name = name;
      return that;
    }
    var person = new Person("demo");
    person.name;//demo
    Copy the code

    If we return the object at the end, then this is invalidated. This is still valid if the last display returns the original value.

    function Person() {
        var that = {};
        that.name = "that";
        this.name = "this";
        return 123;
    }
    var person = new Person();
    person.name;//this
    Copy the code

    Add, delete, modify, and check object attributes

    Increased 1.

    var obj = {};
    obj.name = "scarlett";
    obj.name;//scarlett
    Copy the code

    We can add new attributes and assign values to objects by using the object name + dot + attribute name.

    2. Change

    The modification operation is the same as the increment operation, just call the same property name and assign a new value.

    var obj = {
      name: "scarlett"
    }
    obj.name = "demo";
    obj.name;//demo
    Copy the code

    3. Check

    obj.name = 'demo';
    console.log(obj.name);//demo
    Copy the code

    4. Delete

    To delete an attribute, we need the delete operator

    var obj = {
      name: "scarlett"
    }
    obj.name;//scarlett
    delete obj.name;
    obj.name;//undefined
    Copy the code

    Enumeration of objects

    We know we can use the dot operator obj.name to view object properties, but there is another way:

    obj['name']
    Copy the code

    This allows us to traverse the object with the for-in operator.

    var obj = {
      name: "scarlett".age: 18.sex: "female"
    }
    for(var prop in obj) {
      console.log(prop + ":" + obj[prop]);
    }
    Copy the code

    Our for-In loop will fetch the property names in the order of the properties and assign them to prop, and the for-in loop will print out all the properties in the prototype together.

    Here we introduce three operators

    1.hasOwnProperty

    This operator checks to see if the current property is a property of the object itself. Properties in the stereotype chain are filtered out. Returns true if it is self, false otherwise.

    function Person() {
      this.name = "scarlett";
    }
    
    Person.prototype = {
      age: 18
    }
    var oPerson = new Person();
    for(var prop in oPerson) {
      if(oPerson.hasOwnProperty(prop)) {
        console.log(oPerson[prop]); }}Copy the code

    Thus, our for-in loop prints only its own name property and not the age property on the prototype.

    2. The in operator

    The purpose of this operator is to check whether an attribute is present in the object or its stereotype

    "name" in oPerson;//true
    "age" in oPerson;//true
    "sex" in oPerson;//false
    Copy the code

    3. Instanceof operator

    The purpose of this operator is to check whether the preceding object is constructed by the following constructor

    oPerson instanceof Person;//true
    oPerson instanceof Object;//true
    {} instanceof Object;//true
    {} instanceof Person;//false
    Copy the code

    It can also be understood as whether the stereotype of the later constructor is on the stereotype chain of the previous object.

    A wrapper class

    We mentioned earlier that primitive values cannot be changed, only objects have properties and methods, so what about this?

    var str = "abcd";
    console.log(str.length);/ / 4
    Copy the code

    Strings are supposed to be raw and have no attributes, but you can look at length here.

    This is where a knowledge called the wrapper class comes in.

    str.length
    Copy the code

    Before we call this line of code, STR will be wrapped as a string object, which will be destroyed after the line of code is executed.

    var str = "abcd";
    //var str1 = new String("abcd");
    str.length;//str1.length
    / / destroy str1
    Copy the code

    Str. length is str1. Str1 is an object that has properties and methods on it, and then you can print the Length property. After the str.length line is executed, the object str1 is destroyed.

    This is why str.length is still 4 after str.length = 2.

    var str = "abcd";
    //var str1 = String("abcd");
    str.length = 2;//str1.length = 2;
    / / destroy str1
    console.log(str);//abcd length is still 4
    Copy the code

    The same is true for other types of data. When we add attributes to raw values, we wrap them implicitly as objects, and then destroy the object after assigning the attribute value.

    var bool = true;
    bool.len = 4;
    console.log(bool.len);
    Copy the code

    Array declaration

    Arrays can be declared in one of two ways:

    1. Declare arrays literally.

    var arr = [];
    Copy the code

    2. Declare arrays via array constructors.

    var arr = new Array(1.2.3.4);
    console.log(arr);/ / 1 2 3 4
    Copy the code

    This is no different from the literal approach, but note that if we just write the number new Array(5) inside the constructor; Now, instead of saying that the first value is 5, we’re going to create an array of length 5.

    var arr = new Array(10);
    console.log(arr);// An empty array of length 10
    Copy the code

    Reading and writing arrays

    Js arrays are weakly typed arrays and are not as strict as other languages.

    Overflow is read as undefined

    var arr = [1.2];
    console.log(arr[3]);//undefined
    Copy the code

    Can overflow write

    arr[5] = 5;
    console.log(arr);/ / 1, 2,,, 5
    Copy the code

    Common methods of arrays

    Array methods can be roughly classified into two categories: those that do not change the array and those that change the array.

    1. Change the original array

    Change the original array methods mainly include: reverse, sort, push, pop, shift, unshift, splice

    • reverse

    Reverse is to reverse the array.

    • push

    Push is adding data at the end of the array.

    arr.push(4.5.1);
    Copy the code

    • pop

    Pop removes one bit of data from the back of the array and returns the deleted data with no arguments.

    The shift,

    Removes one bit of data from the front of the data and returns the data with no arguments.

    • unshift

    Add data to the front of the data in the same way as push.

    • splice

    This method stands for intercept. It takes three parameters. The first parameter is the position where the intercept starts, the second parameter is the length of the intercept, and the third parameter is a set of data that represents the data we want to add to the intercept position.

    var arr = [1.2.3.4.5];
    arr.splice(1.2.100.188);
    console.log(arr);//1 100 188 4 5
    Copy the code

    If we do not write the data to be added, the method becomes deleting the data from the array.

    If we truncate 0 and then add data, the method becomes adding data at a specific location of the data.

    The sort,

    This method stands for sort.

    It is sorted by default in lexicographical order.

    arr --> 1 2 5 4 3
    arr.sort --> 1 2 3 4 5
    arr --> a c b d
    arr.sort --> a b c d
    Copy the code

    We can also customize the collation rules

    arr.sort(function(a, b) {
      return a.age < b.age;
    })
    Copy the code

    The a’s and b’s represent any two digits in the array.

    No matter what the intermediate rules are, the system only cares whether the function returns a positive or negative value at the end.

    When it’s negative, it means a is in front and B is behind.

    When it’s positive, it means a is in the back and B is in the front.

    If we write it like this, it’s out of order:

    function (a, b) {
      var num = Math.random() - 0.5;
      return num;
    }
    Copy the code

    Methods that do not change the original array

    The main methods of not changing the original array are:

    concat,join

    • concat

    This method is used to join arrays.

    arr1 = [1.2];
    arr2 = [2.3];
    arr = arr1.concat(arr2);
    console.log(arr, arr1, arr2);//[1, 2, 3],[1, 2], [2, 3]
    Copy the code

    We find that arR is now a concatenated array of arr1 and ARR2, and that neither arR1 nor ARR2 has changed.

    Of course, if we want to concatenate multiple arrays, we can separate the arrays in concat with commas.

    arr3 = [5.5];
    arr = arr1.concat(arr2, arr3);
    Copy the code

    • the join

    This method is how to concatenate each piece of the array into a string.

    var arr = ["a"."b"."c"];
    var str = arr.join("-");
    console.log(str);//a-b-c
    Copy the code

    We can concatenate large numbers of strings with this method, and it performs better than concatenating strings with the + operator.

    Also, strings have a split operation as opposed to a join operation.

    Split is how to split a string into arrays.

    var str = "a-b-c-d";
    var arr = str.split("-");
    console.log(arr);//a b c d
    Copy the code

    Array deduplication problem

    Array.prototype.unique = function() {
      var obj = {},
        arr = [];
      for(var i = 0, len = this.length; i < len; i ++) {
        if(! obj[this[i]]) {
          obj[this[i]] = true;
          arr.push(this[i]); }}return arr;
    }
    arr = [1.1.2.3.4.2.5.6.undefined.undefined.null.null];
    console.log(arr.unique());
    Copy the code

    Here we use a simple hash structure. When this element is present once in our array, we mark the position of the element’s value as true in obj. If the value of the same attribute is present later, it will not be added to the new array because this position is already true, thus eliminating the duplicate effect.

    Of course, we generally don’t recommend modifying the array prototype directly, but this is for demonstration purposes only.

    ES6 array methods

    ES6 provides richer array methods, and here are a few that are often used

    • forEach

    This method changes the array by iterating through the elements of the array, each calling the method we passed in forEach without stopping.

    var arr = [1.2.3.4];
    arr.forEach(function(item, index) {
      arr[index] += 1;
    });
    console.log(arr); // [2, 3, 4, 5]
    Copy the code

    The map,

    This method is similar to forEach, except that map returns a new array. It also passes a specified method that is called once for every element in the array. But remember that the map method returns a value at the end.

    var arr = [1.2.3];
    var test = arr.map(function(item) {
      return item * item;
    });
    console.log(test);/ / [1, 4, 9]
    console.log(arr);/ / [1, 2, 3]
    Copy the code

    • the filter

    This method is used for filtering and returns a subset of the original array. We also pass a method that calls each element, but only elements that return true are added to the new array, and elements that return false are not.

    var a = [1.2.3.4.5];
    var b = a.filter(function(item) {
        return item > 2;
    });
    console.log(b);/ / 3, 4, 5
    Copy the code

    At the same time, filter() skips missing elements in the sparse array; its return array is always dense.

    var arr = [1.3.4];
    var b = arr.filter(function() {
      return true;
    });
    console.log(b);/ / 1, 3, 4
    Copy the code

    • every and some

    These are methods that iterate over arrays. They apply a specified function to the array and return true or false.

    Every returns true if each element is evaluated by the passed method.

    Some returns true whenever one element returns true.

    var arr = [1.2.3];
    console.log(arr.some(function(item) {
      return item < 3;
    }));//true
    console.log(arr.every(function(item) {
      return item < 3;
    }));//false
    Copy the code

    • reduce and reduceRight

    The reduce() and reduceRight() methods use specified functions to combine array elements into a single value, reduce from left to right and reduceRight from right to left. There are two arguments, the first is the method, and the second is the optional argument, which is the initial value of our final value.

    When we do not set the initial value, we use the value of the first element of the array as the initial value. However, an error is reported when the array is empty without an initial value.

    When we have an array with only one element and no initial value specified, or an empty array and an initial value specified, reduce simply returns that value without calling the function.

    var arr = [1.2.3];
    var sum = arr.reduce(function(x, y) {
      return x + y;
    }, 0);
    console.log(sum);//0 + 1 + 2 + 3 = 6
    var temp = [1];
    var temoOut = temp.reduce(function(x, y) {
      return x * x * y;
    });//1, this function is not called because the array has only one value
    Copy the code

    Array type detection

    In ES6, we have an isArray() method to check for arrays.

    In ES5, typeof operators, arrays, and objects all return Object, so arrays and objects cannot be distinguished.

    The constructor and instanceof operators can also be used for judgment, but they have hidden problems:

    Our Web browser may have multiple Windows or forms, each with its own JS environment and its own global objects. Also, each global object has its own constructor, so an object on one form cannot be an instanceof a constructor on another form, so neither constructor nor instanceof can really reliably detect array types.

    At this point we need code like this to check:

    Object.prototype.toString.call(arr) === '[object Array]'
    Copy the code

    This is the most reliable detection method in ES5.

    precompiled

    When we define a function later, it is also ok to use the function before defining it.

    We declare a variable with var in the back, and there is no error but undefiend when we call this variable in the front.

    These two phenomena are called function declaration promotion and variable declaration promotion in JS. Function declaration promotion is a kind of overall promotion, which will promote the function declaration and function body together to the front. Variable declaration promotion is a local promotion that only brings the declaration of variables forward, but does not bring assignment forward as well.

    They are all done in the pre-compilation phase.

    Js runs in three phases:

    1. Grammatical analysis

    2. The precompiled

    3. Explain execution

    Parsing: Before parsing THE JS code, the JS engine scans the entire text to find low-level syntax errors, such as wrong braces.

    Interpretive execution: We mentioned earlier that JS is an interpretive language, compiling line by line. When parsing is ok and precompilation is complete, the interpretive execution code begins.

    This section focuses on precompilation

    Before introducing precompilation, there are two important concepts to grasp.

    1. Implicit global variables.

    If a variable is assigned an undeclared value, it becomes an attribute of the global object Window

    window.a = 123;
    window.a === a;//true
    Copy the code

    or

    a = 123;
    window.a === a;
    Copy the code

    2. All declared global variables are properties of window.

    var a = 123;
    console.log(window.a);/ / 123
    Copy the code

    What’s the difference between the two cases?

    Declared global variables cannot be deleted by the DELETE operation, but undeclared global variables can be deleted.

    a = 123;
    delete window.a;
    console.log(window.a);// undefined
    console.log(a);// Uncaught ReferenceError: a is not defined
    var b = 123;
    delete window.b;
    console.log(window.b);/ / 123
    console.log(b);/ / 123
    Copy the code

    One of the drawbacks of ES5 is that we implicitly declare global variables because of this feature.

    function test() {
      var a = b = 0;
    }
    Copy the code

    In this code, a is declared, but B is not declared, and B becomes a global variable.

    With these two points in mind, let’s begin the formal introduction to the precompilation process

    The precompilation process is divided into the following four steps:

    1. Create an AO Activation Object.

    2. Find the parameter and variable declarations and add the variables and parameters to the AO object as property names with the value undefined. It is important to note that the function names of function declarations are not called variable declarations.

    3. Unify the parameter values with the parameter values.

    4. Find the function declaration in the function body, and use the function name as the attribute name. The value is the function body.

    Before a function is executed, it generates a context called an Activeaction Object, or AO Object.

    Can be imagined as

    AO = {}
    Copy the code

    This object is empty, but it has implicit properties that we can’t see, such as this, arguments, etc.

    This object is used to hold properties and methods that were generated in the previous four precompiled steps.

    Here’s an example:

    function test(a, b) {
      console.log(a); ƒ a () {}
      function a () {};
      a = 222;
      console.log(a); / / 222
      function b () {}; ƒ b () {}
      console.log(b);
      var b = 111;
      var a;
    }
    test(1);
    Copy the code

    Let’s go through the precompilation process to see why these values are printed.

    First step, create an AO object.

    var AO = {};
    Copy the code

    Second, find the parameter value and variable declaration, and assign the value to undefined

    AO = {
      a: undefined.b: undefined
    }
    Copy the code

    Third, unify the argument values with the parameter values. Attribute A is assigned to 1.

    AO = {
      a: 1.b: undefined
    }
    Copy the code

    Fourth, look for the function declaration and assign the function body to the property.

    AO = {
      a: function() {},
      b: function() {}}Copy the code

    This is what the AO object created during the pre-compilation phase looks like before explaining the execution

    At this point we can interpret the printed values

    Log a — > function () {}

    The second console.log a — > 222 is reassigned because a = 222 was executed.

    Log b — > function () {}

    Var b = function () {} this is not called a function declaration, this is a function assigned to b variable, b variable is a declaration.

    Such as:

    function fn(a) {
      a//function
      d//function
      var a = 123;
      a/ / 123
      function a() {}
      b//undefined
      var b = function() {}
      b//function
      function d() {}}Copy the code

    When you look for a variable declaration, you don’t care if the code inside it actually executes, you just look for all the variables.

    function test(b) {
      console.log(a)//undefined
      if(1 > 5) {
        var a = 123;
        function b() {}}console.log(a)//undefined
      console.log(b)//function
      var b = 234;
      console.log(b)/ / 234
    }
    test(2);
    Copy the code

    It will not print the first a but undefined, it will print the first a if there is no declaration of a, there is a declaration of a, if condition has nothing to do with finding variable declaration.

    Prototype and prototype chain

    The prototype

    Definition of a stereotype: A stereotype is a property of the function object that defines the common ancestor of the object produced by the constructor. Objects generated by this constructor can inherit the properties and methods of the stereotype. Prototypes are also objects.

    function Person() {}
    Copy the code

    We’ll start by defining a constructor. The Person.prototype property is the prototype of this constructor, which is inherent and whose value is an object.

    We can add properties and methods to Prototype, and each constructed object can inherit those properties and methods.

    Person.prototype.name  = "scarlett";
    Person.prototype.age = 17;
    var oPerson = new Person();
    console.log(oPerson.name);//scarlett
    console.log(oPerson.age);/ / 17
    Copy the code

    Although each object is independent, they have a common ancestor. When we access the property of this object, if it does not have the property, we will find its prototype up, and then access the property on the prototype.

    function Person() {
      this.money = 100;
    }
    Person.prototype = {
      money: 200
    }
    var oPerson = new Person();
    console.log(oPerson.money);/ / 100
    delete oPerson.money;
    console.log(oPerson.money);/ / 200
    Copy the code

    Here we have the oPerson object because it has a money property, so it doesn’t look for the money property in the prototype, so it prints 100. But when we delete our money property, it looks for the money property in the prototype, so it prints 200.

    Using prototype characteristics, we can extract common attributes.

    We can extract the public properties of every object into the prototype, so that when we use constructors to construct a large number of objects, we do not need to go through the constructor’s assignment statement multiple times, and we can directly look up the prototype when each object calls the property.

    How does the object view the prototype

    We mentioned that the constructor can view the prototype using the.prototype method, so how do we view the prototype on an object?

    We mentioned earlier that when we use a constructor to construct an object, we implicitly create a this object with a default attribute called __proto__. The value of this attribute refers to the prototype of the object.

    var this = {
      //xxx
      __proto__:Person.prototype;
    }
    Copy the code

    When looking for a property that the object does not have, the __proto__ property is first looked up. This property refers to the prototype, so you can continue looking for the property on the prototype.

    Person.money.prototype = 100;
    oPerson.__proro__.money/ / 100
    Copy the code

    Prototype is the constructor property, __proto__ is the object property, and it points to Prototype.

    How does an object view its own constructor

    In Prototype, there is an implicit property called constructor that records the object constructor.

    console.log(oPerson.constructor); // Person();
    Copy the code

    Prototype chain

    With a prototype, the prototype is still an object, so the object named a prototype naturally has its own prototype, so that the prototype and the structure of the prototype form the prototype chain.

    Gra.prototype.firstName = "scarlett";
    function Gra () {
      this.name = "grandfather";
      this.sex = "male";
    }
    var grandfoo = new Gra();
    grandfoo.word = "hello";
    Foo.prototype = grandfoo;
    function Foo() {
      this.age = 18;
      this.money = 100;
    }
    var father = new Foo();
    function Son() {
      this.name = "son";
    }
    Son.prototype = father;
    var son = new Son();
    
    console.log(son.firstName)// "scarlett"
    Copy the code

    This chain structure is called a prototype chain.

    The end of the prototype chain

    console.log(Gra.prototype);// Object{"name": "scarlett"}
    console.log(Gra.prototype.__proto__);//Object.prototype
    console.log(Gra.prototype.__proto__.__proto__);//null
    Copy the code

    Prototype (null) gra.prototype (Object. Prototype)

    In fact, most objects eventually inherit from object.prototype

    var obj = {};
    console.log(obj.__proto__ === Object.prototype);
    Copy the code
    var obj = new Object(a);console.log(obj.__proto__ === Object.prototype);
    Copy the code

    We don’t have a custom prototype Object; its prototype is Object.prototype.

    Therefore, the end of the prototype chain is object.prototype;

    But not all objects have archetypes.

    We can use the object.create method to create objects without prototypes.

    The object.create () method writes an argument that is passed in as the prototype of the Object.

    If we wanted to construct an object like var obj = {}, we could write:

    var obj = Object.create(Object.prototype);
    Copy the code

    We can also write a custom object and make it a prototype.

    var obj = Object.create({ name: "scarett" });
    console.log(obj.name);//scarlett
    Copy the code

    When we write the argument to null, we construct an object with no prototype.

    var obj = Object.create(null);
    console.log(obj.__proto__);//undefined
    Copy the code

    Add, delete, change and check the attributes on the prototype chain

    1. The new

    Person.prototype.a = 1
    Copy the code

    or

    person.__proto__.b = 2
    Copy the code

    2. Delete the

    Person.prototype.name = "father";
    function Person() {
      this.name = "son";
    }
    var person = new Person();
    delete person.name;
    console.log(person.name);//father
    Copy the code

    At this point, the Person object has no name property on it, so if we delete this property again, can we delete the property on the prototype?

    delete person.name;
    console.log(person.name);//father
    Copy the code

    It doesn’t, so the object can’t delete properties from the stereotype.

    This is the only way to delete

    delete person.__proto__.name
    Copy the code

    or

    delete Person.prototype.name
    Copy the code

    3. Modify

    If the property of an object is only present in the stereotype, when we change the value of the property of the stereotype through an object, the value of the property of all objects will also change.

    function Person () {}
    Person.prototype.arr = [1.2.3];
    var person1 = new Person();
    var person2 = new Person();
    person1.arr.push(4);
    console.log(person2.arr);/ / [1, 2, 3, 4]
    
    function Person () {}
    Person.prototype.name = 'init';
    var person1 = new Person();
    var person2 = new Person();
    console.log(person2.name);//init
    Person.prototype.name = 'person1';
    console.log(person2.name);//person1
    
    function Person () {}
    Person.prototype.name = 'init';
    var person1 = new Person();
    var person2 = new Person();
    console.log(person2.name);//init
    person1.__proto__.name = 'person1';
    console.log(person2.name);//person1
    Copy the code

    4. Look for

    We’ve talked a lot about searching.

    Finally, let’s look at an example:

    Person.prototype.name = "scarlett";
    Person.prototype.sayName = function() {
      console.log(this.name);
    }
    function Person() {
      this.name = "son";
    }
    var oPerson = new Person();
    oPerson.sayName();//son
    Copy the code

    One thing we need to remember is, who called this method, this in this method refers to the object that called it, so it prints son.

    inheritance

    1. Traditional form

    The inheritance used in this phase is the prototype chain inheritance we described earlier.

    But the downside of this inheritance is that it inherits too many useless attributes.

    2. Borrow constructors

    function Foo(name, age) {
      this.name = name;
      this.age = age;
    }
    function Son(name, age) {
      Foo.call(this, name, age);
    }
    var son = new Son("son".123);
    console.log(son.name);//son
    Copy the code

    This approach takes advantage of the fact that call and Apply can change the point to this and construct child objects indirectly through constructors.

    But this approach has two drawbacks:

    1. Strictly speaking, this approach is not inheritance and does not access the prototype of the prototype.

    2. It is inefficient to use two constructors every time an object is constructed.

    3. Share prototypes.

    Son.prototype = Foo.prototype;
    Copy the code

    Although this method allows the child constructor to access the stereotype chain without having to go through two constructors, the disadvantage is obvious: if you change the child’s stereotype, the parent’s stereotype will also change, because they are the same.

    4. Holy Grail mode

    This is the final stage and the way we are currently using it.

    function inherit(C, P) {
      function F() {}
      F.prototype = P.prototype;
      C.prototype = new F();
    }
    Copy the code

    Here we use an intermediate function F to connect the prototype of P and C, so that when we change the prototype of C, only F will be affected, not P.

    But there is a problem. When we want to see the constructor of the object constructed by the Child, it prints the Parent function.

    So we also need to record the constructor of the subclass.

    C.prototype.constructor = C;
    Copy the code

    The final form looks like this:

    function inherit(C, P) {
      function F() {};
      F.prototype = P.prototype;
      C.prototype = new F();
      C.prototype.constructor = C;
    }
    Copy the code

    Functions and closures

    Functions can be declared in two ways:

    1. Function demo () {

    2. Var demo = function () {

    Var demo = function XXX () {

    In fact, the second and the third kind of comparison, the second kind is called anonymous function expression, we usually use the first and the second kind of majority, rarely use the third kind.

    So the second type is simply called a function expression (XXX of the third type cannot reference a function).

    The AO object of each function has a class array property called Arguments, which holds arguments.

    function func (a) {
      console.log(arguments[0]);/ / 1
    }
    func(1)
    Copy the code

    Arguments [0] to view the first argument we passed.

    The function has a length attribute, which stores the number of arguments.

    Each function will have a return, and the function will automatically add a return if it does not write;

    Return has two functions:

    1. Return the execution result of this function.

    2. Terminate the function execution.

    The arguments. The callee and function. The caller

    Arguments.callee refers to the function itself.

    Arguments.callee when we recursively call the function itself from an anonymous function or instant-execute function, we can call it as arguments.callee because the function has no name.

    Function. caller, a property of the function itself, can indicate the function reference of the current function execution environment, i.e. the function body in which the function is executed.

    function test() {
      console.log(test.caller);
    }
    function demo() {
      test()
    }
    demo();//function demo(){}
    Copy the code

    scope

    Definition: variable (variable scope also called context) and function effect (can be accessed) area.

    Javascript functions can be scoped!

    In ES5, there are only two types of scope: global scope and function scope. In ES6, block-level scope was added.

    var demo = 123;// Global variables
    function test() {
      var demo = 234;// Local variables
      console.log(demo);
    }
    test();/ / 234
    console.log(demo1);/ / an error
    Copy the code

    If declaring a variable in a function scope does not use var, then you are declaring a global variable.

    Two different scopes (except for the global scope) are not mutually accessible.

    function demo1() {
      var str1 = "abc";
    }
    
    function demo2() {
      console.log(str1);
    }
    
    demo2();/ / an error
    Copy the code

    The scope chain

    Since functions have function scopes and functions can be nested, nesting relationships between scopes will naturally occur, and this is when the scope chain is generated.

    When code is executed in an environment, a scope chain of variable objects is created to ensure access to environment variables, functions, and ordered access.

    The top-level object of the scope chain is always the variable object of the environment in which the code is currently executing.

    function demo() {
      var demo_a = 1;
      function test() {
        var demo_a = 2;
        console.log(demo_a);
      }
      test();
    }
    demo();
    Copy the code

    In this example, the demo runs with a scope created first, but the Window itself has a global scope, which gives the Demo a scope chain. With privileged and ordered access to the execution environment, the scope of each function itself is always at the top of the scope chain, followed by the scope of the function’s parent, and then the parent’s parent, all the way to the global scope. So this example prints a value of 2.

    closure

    What is a closure?

    Closures are functions that can read variables inside other functions

    Different scopes cannot access each other, but if we define a function inside a function and the inner function is associated with the variables of the outer function, we can return the inner function and then access the variables of the outer function.

    A closure is a bridge that connects the inside and outside of a function.

    function func () {
      var demo = 1;
      return {
        add: function() {
          demo ++;
        },
        get: function() {
          returndemo; }}}var obj = func();
    obj.add();
    obj.add();
    console.log(obj.get())/ / 3
    Copy the code

    When the function is finished executing, the execution context of the function is destroyed and we cannot access the variables inside it. But we have this function returns a depends on the function of the new function, that is to say, this has not been destroyed the new function of still exist in the scope of the chain of the original function scope of reference, will lead to we originally the context of the function will not be destroyed, we call back this new function is the original function of the closure function.

    In the above example, we have a local variable demo inside the func function. We assign the return value of this function to a global variable obj, but the context of the func function is not destroyed because the new function in the return value depends on the original func function.

    Here we run obj.add() twice, and the final printed value is 3, indicating that the func variable a is not destroyed after the function is executed, but is stored in memory.

    The add function in this case acts as a setter accumulator, operating outside of the function on variables inside the function.

    Closures cause variables in a function to be kept in memory, so you can’t abuse closures.

    Execute function immediately

    Executing functions immediately is an important way to handle closures. Note, however, that there is no way to undo a closure; we simply eliminate the effects of the previous closure by creating a new closure.

    Definition: the immediate function does not need to be defined. It is executed directly and released immediately after execution.

    Often used for initialization.

    1.(function (a) {})(num);

    2.(function (a) {} (num));

    The parameter passed is a, whose argument value is num, which is the variable we define outside.

    They do exactly the same thing, but the standard version is the second.

    Function declarations cannot be executed, but function expressions can.

    function test() {} ();/ / error
    var test = function () {} ();// Expressions can also be written as immediate functions.
    Copy the code

    The first type of function can be executed immediately with a parenthesis.

    Handle closures using immediate execution functions.

    function returnB() {
      var arr = [];
      for (var i = 0; i < 10; i ++) {
        arr[i] = function() {
          console.log(i); }}return arr;
    }
    var save = returnB();
    for(var i = 0; i < 10; i ++) {
      save[i]();
    }
    Copy the code

    We end up with 10 tens, not the 0-9 we want.

    This is because the function in which we print I does not have the variable I in its scope, but only in its parent function returnB, and the 10 values arr[0]-arr[9] are closures. After the for loop is executed and I becomes 10, When we subsequently fire each save[I] (arr[0]-arr[9]) function, the function is looking for I in the parent function’s returnB scope, which has already become 10.

    So how can I change it to print 0-9? This is where we need to eliminate the problem of sharing a closure value by generating a new closure using an immediate function.

    function returnB() {
      var arr = [];
      for(var i = 0; i < 10; i ++) {
        (function(n) {
          arr[n] = function() {
            console.log(n);
          };
        }(i));
      }
      return arr;
    }
    var save = returnB();
    for(var i = 0; i < save.length; i ++) {
      save[i]()
    }
    Copy the code

    After executing the function immediately, a new scope will be created. We pass in the 10 numbers of I from 0 to 9 as arguments. This means that n in each scope is different, so it will print 0 to 9 normally.

    call/apply

    Use call/apply to change the this reference. The difference between call/apply is that the parameters are passed in different forms.

    function person() {
      this.name = "scarlett";
      console.log(this);
    }
    person();//window
    Copy the code

    This prints window.

    Let’s try using call

    var obj = {};
    person.call(obj);//{name: "scarlett"}
    Copy the code

    When the call method is used, the this inside the person function points to the obj object we passed.

    If we still need to pass arguments, we simply place the argument values after the call and separate them with commas.

    function person(name, age) {
      this.name = name;
      this.age = age;
    }
    var obj = {};
    person.call(obj, "scarlett".18);
    console.log(obj.name);//scarlett
    Copy the code

    The only difference between apply and call is that the parameters after call are passed one by one, while the parameters after apply are passed in an array.

    Again in the above example, if the arguments were passed by apply, they would look like this.

    person.apply(obj, ["scarett".17]);
    Copy the code

    This points to the

    In js this points to just remember these four points

    1. This — >window during precompilation

    2. This — >window in the global scope

    3. Call /apply can change this reference

    4. Obj.func () This in func() refers to obj

    Let’s take a few examples:

    var obj = {
      height: 190.eat: function() {
        this.height++;
      }
    }
    obj.eat();// This refers to obj. This refers to whoever called this.
    eat.call(obj);/ / this point to obj
    Copy the code

    If you understand this code, you should have a pretty good idea what this is pointing to.

    var name = "222";
    var a = {
      name: "111".say: function() {
        console.log(this.name); }}var fun = a.say;
    fun();/ / 222
    a.say();/ / 111
    var b = {
      name: "333".say: function(fun) {
        fun();
      }
    }
    b.say(a.say);/ / 222
    b.say = a.say;
    b.say();/ / 333
    Copy the code

    The first print calls fun(), which assigns the body of a.say to fun. In this case, we write a func function in the global space. The code inside is the code in a.say.

    The second print calls a.say(). As we said earlier, this refers to whoever calls the function, so this refers to a, so print 111.

    The third one is more complicated. It calls b.say(a.say)). When we call b.say(), this refers to B, but this is not in fun, but in say. This in fun refers to window during precompilation. So print 222.

    The fourth type, b.say = a.say, means exactly the same as the second type, so print 333.

    cloning

    The concept of cloning

    There are some differences between clone and inheritance, clone is a copy of a exactly the same target object, clone is divided into shallow clone and deep clone.

    Shallow clone

    The source object has the same properties as the target object:

    function clone(src, tar) {
      var tar = tar || {};
      for(var prop in src) {
        if(src.hasOwnProperty(prop)) { tar[prop] = src[prop]; }}return tar;
    }
    Copy the code

    When we have an attribute value that is a reference value (array or object), in this way, if we change the reference value of the source object or the target object, the other attribute value will also change, which is the disadvantage of shallow cloning.

    Deep cloning

    The principle of deep cloning is very simple, we just do not clone the reference value of the reference value, but also as a source object, the value of the inside of the clone into the target object.

    function deepClone(src, tar) {
      var tar = tar || {};
      for(var prop in src) {
        if (src.hasOwnProperty(prop)) {
          if (typeof(src[prop]) === "object") {
            tar[prop] = (src[prop] instanceof Array)? [] : {}; deepClone(src[prop], tar[prop]); }else{ tar[prop] = src[prop]; }}}return tar;
    }
    var src = {
      a: [1.2.3].b: {
        age: "18".sex: "male"}}var tar = {};
    var tar1 = deepClone(src, tar);
    src.a.push(4);
    src.b.name = "jiang";
    console.log(src);
    console.log(tar1)
    Copy the code

    Here we use recursive calls. When we detect that the attribute value in the source object is a reference type, we create a reference type attribute in the target object. If it is an array, create an array. If it is an object, create an object. Then clone the reference value in the source object as the new source object and the reference value in the target object as the new target object.

    An array of class

    We know that there are two kinds of data called arrays and objects, but we can actually simulate arrays with objects, which we call arrays.

    The arguments list we mentioned earlier is an array of classes.

    A class array is not an array, but it can behave like an array.

    var arrObj = {
      "0": 1."1": 2."2": 3."length": 3."push": Array.prototype.push
    
    }
    arrObj.push(4);
    
    console.log(arrObj);//{0: 1, 1: 2, 2: 3, 3: 4, length: 4}
    Copy the code

    So we’ve created a class array that behaves like an array.

    We’ll see that it automatically changes the length value, which is pretty amazing.

    In fact, the key of this class array is on the length attribute, if there is no length attribute, then it is an ordinary object, even if there is a push method can not be used.

    Let’s simulate the implementation of array push:

    Array.prototype.push = function(num) {
      this[this.length++] = num;
    }
    Copy the code

    The try… catch

    try{}catch (e) {
    
    } finally{}Copy the code

    It’s usually used to detect code that might go wrong.

    We put the block of code that might go wrong ina try, and then we put the code that should go wrong ina catch. Finally is the code that will go last.

    The parameter E of catch must be specified. The system will automatically send error messages. Generally, there are six kinds of error messages:

    EvalError eval() : uses a value inconsistent with the definition. 2.RangeError: uses a value that is out of bounds. 3. Operand type error 6.URIError, improper use of URI handler

    3 and 4 are common.

    When the code inside a try fails, the code behind the failed code inside the try will not execute, but the code outside the try will execute normally.

    try {
      console.log(a);
    }catch (e) {
      console.log(e);// ReferenceError: a is not defined
    }
    console.log(1);/ / 1
    Copy the code

    with

    With () {} changes the scope chain by placing the execution-time context or scope in parentheses at the top of its scope chain.

    var obj = { a: 123 };
    function test() {
      var a = 111;
      var b = 222;
      with(obj) {
        console.log(a);/ / 123
        console.log(b);/ / 222
      }
    }
    test();
    Copy the code

    Without with, the top of the scope chain in the test function would be itself, but with with, we put obj at the top of the scope chain.

    With changes the scope chain and affects performance. It is not recommended.

    ES5 Strict mode

    Es5 strict mode is a new ES5 specification, in which some of the ES3 non-standard rules cannot be used.

    We just say “use strict;” on the first line of the code. This line of string will enter strict mode and will not affect browsers that are not compatible with strict mode.

    Strict mode can also be divided into:

    1. Global strict mode

    2. Local strict mode

    Global mode is where we write the string in the first line of the whole JS code, and local mode is where we write the string in the first line of the function.

    Using strict mode forces our code to avoid some unrecommended syntax, such as:

    1. Disallow use of the with function, arguments.callee method, and func.caller attribute.

    2. Variables must be declared before assigning values.

    3. The local “this” must be assigned before being used. The default value for this is “Window”, and the others are undefiend by default. In non-strict mode, person. call(null/undefined) still points to window. But for strict mode, if you pass NULL, this points to NULL, and if you pass undefiend, this points to undefiend.

    4. Reject duplicate attributes and parameters. However, some browser property names can be duplicated.

    .

    》》》》》》》》》》》》》》》》》

    react

    React started as an internal Project at Facebook and was open-source in May 2013.

    React has several important features

    1. The virtual DOM

    Traditional Web pages typically manipulate the DOM directly, but DOM manipulation is performance-intensive. React introduces the concept of the virtual DOM. When the DOM needs to be updated, the DIff algorithm is used to calculate the minimum update operation of the virtual DOM and then the update is performed. Therefore, the virtual DOM has high performance.

    Since we haven’t learned the DOM chapter yet, you just need to think of it as an HTML tag (div, A, etc.).

    2. The modular

    The entire page is composed of components, making it easy to decouple and reuse functional units.

    3. Unidirectional data flow

    Data is passed and updated one-way from the outer component to the inner component, making the relationship between components simple and predictable.

    Environment set up

    The source code for all examples in this chapter can be viewed and debugged in The React-Demos.

    It only needs to clone the repository, run CNPM install in the root directory to install the dependency packages, and then run NPM run start to debug.

    Node.js is required to run the NPM and CNPM commands

    Node. js is easy to install. Go to the official website to download the long-term support version and install the latest version.

    However, we recommend installing NVM (Node Version Manager, which can switch between Node.js versions) as described in the pre-class overview.

    After installing Node.js, you can manage NPM using the packages that come with it.

    With NPM download directly depend on the package is very time-consuming connection (because is the foreign server), so I suggest you to switch to the taobao NPM mirror, perform NPM install – g CNPM, registry=https://registry.npm.taobao.org, This allows you to install dependencies using the CNPM command.

    Simple engineering construction

    Now that the environment is set up, let’s look at how the React-Demos simple project is set up.

    Let’s start by creating an empty folder called React-demos

    Use this folder as the root directory to execute NPM init and press Enter.

    Then run the dependency package installation command:

    CNPM install [email protected] [email protected] [email protected] [email protected] Babel-preset -stage-2@^6.24.1 [email protected] [email protected] [email protected] [email protected] --save-dev CNPM install [email protected] [email protected] --saveCopy the code

    Create a webpack.config.js file with the following contents:

    const path = require("path");
    const { WebPlugin } = require("web-webpack-plugin");
    
    module.exports = {
      mode: "development".entry: {
        // Modify the entry file to debug the code under different files
        app: "./src/01/index.js"
      },
      output: {
        path: path.resolve(__dirname, "dist"),
        filename: "[name]_[contenthash:8].js"
      },
      devServer: {
        open: true
      },
      module: {
        rules: [{test: /\.jsx? $/,
            include: [path.resolve(__dirname, "src")].loader: "babel-loader".options: {
              presets: ["react"."es2015"]}}]},plugins: [
        new WebPlugin({
          template: "./src/index.html".filename: "index.html"}})];Copy the code

    The configuration of WebPack will be described in a later chapter, so you can copy it here.

    Write your first React page

    Now that the project is set up, we can write react code.

    We create the code directory structure as follows:

    src
      01
        index.jsx
      02
        index.jsx
      03
        index.jsx
      ...
      index.html
    Copy the code

    We mainly write our code in the index.jsx file. 01, 02, 03… The directory is designed to make it easy to manage the sample code for different points in this chapter, so you can switch between them by changing the address of the webpack.config.js entry file.

    The index. HTML file, which we won’t touch, has the following contents

    <! DOCTYPEhtml>
    <html lang="zh">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
        <title>react demos</title>
      </head>
      <body>
        <div id="root"></div>
        <script src="app"></script>
      </body>
    </html>
    Copy the code

    Next, write the React code in the index.jsx file.

    // Import the required modules
    import React, { Component } from "react";
    import ReactDom from "react-dom";
    
    // Write a component
    class App extends Component {
      render() {
        // Const is similar to var in that it is the variable naming keyword in ES6. It names a constant.
        const text = 'test'
        / / JSX syntax
        return <div>{text}</div>; }}// Render the component to the page
    ReactDom.render(<App />.document.getElementById("root"));
    Copy the code

    Class App extends Component is the way react writes components. Our page is made up of components.

    The syntax for writing HTML directly in JavaScript is called JSX, and its basic syntax rules are: when an HTML tag (beginning with <) is encountered, use HTML rules to parse it; When you encounter a block of code (beginning with {), you parse it with JavaScript rules.

    Reactdom.render converts the component instance (
    ) to HTML and renders it to the specified DOM node.

    We’ll run NPM run start in the root directory and see that the browser automatically opens our first React page with test.

    Interline style and className

    The react element’s style property allows you to add in-line styles.

    import React, { Component } from "react";
    import ReactDom from "react-dom";
    
    class App extends Component {
      render() {
        const style = {
          color: "red"
        };
        return (
          <span className="text" style={style}>
            test
          </span>
        );
      }
    }
    
    ReactDom.render(<App />.document.getElementById("root"));
    Copy the code

    In development, we typically set the class name for the element (since class is a reserved word, we use className to set the class name), and then style the element in a separate style file using CSS’s class selector rather than using the style attribute, which decoupled the style file.

    this.props

    In a component, the this.props property is used to get the parameters passed to the component, and a change in props triggers the component to re-render (execute the render function).

    The native array map method can render a list. You need to add a unique identifier for Each child in the list. Otherwise, Warning: Each child in a list should have a unique “key” prop. Warning.

    import React, { Component } from "react";
    import ReactDom from "react-dom";
    
    class App extends Component {
      render() {
        const { arr } = this.props;
    
        return (
          <ul>
            {arr.map(item => (
              <li key={item}>{item}</li>
            ))}
          </ul>); }}const arr = [1.2.3];
    
    ReactDom.render(<App arr={arr} />.document.getElementById("root"));
    Copy the code

    The page now renders 1, 2, and 3.

    this.state

    State is the internal state of the component. React treats the component as a state machine. The state can be changed by calling the this.setState method, which triggers the component to rerender (the render function).

    import React, { Component } from "react";
    import ReactDom from "react-dom";
    
    class App extends Component {
      constructor(props) {
        super(props);
        this.state = {
          value: ""
        };
        this.ref = React.createRef();
      }
    
      onChange = () = > {
        this.setState({
          value: this.ref.current.value
        });
      };
    
      render() {
        const { value } = this.state;
        return (
          <div>
            <input ref={this.ref} onChange={this.onChange}></input>
            <span>{value}</span>
          </div>
        );
      }
    }
    
    ReactDom.render(<App />.document.getElementById("root"));
    Copy the code

    Tags in components are not real DOM nodes, but virtual DOM (DOM). It only becomes a real DOM when it is inserted into an HTML document.

    This example also shows how to get the actual DOM node from the component, which is how refs forwarding is used.

    Component life cycle

    A component is a state machine and its life cycle is divided into three phases:

    1.Mounting (Dashed box on the top)

    You will experience:

    GetDefaultProps Initializing props

    GetInitialState Initializes the state

    ComponentWillMount will be loaded

    Render to render

    ComponentDidMount is loaded, the updated DOM is available, and AJAX requests are called during this lifecycle

    Updating (dotted box in lower left corner)

    Once the component is loaded, it is in the run phase.

    When the state or props changes, the component is updated and re-rendered (performing the render function).

    The following life cycle will be followed:

    ShouldComponentUpdate (nextProps, nextState) returns a Boolean to determine whether to rerender. The default is true.

    ComponentWillUpdate (nextProps, nextState) will render

    render

    ComponentDidUpdate (prevProps, prevState) render

    We can notice that when the props changes, one more lifecycle function is passed:

    ComponentWillReceiveProps (nextProps) that will receive the new props, here you can get nextProps value (the final props value)

    3.Unmounting (Lower right corner dashed box)

    ComponentWillUnmount The component is to be unmounted, which usually does some cleaning operations, such as clearing timers.

    You can print the life cycle in the code

    import React, { Component } from "react";
    import ReactDom from "react-dom";
    
    class App extends Component {
      static defaultProps = {
        value: ""
      };
      constructor(props) {
        super(props);
        this.state = {};
      }
    
      componentWillMount() {
        console.log("componentWillMount");
      }
    
      componentDidMount() {
        console.log("componentDidMount");
      }
    
      render() {
        console.log("render");
        return null;
      }
    }
    
    ReactDom.render(<App />.document.getElementById("root"));
    Copy the code

    It will be printed in sequence in the console

    componentWillMount
    render
    componentDidMount
    Copy the code

    Ajax

    The data source for a component is usually obtained from the server via an Ajax request, which we call in the componentDidMount lifecycle method, and when the request succeeds, we use the this.setState method to store the data in the component’s state. At the same time, the state change triggers the UI to be re-rendered and the page to display the data.

    Child component passes data to parent component (communication)

    Because the React data flow is unidirectional, the parent component only needs to pass the parameter directly to its child component and then obtain the parameter through this.props, while the child component needs to use the callback function to pass the data to the parent component.

    import React, { Component } from "react";
    import ReactDom from "react-dom";
    
    class Child extends Component {
      render() {
        const { onClick } = this.props;
    
        return (
          <div>
            <button
              onClick={()= > {
                onClick(Math.random().toString());
              }}
            >
              child button
            </button>
          </div>); }}class Parent extends Component {
      constructor(props) {
        super(props);
        this.state = {
          text: ""
        };
      }
    
      onClick = text= > {
        this.setState({
          text
        });
      };
    
      render() {
        const { text } = this.state;
    
        return (
          <div>
            <Child onClick={this.onClick} />
            <span>{text}</span>
          </div>
        );
      }
    }
    
    ReactDom.render(<Parent />.document.getElementById("root"));
    Copy the code

    In this example, we define a callback function for the click event in the parent component and pass the child component through props. The click event of the child component calls the callback function and passes the data.

    this.props.children

    It represents all the child nodes of the component. Sometimes we need to reserve something for the definition of a component.

    import React, { Component } from "react";
    import ReactDom from "react-dom";
    
    class Child extends Component {
      render() {
        return (
          <div>
            <div>child</div>
            <div>{this.props.children}</div>
          </div>); }}class App extends Component {
      render() {
        return <Child>parent</Child>;
      }
    }
    
    ReactDom.render(<App />.document.getElementById("root"));
    Copy the code

    Both child and parent are displayed on the page.

    》》》》》》》

    Redux

    The sample code

    What is the story

    Redux is a JavaScript state container that provides predictable state management.

    Why Redux

    React is actually a view framework. As JavaScript application development becomes more and more complex, more and more states need to be managed. At the same time, predictable application behavior needs to be ensured.

    Redux doesn’t have to be used. For some projects you can use React, but for others you might want to use another state management framework like Mobx. React+Redux is still the most popular and classic combination to support any large mid – to back-end application.

    Redux data flow

    Let’s start with a general overview of Redux’s data flow, which you don’t want to fully understand because we’ll cover the various concepts involved in data flow later.

    As you can see from the diagram, Redux’s data flow is one-way, and you can only change the view by changing the data, which also makes the data flow clear and predictable.

    The general process for Redux is: The view triggers an event, and the Action forms a function that generates an Action. An Action is a normal object, and it has a mandatory property type that represents the type of the Action. The container Store takes the Action as an argument and calls the Dispatch method to distribute it. The reducer function, which defines how actions change the state of the Store, is then followed. Finally the Store state changes and the view refreshes automatically.

    Store

    A Store is where your app’s state is stored. You can think of it as a container, and the only way to change the state in a Store is through a Dispatch (action). There should be only one Store in your app.

    const Store = createStore(reducer)/ / create a Store
    Copy the code

    There are several ways to do this on Store

    1. GetState () : getState

    2. Dispatch (Action): Dispatch an action

    3. Subscribe (listener): Adds a listener function and executes the listener function every time the action is issued

    action

    Dispatch (Action) is the only way to change state. An Action is a normal JavaScript object that must have a string type field to indicate the type of action to perform.

    Such as:

    const action = {
      type: "ADD". }Copy the code

    reducer

    Reducer is used to describe how the Store changes state based on actions. It’s essentially a pure function.

    So what is a pure function?

    1. No impact on the outside world

    2. Input is not affected

    The same input must produce the same output.

    Such as:

    function add(x, y) {
      return x + y;
    }
    Copy the code

    1. No impact on the outside world

    counter-examples

    function add(x, y) {
      const sum = x + y;
      updateSql(sum);// There are operations on the database
      return sum;
    }
    Copy the code

    2. Input is not affected

    counter-examples

    function addComponent(arr, ele) {
      arr.push(ele);
      return arr;
    }
    Copy the code

    The same input must produce the same output.

    counter-examples

    function getTime() {
      return new Date().getTime();
    }
    Copy the code

    That’s what redux is all about, isn’t it easy? Let’s get good at it with a practical example.

    Implement a counter

    First we compiled a reducer counter

    Reducer is a pure function that describes how the action changes state
    function counter(state = 0, action) {
      switch (action.type) {
        case "INCREASE":
          return state + 1;
        case "DECREASE":
          return state - 1;
        default:
          returnstate; }}Copy the code

    Then create a Store using redux’s createStore API

    // Create a Store using the createStore API in Redux
    const Store = createStore(counter);
    Copy the code

    Let’s test the Store

    const Store = createStore(counter);
    
    // Store provides getState to getState
    console.log(Store.getState()); / / 0
    
    // Dispatch an action via the Store's dispatch method
    Store.dispatch({
      type: "INCREASE"
    });
    
    console.log(Store.getState()); / / 1
    
    Store.dispatch({
      type: "DECREASE"
    });
    
    console.log(Store.getState()); / / 0
    Copy the code

    You can see that it already has the function of a counter, and the redux we introduced earlier is also covered. That’s right, redux is that easy to use!

    Of course, we also want to see it visually on the page

    Let’s just do some DOM processing

    // The click event on the document element binding is described in the DOM section
    document.addEventListener(
      "click".function() {
        Store.dispatch({
          type: "INCREASE"
        });
      },
      false
    );
    
    // Writing HTML content to the body element is covered in the DOM section
    function render() {
      document.body.innerHTML = "<h1>" + Store.getState() + "</h1>";
    }
    
    // Initialize the page
    render();
    
    // subscribe is used to add listeners, which are executed each time an action is issued
    Store.subscribe(render);
    Copy the code

    So when you click on the page the numbers add up.

    Simply combine the React counter

    Here is a simple combination of React and Redux.

    import React, { Component } from "react";
    import ReactDom from "react-dom";
    import { createStore } from "redux";
    
    function counter(state = 0, action) {
      switch (action.type) {
        case "INCREASE":
          return state + 1;
        case "DECREASE":
          return state - 1;
        default:
          returnstate; }}const Store = createStore(counter);
    
    class Counter extends Component {
      render() {
        return (
          <div>
            <h1>{Store.getState()}</h1>
            <button
              onClick={()= >{ Store.dispatch({ type: "INCREASE" }); > +}}</button>
            <button
              onClick={()= >{ Store.dispatch({ type: "DECREASE" }); > -}}</button>
          </div>); }}function render() {
      ReactDom.render(<Counter />.document.getElementById("root"));
    }
    
    render();
    Store.subscribe(render);
    Copy the code

    combineReducers

    Reducer is a function that describes how actions change state. We found that the reducer logic could only be written in one function and could not be split if we followed the previous formulation.

    At this time, we need to use combineReducers API, which can combine multiple reducer. This allows you to write multiple Reducer functions, with different reducer functions.

    Example: todolist

    Let’s look at a todoList example to see how combineReducers are used.

    There are two Reducer, Todos and visiableFilter in this example. Todos stores manifest list data, and visiableFilter stores filter criteria.

    // ./reducers/todos.js
    
    let gid = 0;
    
    const todos = (state = [], action) = > {
      switch (action.type) {
        case "ADD_TODO":
          return [
            ...state,
            {
              id: ++gid,
              text: action.text,
              completed: false}];case "TOGGLE_TODO":
          return state.map(todo= > {
            if (todo.id === action.id) {
              return {
                ...todo,
                completed: !todo.completed
              };
            }
            return todo;
          });
        default:
          returnstate; }};export default todos;
    Copy the code
    // ./reducers/visiableFilter.js
    
    const visiableFilter = (state = "SHOW_ALL", action) = > {
      switch (action.type) {
        case "SET_VISIABLE_FILTER":
          return action.filter;
        default:
          returnstate; }};export default visiableFilter;
    Copy the code

    We combine the two reducer using combineReducer.

    // ./reducers/index.js
    import { combineReducers } from "redux";
    
    import todos from "./todos.js";
    import visiableFilter from "./visiableFilter.js";
    
    export default combineReducers({
      todos,
      visiableFilter
    });
    Copy the code

    Now we can use the rootReducer in our application.

    Since the final list to be shown is the result of calculations by ToDOS and visiableFilter, we write a getFilterTodos todo this calculation.

    We also added filters, which are the three filterlinks at the bottom that correspond to the visiableFilter Reducer operation.

    So separate todos and visiableFilter from two separate states, with one state dedicated to one function.

    // ./index.jsx
    
    import React, { Component } from "react";
    import ReactDom from "react-dom";
    import { createStore } from "redux";
    
    import rootReducer from "./reducers/index.js";
    import FilterLink from "./FilterLink.jsx";
    
    const Store = createStore(rootReducer);
    
    const FILTER_TYPE_MAP = {
      SHOW_ALL: "SHOW_ALL".SHOW_COMPLETED: "SHOW_COMPLETED".SHOW_ACTIVE: "SHOW_ACTIVE"
    };
    
    const getFilterTodos = (todos, visiableFilter) = > {
      switch (visiableFilter) {
        case FILTER_TYPE_MAP.SHOW_ALL:
          return todos;
        case FILTER_TYPE_MAP.SHOW_COMPLETED:
          return todos.filter(todo= > todo.completed);
        case FILTER_TYPE_MAP.SHOW_ACTIVE:
          return todos.filter(todo= >! todo.completed);default:
          throw new Error("unknow filter type"); }};class App extends Component {
      constructor(props) {
        super(props);
        this.inputRef = React.createRef();
      }
    
      render() {
        const state = Store.getState();
        let { todos, visiableFilter } = state;
    
        todos = getFilterTodos(todos, visiableFilter);
    
        return (
          <div>
            <input type="text" ref={this.inputRef} />
            <button
              onClick={()= > {
                Store.dispatch({
                  type: "ADD_TODO",
                  text: this.inputRef.current.value
                });
              }}
            >
              add
            </button>
            <ul>
              {todos.map(todo => (
                <li
                  style={{
                    textDecoration: todo.completed ? "line-through" : "none"}}key={todo.id}
                  onClick={()= > {
                    Store.dispatch({
                      type: "TOGGLE_TODO",
                      id: todo.id
                    });
                  }}
                >
                  {todo.text}
                </li>
              ))}
            </ul>
            {Object.keys(FILTER_TYPE_MAP).map(key => {
              const filter = FILTER_TYPE_MAP[key];
              return (
                <FilterLink
                  key={filter}
                  filter={filter}
                  visiableFilter={visiableFilter}
                  handleClick={()= > {
                    Store.dispatch({
                      type: "SET_VISIABLE_FILTER",
                      filter
                    });
                  }}
                />
              );
            })}
          </div>); }}const render = () = > {
      ReactDom.render(<App />.document.getElementById("root"));
    };
    
    render();
    Store.subscribe(render);
    Copy the code

    FilterLink is a component that we wrote to reuse code so that we don’t have to write three similar tags and behaviors. When the filter itself is equal to the visiableFilter selected by the current user, the color of the component text is red, and the filter operation can be realized by clicking the component.

    // ./FilterLink.jsx
    
    import React, { Component } from "react";
    
    class FilterLink extends Component {
      render() {
        const { filter, visiableFilter, handleClick } = this.props;
    
        const style = {};
        if (filter === visiableFilter) {
          style.color = "red";
        }
    
        return (
          <div style={style} onClick={handleClick}>
            {filter}
          </div>); }}export default FilterLink;
    Copy the code

    react-redux

    A better way to combine Redux and React in real life projects is the React-Redux library.

    Its main function is to wrap the root component with the Provider component and inject Store from the Provider component, so that any child component can access state and disptach (that is, the state and the methods that change the state) in the Store using the connect method. When state is updated, the related child components are updated automatically (state and view are consistent).

    First, let’s write the Redux part

    The Reducer part is similar to the previous section

    // ./redux/reducers/todos.js
    
    import { ADD_TODO, TOGGLE_TODO } from ".. /actions";
    
    let gid = 0;
    
    const todos = (state = [], action) = > {
      switch (action.type) {
        case ADD_TODO:
          return [
            ...state,
            {
              id: ++gid,
              text: action.text,
              completed: false}];case TOGGLE_TODO:
          return state.map(todo= > {
            if (todo.id === action.id) {
              return {
                ...todo,
                completed: !todo.completed
              };
            }
            return todo;
          });
        default:
          returnstate; }};export default todos;
    Copy the code
    // ./redux/reducers/visiableFilter.js
    
    import { SET_VISIABLE_FILTER } from ".. /actions";
    
    const visiableFilter = (state = "SHOW_ALL", action) = > {
      switch (action.type) {
        case SET_VISIABLE_FILTER:
          return action.filter;
        default:
          returnstate; }};export default visiableFilter;
    Copy the code
    // ./redux/reducers/index.js
    
    import { combineReducers } from "redux";
    
    import todos from "./todos.js";
    import visiableFilter from "./visiableFilter.js";
    
    export default combineReducers({
      todos,
      visiableFilter
    });
    Copy the code

    We put all of our actions in the Actions directory so that we can easily find which actions are triggered throughout the application.

    // ./redux/actions/index.js
    
    export const ADD_TODO = "ADD_TODO";
    export const TOGGLE_TODO = "TOGGLE_TODO";
    export const SET_VISIABLE_FILTER = "SET_VISIABLE_FILTER";
    
    export const addTodo = todo= > {
      return {
        type: ADD_TODO,
        text: todo
      };
    };
    
    export const toggleTodo = id= > {
      return {
        type: TOGGLE_TODO,
        id
      };
    };
    
    export const setVisiableFilter = filter= > {
      return {
        type: SET_VISIABLE_FILTER,
        filter
      };
    };
    Copy the code

    After the redux coding section, let’s take a look at how redux and React can be combined using the React-Redux library.

    You can see that we use the Provider component to wrap the App, the root component of the application, and inject the Store into it.

    At the same time, we made further optimization, the whole application was split into AddTodo, TodoList, FilterLink three components.

    // ./index.jsx
    
    import React, { Component } from "react";
    import ReactDom from "react-dom";
    import { createStore } from "redux";
    import { Provider } from "react-redux";
    
    import rootReducer from "./redux/reducers/index.js";
    import AddTodo from "./components/AddTodo.jsx";
    import TodoList from "./components/TodoList.jsx";
    import FilterLink from "./components/FilterLink.jsx";
    import { FILTER_TYPE_MAP } from "./constants";
    
    const store = createStore(rootReducer);
    
    class App extends Component {
      render() {
        return (
          <div>
            <AddTodo />
            <TodoList />
            {Object.keys(FILTER_TYPE_MAP).map(key => {
              const filter = FILTER_TYPE_MAP[key];
              return <FilterLink key={filter} filter={filter} />;
            })}
          </div>
        );
      }
    }
    
    ReactDom.render(
      <Provider store={store}>
        <App />
      </Provider>.document.getElementById("root"));Copy the code

    All we need to do is write these three components and the application is complete.

    The AddTodo component adds todo items, similar to the implementation described in the previous section. The difference is that we use the connect method, and mapDispatchToProps is responsible for mapping user actions to components into actions.

    Here we inject addTodo action into addTodo. This makes it easy to trigger the AddTodo action in the AddTodo component to change the state.

    // ./components/AddTodo.js
    
    import React, { Component } from "react";
    import { connect } from "react-redux";
    
    import { addTodo } from ".. /redux/actions";
    
    class AddTodo extends Component {
      constructor(props) {
        super(props);
        this.inputRef = React.createRef();
      }
      render() {
        const { addTodo } = this.props;
    
        return (
          <div>
            <input type="text" ref={this.inputRef} />
            <button
              onClick={()= > {
                addTodo(this.inputRef.current.value);
              }}
            >
              add
            </button>
          </div>); }}const mapDispatchToProps = dispatch= > {
      return {
        addTodo: todo= >{ dispatch(addTodo(todo)); }}; };export default connect(null, mapDispatchToProps)(AddTodo);
    Copy the code

    The FilterLink component also uses the Connect method, which injects the setVisiableFilter Action to make it easy to change the visiableFilter in state.

    MapStateToProps maps state to the props of the component. Connect passes state as an argument to mapStateToProps. All you need to do is get the visiableFilter as an object value.

    // ./components/FilterLink.js
    
    import React, { Component } from "react";
    import { connect } from "react-redux";
    
    import { setVisiableFilter } from ".. /redux/actions";
    
    class FilterLink extends Component {
      render() {
        const { filter, visiableFilter, setVisiableFilter } = this.props;
    
        const style = {};
        if (filter === visiableFilter) {
          style.color = "red";
        }
    
        return (
          <div
            style={style}
            onClick={()= > {
              setVisiableFilter(filter);
            }}
          >
            {filter}
          </div>); }}const mapStateToProps = state= > {
      const { visiableFilter } = state;
      return {
        visiableFilter
      };
    };
    
    const mapDispatchToProps = dispatch= > {
      return {
        setVisiableFilter: filter= >{ dispatch(setVisiableFilter(filter)); }}; };export default connect(mapStateToProps, mapDispatchToProps)(FilterLink);
    Copy the code

    With the connect method introduced earlier, the TodoList component is easy to understand.

    // ./components/TodoList.js
    
    import React, { Component } from "react";
    import { connect } from "react-redux";
    
    import { toggleTodo } from ".. /redux/actions";
    import { FILTER_TYPE_MAP } from ".. /constants";
    
    class TodoList extends Component {
      render() {
        const { todos, toggleTodo } = this.props;
    
        return (
          <ul>
            {todos.map(todo => (
              <li
                style={{
                  textDecoration: todo.completed ? "line-through" : "none"}}key={todo.id}
                onClick={()= > {
                  toggleTodo(todo.id);
                }}
              >
                {todo.text}
              </li>
            ))}
          </ul>); }}const getFilterTodos = (todos, visiableFilter) = > {
      switch (visiableFilter) {
        case FILTER_TYPE_MAP.SHOW_ALL:
          return todos;
        case FILTER_TYPE_MAP.SHOW_COMPLETED:
          return todos.filter(todo= > todo.completed);
        case FILTER_TYPE_MAP.SHOW_ACTIVE:
          return todos.filter(todo= >! todo.completed);default:
          throw new Error("unknow filter type"); }};const mapStateToProps = state= > {
      const { todos, visiableFilter } = state;
      return {
        todos: getFilterTodos(todos, visiableFilter)
      };
    };
    
    const mapDispatchToProps = dispatch= > {
      return {
        toggleTodo: id= >{ dispatch(toggleTodo(id)); }}; };export default connect(mapStateToProps, mapDispatchToProps)(TodoList);
    Copy the code

    react-router-dom

    As the name suggests, this class library enables our application to integrate routing capabilities.

    It is also easy to understand how to use, basically matching the corresponding component according to the path.

    import React from "react";
    import { Route, HashRouter } from "react-router-dom";
    
    import BaseLayout from "./layouts/BaseLayout.jsx";
    import Todo from "./pages/Todo/index.jsx";
    
    function AppRouter() {
      return (
        <HashRouter>
          <Route exac path="/" component={BaseLayout} />
          <Route exac path="/:filter" component={Todo} />
        </HashRouter>
      );
    }
    
    export default AppRouter;
    Copy the code

    The withRouter advanced component wrap makes it easy for components to get routing parameters (match-.params) and provides a Link component that can be clicked to jump to a route.

    import React, { Component } from "react";
    import { Link, withRouter } from "react-router-dom";
    
    class FilterLink extends Component {
      render() {
        const { filter, match } = this.props;
        const { params } = match;
    
        const style = {};
        if (params.filter === filter) {
          style.color = "red";
        }
    
        return (
          <div>
            <Link to={filter} style={style}>
              {filter}
            </Link>
          </div>); }}export default withRouter(FilterLink);
    Copy the code

    See react-router-dom for the complete code

    Redux middleware

    Here we introduce two useful redux middleware: Redux-Thunk and Redux-Logger

    Redux-thunk allows Redux to handle asynchronous operations such as Ajax requests.

    The Redux-Logger can print redux state changes through the console log for easy debugging.

    Introducing them is simple.

    // ./redux/index.js
    
    import { createStore, applyMiddleware } from "redux";
    import thunk from "redux-thunk";
    import { createLogger } from "redux-logger";
    
    import rootReducer from "./reducers";
    
    const store = createStore(rootReducer, applyMiddleware(thunk, createLogger()));
    
    export default store;
    Copy the code

    So you can use both middleware.

    The Redux-Logger does nothing and automatically prints the Redux logs to the console.

    Redux-thunk requires you to change the way you write your actions to support asynchronous operations, where our action is a function.

    The following is an example:

    import * as api from ".. /.. /apiMock";
    
    export const SET_TODOS = "SET_TODOS";
    export const SET_LOADING = "SET_LOADING";
    
    export const setTodos = todos= > {
      return {
        type: SET_TODOS,
        todos
      };
    };
    
    export const setLoading = loading= > {
      return {
        type: SET_LOADING,
        loading
      };
    };
    
    export const fetchTodos = () = > {
      return dispatch= > {
        dispatch(setLoading(true));
        api
          .fetchTodoList()
          .then(res= > {
            dispatch(setTodos(res));
          })
          .finally(() = > {
            dispatch(setLoading(false));
          });
      };
    };
    Copy the code

    See redux Middleware for the complete code

    Continuously updated…