Dark horse programmer front-end JavaScript advanced - ES6 study notes

Take a brief look at the opening directory, which contains object-oriented programming ideas, as well as knowledge about constructors, classes and objects, prototype chains, arrow functions, new methods for arrays and strings, function recursion, deep copy and shallow copy, regular expressions, etc. point. This article is a supplement to the records of other bloggers on CSDN, because the dark horse has only added some knowledge points this year, and this article includes them here, so it is not surprising that they are similar.

Table of contents

Day 1 - JavaScript Object Orientation

01 - Learning objectives (target)

02 - Introduction to Object-Oriented Programming

Process-oriented programming POP (Process-oriented programming)

Object Oriented Programming (OOP)

03 - Classes and Objects in ES6

object

class class

Create classes and objects:

Class add method:

04 - Inheritance of classes

super keyword

Notes on using classes

Day 2 - Constructor and Prototype

01 - Learning objectives (target)

02 - Constructors and Prototypes

overview

Constructor

constructor prototype prototype 

Object prototype __proto__ 

constructor constructor

The relationship between constructors, instances, and prototype objects

prototype chain

JavaScript's member lookup mechanism (rules)

The prototype object this points to

Extend built-in objects

03 - Inheritance

call() method

Borrow the constructor to inherit the properties of the parent type

Borrow the prototype object to inherit the method of the parent type

The essence of ES6 classes

04 - New methods in ES5

overview

array method

string method

object method

Day 3 - Advanced functions

01 - Learning objectives (target) 

02 - Function definition and call

how the function is defined  

How to call the function

03 - what this points to 

Change the internal this point of the function

call apply bind summary

04 - Strict Mode 

What is strict mode

Enable strict mode

Changes in strict mode

05 - Higher order functions

06 - Closures

variable scope

What is a closure

Debug closures in chrome 

The role of closure

Closure application --- click li to output the index number

Closure case

Closure summary

07 - Recursion

what is recursion

Use recursion to solve math problems

shallow copy and deep copy

Day 4 - Regular Expressions

01 - Learning objectives (target)

02 - Regular Expression Overview

what is a regular expression

Features of regular expressions

03 - The use of regular expressions in JavaScript

Create a regular expression

Test regular expression test

04 - Special characters in regular expressions

The composition of regular expressions 

boundary character

character class

Quantifier

Case: Username Verification

parentheses summary

predefined class

Case: landline number verification

05 - Substitutions in regular expressions

replace replace

regular expression parameter

Case: sensitive word filtering

Day 5 - Part of ES6 knowledge 

01 - learning objectives (target)

02 - Introduction to ES6

What is ES6

Why use ES6

03 - New syntax for ES6

let keyword

classic interview questions

const keyword

The difference between let, const, and var

destructuring assignment

arrow function

remaining parameters

04 - ES6 built-in object extensions

Extension methods for Array 

Extension methods for String

Set data structure


Day 1 - JavaScript Object Orientation

01 - Learning objectives (target)

  • be able to say what is object oriented
  • Be able to tell the relationship between classes and objects
  • Ability to create custom types using class
  • be able to say what inheritance is

02 - Introduction to Object-Oriented Programming

Process-oriented programming POP (Process-oriented programming)

Process-oriented is to analyze the steps needed to solve the problem, and then use functions to realize these steps step by step, and then call them one by one when using them.

Process-oriented means solving problems according to the steps we have analyzed.

Object Oriented Programming (OOP)

Object-oriented is to decompose the transaction into individual objects, and then divide and cooperate between the objects.

For example: put the elephant in the refrigerator, object-oriented approach.

Find the objects first, and write the functions of these objects:

1. Elephant object

● go in

2. Refrigerator object

● open

● off

3. Use the functions of elephants and refrigerators

Object-oriented is to divide the problem by object functions, not steps.

Object-oriented programming has the advantages of flexibility, code reusability, easy maintenance and development, and is more suitable for large-scale software projects where multiple people cooperate.

Its characteristics:

  • encapsulation
  • Inheritance
  • polymorphism

Procedural vs Object Oriented

process oriented object oriented
advantage The performance is higher than object-oriented, and it is suitable for things closely related to hardware, such as process-oriented programming adopted by single-chip microcomputers. Easy to maintain, easy to reuse, and easy to expand. Due to the characteristics of object-oriented encapsulation, inheritance, and polymorphism, a low-coupling system can be designed to make the system more flexible and easier to maintain
shortcoming No object-oriented, easy to maintain, easy to reuse, easy to expand lower performance than procedure-oriented

03 - Classes and Objects in ES6

object

 An object is a specific thing . In JavaScript, an object is a collection of unordered related properties and methods. All things are objects , such as strings, numbers, arrays, functions, and so on.

 Objects are made up of properties and methods :

  • Attribute: the characteristics of things , represented by attributes in objects (common nouns)
  • Method: the behavior of a thing , represented by a method in an object (common verb)

class class

The new class concept in ES6, you can use the keyword class to declare a class, and then use this class to instantiate objects.

A class abstracts the public part of an object, and it generally refers to a certain class.

The object refers to a certain one, and a specific object is instantiated through the class.

Object-oriented thinking features:

1. Extract (abstract) attributes and behaviors shared by objects and organize (encapsulate) them into a class (template)

2. Instantiate the class and get the object of the class

Create classes and objects:

<script>
// 1. 创建类 class  创建一个 明星类
    class Star {
       constructor(uname, age) {
          this.uname = uname;
          this.age = age;
       }
    }

// 2. 利用类创建对象 new
    var ldh = new Star('刘德华', 18);
    var zxy = new Star('张学友', 20);
    console.log(ldh);
    console.log(zxy);
//(1) 通过class 关键字创建类, 类名我们还是习惯性定义首字母大写
//(2) 类里面有个constructor 函数,可以接受传递过来的参数,同时返回实例对象
//(3) constructor 函数 只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个函数,类也会自动生成这个函数
//(4) 生成实例 new 不能省略
//(5) 最后注意语法规范, 创建类 类名后面不要加小括号,生成实例 类名后面加小括号, 构造函数不需要加function
</script>

Note: The class must use new to instantiate the object;

The constructor() method is the constructor (default method) of the class, which is used to pass parameters and return an instance object . When an object instance is generated through the new command, this method is automatically called. If no definition is displayed, a constructor() will be automatically created for us inside the class 

Class add method:

<script>
// 1. 创建类 class  创建一个 明星类
   class Star {
   // 类的共有属性放到 constructor 里面
   constructor(uname, age) {
       this.uname = uname;
       this.age = age;
    }
    sing(song) {
    // console.log('我唱歌');
       console.log(this.uname + song);

       }
    }

// 2. 利用类创建对象 new
   var ldh = new Star('刘德华', 18);
   var zxy = new Star('张学友', 20);
   console.log(ldh);
   console.log(zxy);
// (1) 我们类里面所有的函数不需要写function 
// (2) 多个函数方法之间不需要添加逗号分隔
   ldh.sing('冰雨');
   zxy.sing('李香兰');
</script>

04 - Inheritance of classes

Inheritance in the program: subclasses can inherit some properties and methods of the parent class.

grammar:

super keyword

The super keyword is used to access and call functions on the object's parent class. You can call the constructor of the parent class , or you can call the ordinary function of the parent class.

grammar:

Note: The subclass uses super in the constructor, which must be placed before this (the constructor of the parent class must be called first, and then the subclass constructor is used)

Inherited instance of class: 

 <script>
        // 1. 类的继承
        // class Father {
        //     constructor() {

        //     }
        //     money() {
        //         console.log(100);

        //     }
        // }
        // class Son extends Father {

        // }
        // var son = new Son();
        // son.money();
        class Father {
            constructor(x, y) {
                this.x = x;
                this.y = y;
            }
            sum() {
                console.log(this.x + this.y);

            }
        }
        class Son extends Father {
            constructor(x, y) {
                super(x, y); //调用了父类中的构造函数
            }
        }
        var son = new Son(1, 2);
        var son1 = new Son(11, 22);
        son.sum();
        son1.sum();
</script>

The super keyword calls the normal function instance of the parent class 

<script>
// super 关键字调用父类普通函数
   class Father {
     say() {
        return '我是爸爸';
     }
   }
   class Son extends Father {
     say() {
     // console.log('我是儿子');
        console.log(super.say() + '的儿子');
     // super.say() 就是调用父类中的普通函数 say()
           }
   }
   var son = new Son();
   son.say();
// 继承中的属性或者方法查找原则: 就近原则
// 1. 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
// 2. 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
</script>

 The subclass inherits the parent class and inherits and extends its own methods:

<script>
// 父类有加法方法
   class Father {
      constructor(x, y) {
          this.x = x;
          this.y = y;
         }
          sum() {
            console.log(this.x + this.y);
         }
      }
// 子类继承父类加法方法 同时 扩展减法方法
   class Son extends Father {
      constructor(x, y) {
      // 利用super 调用父类的构造函数
      // super 必须在子类this之前调用
            super(x, y);
            this.x = x;
            this.y = y;

         }
         subtract() {
           console.log(this.x - this.y);

         }
      }
   var son = new Son(5, 3);
   son.subtract();
   son.sum();
</script>

Notes on using classes

Three points of attention:

  1. There is no variable promotion for classes in ES6, so the class must be defined before objects can be instantiated through the class.
  2. The common properties and methods in the class must be used with this.
  3. this inside the class points to the problem.
  4. The this in the constructor points to the instance object, and the this in the method points to the caller of the method.
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <button>点击</button>
    <script>
        var that;
        var _that;
        class Star {
            constructor(uname, age) {
                // constructor 里面的this 指向的是 创建的实例对象
                that = this;
                console.log(this);

                this.uname = uname;
                this.age = age;
                // this.sing();
                this.btn = document.querySelector('button');
                this.btn.onclick = this.sing;
            }
            sing() {
                // 这个sing方法里面的this 指向的是 btn 这个按钮,因为这个按钮调用了这个函数
                console.log(this);

                console.log(that.uname); // that里面存储的是constructor里面的this
            }
            dance() {
                // 这个dance里面的this 指向的是实例对象 ldh 因为ldh 调用了这个函数
                _that = this;
                console.log(this);

            }
        }

        var ldh = new Star('刘德华');
        console.log(that === ldh);
        ldh.dance();
        console.log(_that === ldh);

        // 1. 在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象

        // 2. 类里面的共有的属性和方法一定要加this使用.
    </script>
</body>

</html

Day 2 - Constructor and Prototype

01 - Learning objectives (target)

  •  Ability to create objects using constructors
  • be able to say what the prototype does
  • Ability to say rules for accessing object members
  • Ability to use some of the new methods added by ES5

02 - Constructors and Prototypes

overview

Before ES6, the concept of class was not introduced in JS. ES6, the full name of ECMAScript 6.0, was released in June 2015. However, the current browser JavaScript is the ES5 version, and most high-version browsers also support ES6, but only some of the features and functions of ES6 are implemented.

Prior to ES6, objects were not created based on classes, but a special function called a constructor to define objects and their characteristics.

Objects can be created in three ways: (Methods before ES6)

  • object literal
  • new   Object()
  • custom constructor
<script>
   // 1. 利用 new Object() 创建对象

      var obj1 = new Object();

   // 2. 利用 对象字面量创建对象

      var obj2 = {};

   // 3. 利用构造函数创建对象
      function Star(uname, age) {
         this.uname = uname;
         this.age = age;
         this.sing = function() {
            console.log('我会唱歌');

         }
      }

      var ldh = new Star('刘德华', 18);
      var zxy = new Star('张学友', 19);
      console.log(ldh);
      ldh.sing();
      zxy.sing();
</script>

Constructor

A constructor is a special function that is mainly used to initialize an object, that is, to assign initial values ​​to object member variables, and it is always used together with new. We can extract some public properties and methods in the object, and then encapsulate them into this function.

In JS, pay attention to the following two points when using constructors:

  • The constructor is used to create a certain type of object, and its first letter should be capitalized
  • Constructors only make sense when used with new

new does four things when executed:

① Create a new empty object in memory.

② Let this point to this new object.

③ Execute the code in the constructor to add properties and methods to the new object.

④ Return this new object (so there is no need to return in the constructor).

Some members can be added to the JavaScript constructor, either on the constructor itself, or on this inside the constructor. Members added in these two ways are called static members and instance members respectively .

  • Static members : The members added on the constructor are called static members, which can only be accessed by the constructor itself .
  • Instance members : The object members created inside the constructor are called instance members and can only be accessed by the instantiated object .
<script>
    // 构造函数中的属性和方法我们称为成员, 成员可以添加
    function Star(uname, age) {
       this.uname = uname;
       this.age = age;
       this.sing = function() {
           console.log('我会唱歌');

          }
    }
    var ldh = new Star('刘德华', 18);
    // 1.实例成员就是构造函数内部通过this添加的成员 uname age sing 就是实例成员
    // 实例成员只能通过实例化的对象来访问
    console.log(ldh.uname);
    ldh.sing();
    // console.log(Star.uname); // 不可以通过构造函数来访问实例成员
    // 2. 静态成员 在构造函数本身上添加的成员  sex 就是静态成员
    Star.sex = '男';
    // 静态成员只能通过构造函数来访问
    console.log(Star.sex);
    console.log(ldh.sex); // 不能通过对象来访问
</script>

Although the constructor method is very useful, it has the problem of wasting memory .

for example:

function Star(uname, age) {
this.uname = uname;
this.age = age;
this.sing = function() {
console.log('我会唱歌');
}
}
var ldh = new Star('刘德华', 18);
var zxy = new Star('张学友', 19);
console.log(ldh.sing === zxy.sing)  // false

 We want all objects to use the same function, which saves memory, so how do we do it?

constructor prototype prototype 

The function assigned by the constructor through the prototype is shared by all objects . 

JavaScript stipulates that every constructor has a prototype property that points to another object. Note that this prototype is an object, and all properties and methods of this object will be owned by the constructor 

We can define those invariant methods directly on the prototype object, so that all object instances can share these methods. 

Therefore, the above example can be modified as follows:

<script>
   // 1. 构造函数的问题. 
   function Star(uname, age) {
       this.uname = uname;
       this.age = age;
       // this.sing = function() {
       //     console.log('我会唱歌');

       // }
   }
   Star.prototype.sing = function() {
       console.log('我会唱歌');
   }
   var ldh = new Star('刘德华', 18);
   var zxy = new Star('张学友', 19);
   console.log(ldh.sing === zxy.sing);
   // console.dir(Star);
   ldh.sing();
   zxy.sing();
   // 2. 一般情况下,我们的公共属性定义到构造函数里面, 公共的方法我们放到原型对象身上
</script>

 So, what is a prototype?

Answer: An object, we also call prototype a prototype object .

What is the role of the prototype?

Answer: sharing method

Object prototype __proto__ 

The object will have a property __proto__ pointing to the prototype object of the constructor. The reason why our object can use the properties and methods of the prototype object of the constructor function is because the object has a __proto__ prototype.

  • __proto__ object prototype and prototype object prototype are equivalent;
  • The significance of the __proto__ object prototype is to provide a direction, or a route, for the object search mechanism, but it is a non-standard attribute, so in actual development, this attribute cannot be used, and it only internally points to the prototype object prototype.
 <script>
    function Star(uname, age) {
        this.uname = uname;
        this.age = age;
    }
    Star.prototype.sing = function() {
            console.log('我会唱歌');
    }
    var ldh = new Star('刘德华', 18);
    var zxy = new Star('张学友', 19);
    ldh.sing();
  console.log(ldh); // 对象身上系统自己添加一个 __proto__ 指向我们构造函数的原型对象prototype
  console.log(ldh.__proto__ === Star.prototype);
  // 方法的查找规则: 首先先看ldh 对象身上是否有 sing 方法,如果有就执行这个对象上的sing
  // 如果么有sing 这个方法,因为有__proto__ 的存在,就去构造函数原型对象prototype身上去查找sing这个方法
</script>

constructor constructor

Both the object prototype (__proto__) and the constructor (prototype) prototype object have an attribute constructor attribute. The constructor is called a constructor because it points back to the constructor itself. 

The constructor is mainly used to record which constructor the object refers to, and it can make the prototype object point to the original constructor again.

In general, the methods of the object are set in the prototype object of the constructor. If there are multiple object methods, we can assign values ​​to the prototype object in the form of an object, but this will overwrite the original content of the constructor prototype object, so that the modified prototype object constructor no longer points to the current constructor. At this point, we can add a constructor pointing to the original constructor in the modified prototype object.

<script>
   function Star(uname, age) {
      this.uname = uname;
      this.age = age;
   }
// 很多情况下,我们需要手动的利用constructor 这个属性指回 原来的构造函数
// Star.prototype.sing = function() {
//     console.log('我会唱歌');
// };
// Star.prototype.movie = function() {
//     console.log('我会演电影');
// }
   Star.prototype = {
// 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数
       constructor: Star,
       sing: function() {
          console.log('我会唱歌');
       },
       movie: function() {
            console.log('我会演电影');
       }
   }
   var ldh = new Star('刘德华', 18);
   var zxy = new Star('张学友', 19);
   console.log(Star.prototype);
   console.log(ldh.__proto__);
   console.log(Star.prototype.constructor);
   console.log(ldh.__proto__.constructor);
</script>

The relationship between constructors, instances, and prototype objects

prototype chain

 <script>
     function Star(uname, age) {
         this.uname = uname;
         this.age = age;
     }
     Star.prototype.sing = function() {
         console.log('我会唱歌');
     }
     var ldh = new Star('刘德华', 18);
     // 1. 只要是对象就有__proto__ 原型, 指向原型对象
     console.log(Star.prototype);
     console.log(Star.prototype.__proto__ === Object.prototype);
     // 2.我们Star原型对象里面的__proto__原型指向的是 Object.prototype
     console.log(Object.prototype.__proto__);
     // 3. 我们Object.prototype原型对象里面的__proto__原型  指向为 null
</script>

JavaScript's member lookup mechanism (rules)

① When accessing the properties (including methods) of an object, first check whether the object itself has the property.

② If not, find its prototype (that is, the prototype prototype object pointed to by __proto__ ).

③ If not, find the prototype of the prototype object ( the prototype object of Object ).

④ And so on until the Object ( null ) is found.

⑤ The significance of the __proto__ object prototype is to provide a direction, or a route, for the object member search mechanism.

<script>
    function Star(uname, age) {
        this.uname = uname;
        this.age = age;
    }
    Star.prototype.sing = function() {
        console.log('我会唱歌');

    }
    Star.prototype.sex = '女';
    // Object.prototype.sex = '男';
    var ldh = new Star('刘德华', 18);
    ldh.sex = '男';
    console.log(ldh.sex);
    console.log(Object.prototype);
    console.log(ldh);
    console.log(Star.prototype);
    console.log(ldh.toString());
</script>

The prototype object this points to

The this in the constructor points to our instance object.

The method is placed in the prototype object , and this in the method points to the caller of the method, that is, the instance object

 <script>
    function Star(uname, age) {
        this.uname = uname;
        this.age = age;
    }
    var that;
    Star.prototype.sing = function() {
        console.log('我会唱歌');
        that = this;
    }
    var ldh = new Star('刘德华', 18);
    // 1. 在构造函数中,里面this指向的是对象实例 ldh
    ldh.sing();
    console.log(that === ldh);

    // 2.原型对象函数里面的this 指向的是 实例对象 ldh
</script>

Extend built-in objects

The original built-in object can be extended and customized through the prototype object. For example, add the function of customizing the sum of even numbers to the array.

Note: Array and string built-in objects cannot override the operation Array.prototype = {} for prototype objects, only Array.prototype.xxx = function(){}. 

<script>
    // 原型对象的应用 扩展内置对象方法
    Array.prototype.sum = function() {
        var sum = 0;
        for (var i = 0; i < this.length; i++) {
            sum += this[i];
        }
        return sum;
    };
    // Array.prototype = {
    //     sum: function() {
    //         var sum = 0;
    //         for (var i = 0; i < this.length; i++) {
    //             sum += this[i];
    //         }
    //         return sum;
    //     }

    // }
    var arr = [1, 2, 3];
    console.log(arr.sum());
    console.log(Array.prototype);
    var arr1 = new Array(11, 22, 33);
    console.log(arr1.sum());
</script>

03 - Inheritance

ES6 did not provide us with extends inheritance before. We can achieve inheritance through constructor + prototype object simulation, which is called combined inheritance.

call() method

Call this function, and modify the this point when the function is running

  • thisArg : the object pointed to by the current calling function this
  • arg1, arg2: additional arguments passed
<script>
    // call 方法
    function fn(x, y) {
        console.log('我想喝手磨咖啡');
        console.log(this);
        console.log(x + y);


    }
    var o = {
        name: 'andy'
    };
    // fn();
    // 1. call() 可以调用函数
    // fn.call();
    // 2. call() 可以改变这个函数的this指向 此时这个函数的this 就指向了o这个对象
    fn.call(o, 1, 2);
</script>

Borrow the constructor to inherit the properties of the parent type

Core principle: through call(), the this of the parent type points to the this of the subtype, so that the subtype can inherit the properties of the parent type.

<script>
    // 借用父构造函数继承属性
    // 1. 父构造函数
    function Father(uname, age) {
        // this 指向父构造函数的对象实例
        this.uname = uname;
        this.age = age;
    }
    // 2 .子构造函数 
    function Son(uname, age, score) {
        // this 指向子构造函数的对象实例
        Father.call(this, uname, age);
        this.score = score;
    }
    var son = new Son('刘德华', 18, 100);
    console.log(son);
</script>

Borrow the prototype object to inherit the method of the parent type

In general, the methods of the object are set in the prototype object of the constructor, and the method of the parent class cannot be inherited through the constructor. 

Core principle:

① Extract the method shared by the subclass, let the prototype object of the subclass = new parent class () 

② Essence: The subclass prototype object is equivalent to instantiating the parent class, because after the parent class is instantiated, another space is opened up, and the original parent class prototype object will not be affected

③ Repoint the constructor of the subclass to the constructor of the subclass

<script>
    // 借用父构造函数继承属性
    // 1. 父构造函数
    function Father(uname, age) {
        // this 指向父构造函数的对象实例
        this.uname = uname;
        this.age = age;
    }
    Father.prototype.money = function() {
        console.log(100000);

    };
    // 2 .子构造函数 
    function Son(uname, age, score) {
        // this 指向子构造函数的对象实例
        Father.call(this, uname, age);
        this.score = score;
    }
    // Son.prototype = Father.prototype;  这样直接赋值会有问题,如果修改了子原型对象,父原型对象也会跟着一起变化
    Son.prototype = new Father();
    // 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数
    Son.prototype.constructor = Son;
    // 这个是子构造函数专门的方法
    Son.prototype.exam = function() {
        console.log('孩子要考试');

    }
    var son = new Son('刘德华', 18, 100);
    console.log(son);
    console.log(Father.prototype);
    console.log(Son.prototype.constructor);
</script>

The essence of ES6 classes

  1.  The essence of class is still function.
  2. All methods of a class are defined on the prototype property of the class
  3. The instance created by the class also has __proto__ pointing to the prototype prototype object of the class
  4. Therefore, most of the functions of ES6 classes can be achieved by ES5. The new class writing method only makes the object prototype writing method clearer and more like the syntax of object-oriented programming.
  5. .So ES6 classes are actually syntactic sugar .
  6. Syntactic sugar : Syntactic sugar is a convenient way of writing. Simple understanding, there are two ways to achieve the same function, but one way of writing is clearer and more convenient, then this method is syntactic sugar .
<script>
    // ES6 之前通过 构造函数+ 原型实现面向对象 编程
    // (1) 构造函数有原型对象prototype 
    // (2) 构造函数原型对象prototype 里面有constructor 指向构造函数本身
    // (3) 构造函数可以通过原型对象添加方法
    // (4) 构造函数创建的实例对象有__proto__ 原型指向 构造函数的原型对象
    // ES6 通过 类 实现面向对象编程 
    class Star {

    }
    console.log(typeof Star);
    // 1. 类的本质其实还是一个函数 我们也可以简单的认为 类就是 构造函数的另外一种写法
    // (1) 类有原型对象prototype 
    console.log(Star.prototype);
    // (2) 类原型对象prototype 里面有constructor 指向类本身
    console.log(Star.prototype.constructor);
    // (3)类可以通过原型对象添加方法
    Star.prototype.sing = function() {
        console.log('冰雨');

    }
    var ldh = new Star();
    console.dir(ldh);
    // (4) 类创建的实例对象有__proto__ 原型指向 类的原型对象
    console.log(ldh.__proto__ === Star.prototype);
    i = i + 1;
    i++
</script>

04 - New methods in ES5

overview

Some new methods have been added to us in ES5, which can easily manipulate arrays or strings. These methods mainly include:

  • array method
  • string method
  • object method

array method

Iteration (traversal) methods: forEach(), map(), filter(), some(), every();

forEach() method

  • currentValue: the value of the current item in the array
  • index: the index of the current item in the array
  • arr: the array object itself
<script>
    // forEach 迭代(遍历) 数组
    var arr = [1, 2, 3];
    var sum = 0;
    arr.forEach(function(value, index, array) {
        console.log('每个数组元素' + value);
        console.log('每个数组元素的索引号' + index);
        console.log('数组本身' + array);
        sum += value;
    })
    console.log(sum);
</script>

filter() method

  • The filter() method creates a new array, and the elements in the new array are checked by checking all elements in the specified array that meet the conditions, mainly used to filter the array 
  • Note that it directly returns a new array
  • currentValue: the value of the current item in the array
  • index: the index of the current item in the array
  • arr: the array object itself
<script>
    // filter 筛选数组
    var arr = [12, 66, 4, 88, 3, 7];
    var newArr = arr.filter(function(value, index) {
        // return value >= 20;
        return value % 2 === 0;
    });
    console.log(newArr);
</script>

some() method

 

  •  The some() method is used to detect whether the elements in the array meet the specified conditions. The popular point is to find whether there are elements in the array that meet the conditions
  • Note that its return value is a boolean value. If the element is found, it returns true, and if it cannot find it, it returns false.
  • If the first element that satisfies the condition is found, the loop is terminated. The search is not continued.
  • currentValue: the value of the current item in the array
  • index: the index of the current item in the array
  • arr: the array object itself
<script>
    // some 查找数组中是否有满足条件的元素 
    // var arr = [10, 30, 4];
    // var flag = arr.some(function(value) {
    //     // return value >= 20;
    //     return value < 3;
    // });
    // console.log(flag);
    var arr1 = ['red', 'pink', 'blue'];
    var flag1 = arr1.some(function(value) {
        return value == 'pink';
    });
    console.log(flag1);
    // 1. filter 也是查找满足条件的元素 返回的是一个数组 而且是把所有满足条件的元素返回回来
    // 2. some 也是查找满足条件的元素是否存在  返回的是一个布尔值 如果查找到第一个满足条件的元素就终止循环
</script>

 The difference between forEach() and some

<script>
    var arr = ['red', 'green', 'blue', 'pink'];
    // 1. forEach迭代 遍历
    // arr.forEach(function(value) {
    //     if (value == 'green') {
    //         console.log('找到了该元素');
    //         return true; // 在forEach 里面 return 不会终止迭代
    //     }
    //     console.log(11);

    // })
    // 如果查询数组中唯一的元素, 用some方法更合适,
    arr.some(function(value) {
        if (value == 'green') {
            console.log('找到了该元素');
            return true; //  在some 里面 遇到 return true 就是终止遍历 迭代效率更高
        }
        console.log(11);

    });
    // arr.filter(function(value) {
    //     if (value == 'green') {
    //         console.log('找到了该元素');
    //         return true; //  // filter 里面 return 不会终止迭代
    //     }
    //     console.log(11);

    // });
</script>

string method

The trim() method removes whitespace characters from both ends of a string.

The trim() method does not affect the original string itself, it returns a new string.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <input type="text"> <button>点击</button>
    <div></div>
    <script>
        // trim 方法去除字符串两侧空格
        var str = '   an  dy   ';
        console.log(str);
        var str1 = str.trim();
        console.log(str1);
        var input = document.querySelector('input');
        var btn = document.querySelector('button');
        var div = document.querySelector('div');
        btn.onclick = function() {
            var str = input.value.trim();
            if (str === '') {
                alert('请输入内容');
            } else {
                console.log(str);
                console.log(str.length);
                div.innerHTML = str;
            }
        }
    </script>
</body>

</html>

object method

1. Object.keys() is used to get all the properties of the object itself

  • The effect is similar to for...in 
  • Returns an array of property names
<script>
    // 用于获取对象自身所有的属性
    var obj = {
        id: 1,
        pname: '小米',
        price: 1999,
        num: 2000
    };
    var arr = Object.keys(obj);
    console.log(arr);
    arr.forEach(function(value) {
        console.log(value);

    })
</script>

2. Object.defineProperty() defines a new property in an object or modifies an existing property. (learn)

  • obj: required. target 
  • props: Required. The name of the property to define or modify
  • descriptor: Required. properties possessed by the target attribute

Object.defineProperty() The description of the third parameter descriptor: write in the form of object { }

  • value: Set the value of the attribute to undefined by default
  • writable: Whether the value can be rewritten. true | false defaults to false
  • enumerable: Whether the target property can be enumerated. true | false defaults to false
  • configurable: whether the target attribute can be deleted or whether the attribute can be modified again true | false default is false
<script>
    // Object.defineProperty() 定义新属性或修改原有的属性
    var obj = {
        id: 1,
        pname: '小米',
        price: 1999
    };
    // 1. 以前的对象添加和修改属性的方式
    // obj.num = 1000;
    // obj.price = 99;
    // console.log(obj);
    // 2. Object.defineProperty() 定义新属性或修改原有的属性
    Object.defineProperty(obj, 'num', {
        value: 1000,
        enumerable: true
    });
    console.log(obj);
    Object.defineProperty(obj, 'price', {
        value: 9.9
    });
    console.log(obj);
    Object.defineProperty(obj, 'id', {
        // 如果值为false 不允许修改这个属性值 默认值也是false
        writable: false,
    });
    obj.id = 2;
    console.log(obj);
    Object.defineProperty(obj, 'address', {
        value: '中国山东蓝翔技校xx单元',
        // 如果只为false 不允许修改这个属性值 默认值也是false
        writable: false,
        // enumerable 如果值为false 则不允许遍历, 默认的值是 false
        enumerable: false,
        // configurable 如果为false 则不允许删除这个属性 不允许在修改第三个参数里面的特性 默认为false
        configurable: false
    });
    console.log(obj);
    console.log(Object.keys(obj));
    delete obj.address;
    console.log(obj);
    delete obj.pname;
    console.log(obj);
    Object.defineProperty(obj, 'address', {
        value: '中国山东蓝翔技校xx单元',
        // 如果值为false 不允许修改这个属性值 默认值也是false
        writable: true,
        // enumerable 如果值为false 则不允许遍历, 默认的值是 false
        enumerable: true,
        // configurable 如果为false 则不允许删除这个属性 默认为false
        configurable: true
    });
    console.log(obj.address);
</script>

Day 3 - Advanced functions

01 - Learning objectives (target) 

  • Be able to tell the various definitions and calling methods of functions 
  • Ability to speak and change what this points to inside a function
  • Be able to tell the characteristics of strict mode
  • Ability to pass functions as parameters and return values
  • Be able to tell what closures do
  • Be able to state the two conditions for recursion
  • Can tell the difference between deep copy and shallow copy

02 - Function definition and call

how the function is defined  

1. Function declaration method function keyword (named function)

2. Function expressions (anonymous functions)

3. new Function()

  • All parameters in Function must be in string format 
  • The third method is inefficient and inconvenient to write, so it is less used
  • All functions are instances (objects) of Function
  • Functions are also objects

<script>
    //  函数的定义方式

    // 1. 自定义函数(命名函数) 

    function fn() {};

    // 2. 函数表达式 (匿名函数)

    var fun = function() {};


    // 3. 利用 new Function('参数1','参数2', '函数体');

    var f = new Function('a', 'b', 'console.log(a + b)');
    f(1, 2);
    // 4. 所有函数都是 Function 的实例(对象)
    console.dir(f);
    // 5. 函数也属于对象
    console.log(f instanceof Object);
</script>

How to call the function

<script>
    // 函数的调用方式

    // 1. 普通函数
    function fn() {
        console.log('人生的巅峰');

    }
    // fn();   fn.call()
    // 2. 对象的方法
    var o = {
        sayHi: function() {
            console.log('人生的巅峰');

        }
    }
    o.sayHi();
    // 3. 构造函数
    function Star() {};
    new Star();
    // 4. 绑定事件函数
    // btn.onclick = function() {};   // 点击了按钮就可以调用这个函数
    // 5. 定时器函数
    // setInterval(function() {}, 1000);  这个函数是定时器自动1秒钟调用一次
    // 6. 立即执行函数
    (function() {
        console.log('人生的巅峰');
    })();
    // 立即执行函数是自动调用
</script>

03 - what this points to 

Principle :

The point of this  is determined when we call the function. The difference in the way of calling determines  the direction of this  . Generally point to our caller.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <button>点击</button>
    <script>
        // 函数的不同调用方式决定了this 的指向不同
        // 1. 普通函数 this 指向window
        function fn() {
            console.log('普通函数的this' + this);
        }
        window.fn();
        // 2. 对象的方法 this指向的是对象 o
        var o = {
            sayHi: function() {
                console.log('对象方法的this:' + this);
            }
        }
        o.sayHi();
        // 3. 构造函数 this 指向 ldh 这个实例对象 原型对象里面的this 指向的也是 ldh这个实例对象
        function Star() {};
        Star.prototype.sing = function() {

        }
        var ldh = new Star();
        // 4. 绑定事件函数 this 指向的是函数的调用者 btn这个按钮对象
        var btn = document.querySelector('button');
        btn.onclick = function() {
            console.log('绑定时间函数的this:' + this);
        };
        // 5. 定时器函数 this 指向的也是window
        window.setTimeout(function() {
            console.log('定时器的this:' + this);

        }, 1000);
        // 6. 立即执行函数 this还是指向window
        (function() {
            console.log('立即执行函数的this' + this);
        })();
    </script>
</body>

</html>

Change the internal this point of the function

JavaScript provides us with some function methods to help us more elegantly deal with the pointing of this inside the function. The commonly used methods are call(), apply(), and bind() .

1. call method 

The call() method invokes an object. It is simply understood as a way to call a function, but it can change the this point of the function. 

The grammatical structure is:

fun.call(thisArg, arg1, arg2, ...) 
  •  thisArg: the this value specified when the fun function is running;
  • arg1, arg2: other parameters passed;
  • The return value is the return value of the function, because it is the calling function;
  • So when we want to change the point of this and call this function at the same time, we can use call, such as inheritance.
<script>
    // 改变函数内this指向  js提供了三种方法  call()  apply()  bind()

    // 1. call()
    var o = {
        name: 'andy'
    }

    function fn(a, b) {
        console.log(this);
        console.log(a + b);

    };
    fn.call(o, 1, 2);
    // call 第一个可以调用函数 第二个可以改变函数内的this 指向
    // call 的主要作用可以实现继承
    function Father(uname, age, sex) {
        this.uname = uname;
        this.age = age;
        this.sex = sex;
    }

    function Son(uname, age, sex) {
        Father.call(this, uname, age, sex);
    }
    var son = new Son('刘德华', 18, '男');
    console.log(son);
</script>

 2. apply method

The apply() method calls a function. Simply understood as the way to call the function, it can also change the this point of the function. 

The grammatical structure is:

fun.apply(thisArg, [argsArray])
  • thisArg: the this value specified when the fun function is running;
  • argsArray: The passed value must be included in the array;
  • The return value is the return value of the function, because it is the calling function;
  • Therefore, apply is mainly related to arrays, such as using Math.max() to find the maximum value of an array.
<script>
    // 改变函数内this指向  js提供了三种方法  call()  apply()  bind()

    // 2. apply()  应用 运用的意思
    var o = {
        name: 'andy'
    };

    function fn(arr) {
        console.log(this);
        console.log(arr); // 'pink'

    };
    fn.apply(o, ['pink']);
    // 1. 也是调用函数 第二个可以改变函数内部的this指向
    // 2. 但是他的参数必须是数组(伪数组)
    // 3. apply 的主要应用 比如说我们可以利用 apply 借助于数学内置对象求数组最大值 
    // Math.max();
    var arr = [1, 66, 3, 99, 4];
    var arr1 = ['red', 'pink'];
    // var max = Math.max.apply(null, arr);
    var max = Math.max.apply(Math, arr);
    var min = Math.min.apply(Math, arr);
    console.log(max, min);
</script>

 3. bind method

The bind()  method does not call the function. But it can change the this pointer inside the function.

The grammatical structure is:

fun.bind(thisArg, arg1, arg2, ...)
  • thisArg: the this value specified when the fun function is running;
  • arg1, arg2: other parameters passed;
  • Returns a copy of the original function transformed by the specified this value and initialization parameters;
  • So when we just want to change the point of this and don't want to call this function, we can use bind.
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <button>点击</button>
    <button>点击</button>
    <button>点击</button>
    <script>
        // 改变函数内this指向  js提供了三种方法  call()  apply()  bind()

        // 3. bind()  绑定 捆绑的意思
        var o = {
            name: 'andy'
        };

        function fn(a, b) {
            console.log(this);
            console.log(a + b);


        };
        var f = fn.bind(o, 1, 2);
        f();
        // 1. 不会调用原来的函数   可以改变原来函数内部的this 指向
        // 2. 返回的是原函数改变this之后产生的新函数
        // 3. 如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向此时用bind
        // 4. 我们有一个按钮,当我们点击了之后,就禁用这个按钮,3秒钟之后开启这个按钮
        // var btn1 = document.querySelector('button');
        // btn1.onclick = function() {
        //     this.disabled = true; // 这个this 指向的是 btn 这个按钮
        //     // var that = this;
        //     setTimeout(function() {
        //         // that.disabled = false; // 定时器函数里面的this 指向的是window
        //         this.disabled = false; // 此时定时器函数里面的this 指向的是btn
        //     }.bind(this), 3000); // 这个this 指向的是btn 这个对象
        // }
        var btns = document.querySelectorAll('button');
        for (var i = 0; i < btns.length; i++) {
            btns[i].onclick = function() {
                this.disabled = true;
                setTimeout(function() {
                    this.disabled = false;
                }.bind(this), 2000);
            }
        }
    </script>
</body>

</html>

call apply bind summary

Same point:

 Both can change the this pointer inside the function.

Differences:

1. call and apply will call the function, and change the internal this point of the function;

2. The parameters passed by call and apply are different. Call passes parameters aru1, aru2.. The form apply must be in the form of an array [arg];

3. bind will not call the function, and can change the internal this point of the function.

Main application scenarios:

1. call often does inheritance;

2. apply is often related to arrays. For example, use mathematical objects to realize the maximum and minimum values ​​of the array;

3. bind does not call the function, but still wants to change the this point. For example, change the this point inside the timer.

04 - Strict Mode 

What is strict mode

In addition to providing normal mode, JavaScript also provides strict mode (strict mode) . ES5's strict mode is a way to adopt a restrictive variant of JavaScript that runs JS code under strict conditions.

Strict mode is only supported in browsers with versions above IE10, and will be ignored in browsers with older versions.

Strict mode makes some changes to normal JavaScript semantics:

1. Eliminate some unreasonable and imprecise parts of Javascript syntax, and reduce some weird behaviors.

2. Eliminate some unsafe aspects of code operation to ensure the safety of code operation.

3. Improve compiler efficiency and increase running speed.

4. Some grammars that may be defined in future versions of ECMAScript are disabled to pave the way for future new versions of Javascript. For example, some reserved words such as: class, enum, export, extends, import, super cannot be used as variable names

Enable strict mode

Strict mode can be applied to the entire script or to individual functions . Therefore, when using it, we can divide strict mode into two cases: enabling strict mode for scripts and enabling strict mode for functions .

1. Enable strict mode for scripts

Some scripts are basically in strict mode, and some scripts are in normal mode, which is not conducive to file merging, so you can put the entire script file in an anonymous function that is executed immediately. This creates a scope independently without affecting other script files. 

<script>
   (function (){
      "use strict";
      var num = 10;
      function fn() {}
    })();
</script>

 2. Enable strict mode for functions

To enable strict mode for a function, place the "use strict"; (or 'use strict'; ) declaration before all statements in the function body .

function fn(){
    "use strict";
    return "这是严格模式。";
}

Put "use strict" on the first line  of the function body , and the whole function will run in "strict mode".

<body>
    <!-- 为整个脚本(script标签)开启严格模式 -->
    <script>
        'use strict';
        //   下面的js 代码就会按照严格模式执行代码
    </script>
    <script>
        (function() {
            'use strict';
        })();
    </script>
    <!-- 为某个函数开启严格模式 -->
    <script>
        // 此时只是给fn函数开启严格模式
        function fn() {
            'use strict';
            // 下面的代码按照严格模式执行
        }

        function fun() {
            // 里面的还是按照普通模式执行
        }
    </script>
</body>

Changes in strict mode

Strict mode makes some changes to the syntax and behavior of Javascript.

1. Variable specification

① In normal mode, if a variable is assigned without declaration, it defaults to a global variable. Strict mode prohibits this usage, and variables must be declared with the var command before being used.

② It is strictly forbidden to delete declared variables. For example, delete x; syntax is wrong. 

2. This points to the problem in strict mode

① Previously, this in the global scope function pointed to the window object.

② In strict mode, this in the function in the global scope is undefined.

③ In the past, it can be called without adding new when constructing a function. When it is an ordinary function, this points to the global object

④ In strict mode, if the constructor is called without adding new, this points to undefined and if it is assigned a value, an error will be reported

⑤ The constructor instantiated by new points to the created object instance.

⑥ The timer this still points to window.

⑦ Events and objects still point to the caller.

3. Function changes

① Functions cannot have parameters with the same name .

② The function must be declared at the top level. Newer versions of JavaScript introduce "block scoping" (introduced in ES6). In keeping with the new version, functions are not allowed to be declared inside a non-function block.

More strict mode requirements reference:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode

<script>
    'use strict';
    // 1. 我们的变量名必须先声明再使用
    // num = 10;
    // console.log(num);
    var num = 10;
    console.log(num);
    // 2.我们不能随意删除已经声明好的变量
    // delete num;
    // 3. 严格模式下全局作用域中函数中的 this 是 undefined。
    // function fn() {
    //     console.log(this); // undefined。

    // }
    // fn();
    // 4. 严格模式下,如果 构造函数不加new调用, this 指向的是undefined 如果给他赋值则 会报错.
    // function Star() {
    //     this.sex = '男';
    // }
    // // Star();
    // var ldh = new Star();
    // console.log(ldh.sex);
    // 5. 定时器 this 还是指向 window 
    // setTimeout(function() {
    //     console.log(this);

    // }, 2000);
    // a = 1;
    // a = 2;
    // 6. 严格模式下函数里面的参数不允许有重名
    // function fn(a, a) {
    //     console.log(a + a);

    // };
    // fn(1, 2);
    function fn() {}
</script>

05 - Higher order functions

Higher-order functions are functions that operate on other functions, receiving functions as arguments or outputting functions as return values .

<script>
    function fn(callback){
      callback&&callback();
    }
    fn(function(){alert('hi')}
</script>
<script>
    function fn(){
      return function() {}
    }
    fn();
</script>

At this point fn is a higher-order function

A function is also a data type, which can also be used as a parameter and passed to another parameter. The most typical is as a callback function.

Similarly, functions can also be passed back as return values

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="jquery.min.js"></script>
    <style>
        div {
            position: absolute;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    </style>
</head>

<body>
    <div></div>
    <script>
        // 高阶函数- 函数可以作为参数传递
        function fn(a, b, callback) {
            console.log(a + b);
            callback && callback();
        }
        fn(1, 2, function() {
            console.log('我是最后调用的');

        });
        $("div").animate({
            left: 500
        }, function() {
            $("div").css("backgroundColor", "purple");
        })
    </script>
</body>

</html>

06 - Closures

variable scope

Variables are divided into two types according to their scope: global variables and local variables.

1. Global variables can be used inside the function.

2. Local variables cannot be used outside the function.

3. When the function is executed, the local variables in this scope will be destroyed.

What is a closure

A closure is a function that has access to variables in the scope of another function. ----- JavaScript advanced programming

The simple understanding is that a scope can access local variables inside another function. 

<script>
    function fn1(){ // fn1 就是闭包函数
      var num = 10;
      function fn2(){
        console.log(num); // 10
      }
    fn2()
    }
    fn1();
</script>
<script>
    // 闭包(closure)指有权访问另一个函数作用域中变量的函数。
    // 闭包: 我们fun 这个函数作用域 访问了另外一个函数 fn 里面的局部变量 num
    function fn() {
        var num = 10;

        function fun() {
            console.log(num);

        }
        fun();
    }
    fn();
</script>

Debug closures in chrome 

1. Open the browser and press the F12 key to start the chrome debugging tool.

2. Set a breakpoint.

3. Find the Scope option (the meaning of Scope scope).

4. When we refresh the page again, we will enter the breakpoint debugging, and there will be two parameters in Scope (global global scope, local local scope).

5. When fn2() is executed, there will be an additional Closure parameter in Scope, which indicates that a closure has been generated.

The role of closure

<script>
    // 闭包(closure)指有权访问另一个函数作用域中变量的函数。
    // 一个作用域可以访问另外一个函数的局部变量 
    // 我们fn 外面的作用域可以访问fn 内部的局部变量
    // 闭包的主要作用: 延伸了变量的作用范围
    function fn() {
        var num = 10;

        // function fun() {
        //     console.log(num);

        // }
        // return fun;
        return function() {
            console.log(num);
        }
    }
    var f = fn();
    f();
    // 类似于
    // var f = function() {
    //         console.log(num);
    //     }
    // var f =  function fun() {
    //         console.log(num);

    //     }
</script>

Closure application --- click li to output the index number

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <ul class="nav">
        <li>榴莲</li>
        <li>臭豆腐</li>
        <li>鲱鱼罐头</li>
        <li>大猪蹄子</li>
    </ul>
    <script>
        // 闭包应用-点击li输出当前li的索引号
        // 1. 我们可以利用动态添加属性的方式
        var lis = document.querySelector('.nav').querySelectorAll('li');
        for (var i = 0; i < lis.length; i++) {
            lis[i].index = i;
            lis[i].onclick = function () {
                // console.log(i);
                console.log(this.index);

            }
        }
        // 2. 利用闭包的方式得到当前小li 的索引号
        for (var i = 0; i < lis.length; i++) {
            // 利用for循环创建了4个立即执行函数
            // 立即执行函数也成为小闭包因为立即执行函数里面的任何一个函数都可以使用它的i这变量
            (function (i) {
                // console.log(i);
                lis[i].onclick = function () {
                    console.log(i);

                }
            })(i);
        }
    </script>
</body>

</html>

Closure case

1. Loop to register the click event.

2. setTimeout() in the loop.

3. Calculate the taxi price.

<script>
    // 闭包应用-计算打车价格 
    // 打车起步价13(3公里内),  之后每多一公里增加 5块钱.  用户输入公里数就可以计算打车价格
    // 如果有拥堵情况,总价格多收取10块钱拥堵费
    // function fn() {};
    // fn();
    var car = (function() {
        var start = 13; // 起步价  局部变量
        var total = 0; // 总价  局部变量
        return {
            // 正常的总价
            price: function(n) {
                if (n <= 3) {
                    total = start;
                } else {
                    total = start + (n - 3) * 5
                }
                return total;
            },
            // 拥堵之后的费用
            yd: function(flag) {
                return flag ? total + 10 : total;
            }
        }
    })();
    console.log(car.price(5)); // 23
    console.log(car.yd(true)); // 33

    console.log(car.price(1)); // 13
    console.log(car.yd(false)); // 13
</script>

Thinking questions:

<script>
    // 思考题 1:

    var name = "The Window";
    var object = {
        name: "My Object",
        getNameFunc: function () {
            return function () {
                return this.name;
            };
        }
    };

    console.log(object.getNameFunc()())
    var f = object.getNameFunc();
    // 类似于
    var f = function () {
        return this.name;
    }
    f();

    // 思考题 2:

     var name = "The Window";
     var object = {
         name: "My Object",
         getNameFunc: function() {
             var that = this;
             return function() {
                 return that.name;
             };
         }
     };
     console.log(object.getNameFunc()())
     var f = object.getNameFunc();
     var f1 = function () {
         return that.name;
     };
     f1();
</script>

Closure summary

1. What is a closure?

A closure is a function (one scope can access local variables of another function)

2. What is the function of closure?

Extend the scope of variables

07 - Recursion

what is recursion

A function is recursive if it can call itself internally .

Simple understanding: the function calls itself internally, and this function is a recursive function.

A recursive function works the same as a loop

Since recursion is prone to "stack overflow" errors (stack overflow), it is necessary to add the exit condition return .

<script>
    // 递归函数 : 函数内部自己调用自己, 这个函数就是递归函数
    var num = 1;

    function fn() {
        console.log('我要打印6句话');

        if (num == 6) {
            return; // 递归里面必须加退出条件
        }
        num++;
        fn();
    }
    fn();
</script>

Use recursion to solve math problems

1. Find the factorial of 1 * 2 *3 ... * n.

<script>
    // 利用递归函数求1~n的阶乘 1 * 2 * 3 * 4 * ..n
    function fn(n) {
        if (n == 1) {
            return 1;
        }
        return n * fn(n - 1);
    }
    console.log(fn(3));
    console.log(fn(4));
    // 详细思路 假如用户输入的是3
    //return  3 * fn(2)
    //return  3 * (2 * fn(1))
    //return  3 * (2 * 1)
    //return  3 * (2)
    //return  6
</script>

2. Find the Fibonacci sequence. 

<script>
    // 利用递归函数求斐波那契数列(兔子序列)  1、1、2、3、5、8、13、21...
    // 用户输入一个数字 n 就可以求出 这个数字对应的兔子序列值
    // 我们只需要知道用户输入的n 的前面两项(n-1 n-2)就可以计算出n 对应的序列值
    function fb(n) {
        if (n === 1 || n === 2) {
            return 1;
        }
        return fb(n - 1) + fb(n - 2);
    }
    console.log(fb(3));
    console.log(fb(6));
</script>

3. Return the corresponding data object according to the id

<script>
    var data = [{
        id: 1,
        name: '家电',
        goods: [{
            id: 11,
            gname: '冰箱',
            goods: [{
                id: 111,
                gname: '海尔'
            }, {
                id: 112,
                gname: '美的'
            }, ]
        }, {
            id: 12,
            gname: '洗衣机'
        }]
    }, {
        id: 2,
        name: '服饰'
    }];
    // 我们想要做输入id号,就可以返回的数据对象
    // 1. 利用 forEach 去遍历里面的每一个对象
    function getID(json, id) {
        var o = {};
        json.forEach(function(item) {
            // console.log(item); // 2个数组元素
            if (item.id == id) {
                // console.log(item);
                o = item;
                // 2. 我们想要得里层的数据 11 12 可以利用递归函数
                // 里面应该有goods这个数组并且数组的长度不为 0 
            } else if (item.goods && item.goods.length > 0) {
                o = getID(item.goods, id);
            }

        });
        return o;
    }
    console.log(getID(data, 1));
    console.log(getID(data, 2));
    console.log(getID(data, 11));
    console.log(getID(data, 12));
    console.log(getID(data, 111));
</script>

shallow copy and deep copy

1. Shallow copy only copies one layer, and only copy references at the deeper object level.

2. Deep copy copies multiple layers, and the data at each level will be copied.

3. Object.assign(target, ...sources) es6 new method can shallow copy

shallow copy:

<script>
    // 浅拷贝只是拷贝一层, 更深层次对象级别的只拷贝引用.
    // 深拷贝拷贝多层, 每一级别的数据都会拷贝.
    var obj = {
        id: 1,
        name: 'andy',
        msg: {
            age: 18
        }
    };
    var o = {};
    // for (var k in obj) {
    //     // k 是属性名   obj[k] 属性值
    //     o[k] = obj[k];
    // }
    // console.log(o);
    // o.msg.age = 20;
    // console.log(obj);

    console.log('--------------');
    Object.assign(o, obj);
    console.log(o);
    o.msg.age = 20;
    console.log(obj);
</script>

Deep copy:

<script>
    // 深拷贝拷贝多层, 每一级别的数据都会拷贝.
    var obj = {
        id: 1,
        name: 'andy',
        msg: {
            age: 18
        },
        color: ['pink', 'red']
    };
    var o = {};
    // 封装函数 
    function deepCopy(newobj, oldobj) {
       for (var k in oldobj) {
            // 判断我们的属性值属于那种数据类型
            // 1. 获取属性值  oldobj[k]
            var item = oldobj[k];
            // 2. 判断这个值是否是数组
            if (item instanceof Array) {
                newobj[k] = [];
                deepCopy(newobj[k], item)
            } else if (item instanceof Object) {
                // 3. 判断这个值是否是对象
                newobj[k] = {};
                deepCopy(newobj[k], item)
            } else {
                // 4. 属于简单数据类型
                newobj[k] = item;
            }

        }
    }
    deepCopy(o, obj);
    console.log(o);

    var arr = [];
    console.log(arr instanceof Object);
    o.msg.age = 20;
    console.log(obj);
</script>

Day 4 - Regular Expressions

01 - Learning objectives (target)

  • Be able to tell what a regular expression does 
  • Ability to write simple regular expressions
  • Ability to validate forms using regular expressions
  • Ability to replace content using regular expressions

02 - Regular Expression Overview

what is a regular expression

A regular expression (Regular Expression) is a pattern for matching character combinations in a string. In JavaScript, regular expressions are also objects.

Regular tables are usually used to retrieve and replace text that conforms to a certain pattern (rule), such as a verification form: only English letters, numbers or underscores can be entered in the user name form, and Chinese characters can be entered in the nickname input box (matching ) . In addition, regular expressions are often used to filter out some sensitive words in the page content (replacement), or to obtain the specific part we want from the string ( extraction ), etc.

Other languages ​​also use regular expressions. At this stage, we mainly use JavaScript regular expressions to complete form validation. 

Features of regular expressions

1. Flexibility, logic and functionality are very strong.

2. The complex control of strings can be quickly achieved in an extremely simple way.

3. For those new to contact, it is relatively obscure. For example: ^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$

4. In actual development, the written regular expressions are generally copied directly. However, it is required to use regular expressions and modify the regular expressions according to the actual situation. For example, username: /^[a-z0-9_-]{3,16}$/ 

03 - The use of regular expressions in JavaScript

Create a regular expression

In JavaScript, a regular expression can be created in two ways.

1. Created by calling the constructor of the RegExp object

      var variable name = new RegExp(/expression/);

2. Created by literal

      var variable name = /expression/;

// Note: The expression in the middle is a regular literal

Test regular expression test

test() Regular object method, used to detect whether the string conforms to the rule, the object will return true or false, and its parameter is the test string.

 regexObj.test(str)
  • regexObj is the regular expression written
  • str the text we want to test
  • It is to detect whether the str text conforms to the regular expression specification we wrote.
<script>
    // 正则表达式在js中的使用

    // 1. 利用 RegExp对象来创建 正则表达式
    var regexp = new RegExp(/123/);
    console.log(regexp);

    // 2. 利用字面量创建 正则表达式
    var rg = /123/;
    // 3.test 方法用来检测字符串是否符合正则表达式要求的规范
    console.log(rg.test(123));
    console.log(rg.test('abc'));
</script>

04 - Special characters in regular expressions

The composition of regular expressions 

A regular expression can consist of simple characters , such as /abc/, or a combination of simple and special characters , such as /ab*c/. Among them, special characters are also called metacharacters , which are special symbols with special meanings in regular expressions , such as ^, $, +, etc. 

There are many special characters, you can refer to:

● MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions

● jQuery Manual: Regular Expressions section

● Regularity test tool: http://tool.oschina.net/regex

Here we divide metacharacters into several categories for learning.

boundary character

The boundary character (position character) in the regular expression is used to prompt the position of the character , and there are mainly two characters. 

boundary character illustrate
^ Indicates the text that matches the beginning of the line (starting with whom)
$ Indicates the text that matches the end of the line (who ends with it)

If ^ and $ are together, it must be an exact match.

 <script>
    // 边界符 ^ $ 
    var rg = /abc/; // 正则表达式里面不需要加引号 不管是数字型还是字符串型
    // /abc/ 只要包含有abc这个字符串返回的都是true
    console.log(rg.test('abc'));
    console.log(rg.test('abcd'));
    console.log(rg.test('aabcd'));
    console.log('---------------------------');
    var reg = /^abc/;
    console.log(reg.test('abc')); // true
    console.log(reg.test('abcd')); // true
    console.log(reg.test('aabcd')); // false
    console.log('---------------------------');
    var reg1 = /^abc$/; // 精确匹配 要求必须是 abc字符串才符合规范
    console.log(reg1.test('abc')); // true
    console.log(reg1.test('abcd')); // false
    console.log(reg1.test('aabcd')); // false
    console.log(reg1.test('abcabc')); // false
</script>

character class

A character class indicates that there are a series of characters to choose from, as long as one of them matches. All optional characters are enclosed in square brackets

1. [] square brackets

/[abc]/.test('andy') // true 

 As long as the following string contains any character in abc, it will return true.

2. [-] The range character inside the square brackets -

/^[a-z]$/.test(c') // true

Add - inside the square brackets to indicate the range , here it means 26 English letters from a to z .

3. [^] Negation character inside the square brackets ^

/[^abc]/.test('andy') // false

Adding ^ inside the square brackets means negation , as long as the characters in the square brackets are included, false will be returned.

Note that it is different from the boundary character ^, which is written outside the square brackets.

4. Combination of characters

/[a-z1-9]/.test('andy') // true

 Character combinations can be used inside the square brackets, which means that 26 English letters including a to z and numbers from 1 to 9 are all available.

<script>
    //var rg = /abc/;  只要包含abc就可以 
    // 字符类: [] 表示有一系列字符可供选择,只要匹配其中一个就可以了
    var rg = /[abc]/; // 只要包含有a 或者 包含有b 或者包含有c 都返回为true
    console.log(rg.test('andy'));
    console.log(rg.test('baby'));
    console.log(rg.test('color'));
    console.log(rg.test('red'));
    var rg1 = /^[abc]$/; // 三选一 只有是a 或者是 b  或者是c 这三个字母才返回 true
    console.log(rg1.test('aa'));
    console.log(rg1.test('a'));
    console.log(rg1.test('b'));
    console.log(rg1.test('c'));
    console.log(rg1.test('abc'));
    console.log('------------------');

    var reg = /^[a-z]$/; // 26个英文字母任何一个字母返回 true  - 表示的是a 到z 的范围  
    console.log(reg.test('a'));
    console.log(reg.test('z'));
    console.log(reg.test(1));
    console.log(reg.test('A'));
    // 字符组合
    var reg1 = /^[a-zA-Z0-9_-]$/; // 26个英文字母(大写和小写都可以)任何一个字母返回 true  
    console.log(reg1.test('a'));
    console.log(reg1.test('B'));
    console.log(reg1.test(8));
    console.log(reg1.test('-'));
    console.log(reg1.test('_'));
    console.log(reg1.test('!'));
    console.log('----------------');
    // 如果中括号里面有^ 表示取反的意思 千万和 我们边界符 ^ 别混淆
    var reg2 = /^[^a-zA-Z0-9_-]$/;
    console.log(reg2.test('a'));
    console.log(reg2.test('B'));
    console.log(reg2.test(8));
    console.log(reg2.test('-'));
    console.log(reg2.test('_'));
    console.log(reg2.test('!'));
</script>

Quantifier

Quantifiers are used to set the number of occurrences of a pattern

quantifier         illustrate
* Repeat zero or more times
+ repeat one or more times
? Repeat zero or one time
{n} repeat n times
{n,} repeat n or more times
{n,m} Repeat n to m times
<script>
    // 量词符: 用来设定某个模式出现的次数
    // 简单理解: 就是让下面的a这个字符重复多少次
    // var reg = /^a$/;


    //  * 相当于 >= 0 可以出现0次或者很多次 
    // var reg = /^a*$/;
    // console.log(reg.test(''));
    // console.log(reg.test('a'));
    // console.log(reg.test('aaaa'));



    //  + 相当于 >= 1 可以出现1次或者很多次
    // var reg = /^a+$/;
    // console.log(reg.test('')); // false
    // console.log(reg.test('a')); // true
    // console.log(reg.test('aaaa')); // true

    //  ?  相当于 1 || 0
    // var reg = /^a?$/;
    // console.log(reg.test('')); // true
    // console.log(reg.test('a')); // true
    // console.log(reg.test('aaaa')); // false

    //  {3 } 就是重复3次
    // var reg = /^a{3}$/;
    // console.log(reg.test('')); // false
    // console.log(reg.test('a')); // false
    // console.log(reg.test('aaaa')); // false
    // console.log(reg.test('aaa')); // true
    //  {3, }  大于等于3
    var reg = /^a{3,}$/;
    console.log(reg.test('')); // false
    console.log(reg.test('a')); // false
    console.log(reg.test('aaaa')); // true
    console.log(reg.test('aaa')); // true
    //  {3,16}  大于等于3 并且 小于等于16
    var reg = /^a{3,6}$/;
    console.log(reg.test('')); // false
    console.log(reg.test('a')); // false
    console.log(reg.test('aaaa')); // true
    console.log(reg.test('aaa')); // true
    console.log(reg.test('aaaaaaa')); // false
</script>

Case: Username Verification

Functional Requirements:

1. If the user name input is legal, the following prompt information is: User name is legal, and the color is green

2. If the input of the user name is invalid, the following prompt message will be: The user name does not meet the specification, and the color is green

analyze:

1. The user name can only be composed of English letters, numbers, underscores or dashes, and the length of the user name is 6~16 characters

2. First prepare this regular expression pattern /$[a-zA-Z0-9-_]{6,16}^/

3. Start validation when the form loses focus

4. If it conforms to the regular specification, let the following span tag add the right class

5. If it does not conform to the regular specification, let the following span tag add the wrong class

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        span {
            color: #aaa;
            font-size: 14px;
        }
        
        .right {
            color: green;
        }
        
        .wrong {
            color: red;
        }
    </style>
</head>

<body>
    <input type="text" class="uname"> <span>请输入用户名</span>
    <script>
        //  量词是设定某个模式出现的次数
        var reg = /^[a-zA-Z0-9_-]{6,16}$/; // 这个模式用户只能输入英文字母 数字 下划线 短横线但是有边界符和[] 这就限定了只能多选1
        // {6,16}  中间不要有空格
        // console.log(reg.test('a'));
        // console.log(reg.test('8'));
        // console.log(reg.test('18'));
        // console.log(reg.test('aa'));
        // console.log('-------------');
        // console.log(reg.test('andy-red'));
        // console.log(reg.test('andy_red'));
        // console.log(reg.test('andy007'));
        // console.log(reg.test('andy!007'));
        var uname = document.querySelector('.uname');
        var span = document.querySelector('span');
        uname.onblur = function() {
            if (reg.test(this.value)) {
                console.log('正确的');
                span.className = 'right';
                span.innerHTML = '用户名格式输入正确';
            } else {
                console.log('错误的');
                span.className = 'wrong';
                span.innerHTML = '用户名格式输入不正确';
            }
        }
    </script>
</body>

</html>

parentheses summary

1. Braces quantifiers. inside the number of repetitions

2. Brackets Set of characters. Matches any character in square brackets.

3. Parentheses indicate priority

You can test it online: https://c.runoob.com/

<script>
    // 中括号 字符集合.匹配方括号中的任意字符. 
    // var reg = /^[abc]$/;
    // a 也可以 b 也可以 c 可以  a ||b || c
    // 大括号  量词符. 里面表示重复次数
    // var reg = /^abc{3}$/; // 它只是让c重复三次   abccc
    // console.log(reg.test('abc'));
    // console.log(reg.test('abcabcabc'));
    // console.log(reg.test('abccc'));

    // 小括号 表示优先级
    var reg = /^(abc){3}$/; // 它是让abcc重复三次
    console.log(reg.test('abc'));
    console.log(reg.test('abcabcabc'));
    console.log(reg.test('abccc'));
</script>

predefined class

Predefined classes refer to shorthand for some common patterns

scheduled class illustrate
\d Matches any number from 0-9. Equivalent to [0-9]
\D Matches characters other than 0-9. Equivalent to [^0-9]
\w Match any letter, number and underscore, equivalent to [A-Za-z0-9_]
\W Characters other than all letters, numbers, and underscores, equivalent to [^A-Za-z0-9_]
\s Match spaces (including newlines, tabs, spaces, etc.), equivalent to [\t\r\n\v\f]
\S Match non-space characters, equivalent to [^\t\r\n\v\f]

Case: landline number verification

<script>
    // 座机号码验证:  全国座机号码  两种格式:   010-12345678  或者  0530-1234567
    // 正则里面的或者 符号  |  
    // var reg = /^\d{3}-\d{8}|\d{4}-\d{7}$/;
    var reg = /^\d{3,4}-\d{7,8}$/;
</script>

05 - Substitutions in regular expressions

replace replace

The replace() method can implement the replacement string operation, and the parameter used for replacement can be a string or a regular expression. 

stringObject.replace(regexp/substr,replacement)
  • The first parameter: the string or regular expression to be replaced
  • Second parameter: the string to replace with
  • The return value is a replaced new string

regular expression parameter

/表达式/[switch]

 The switch (also known as a modifier) ​​matches according to what pattern. There are three values:

● g: global match

● i: ignore case

● gi: global match + ignore case

Case: sensitive word filtering

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        textarea {
            width: 300px;
            height: 100px;
            border: 1px solid #ccc;
        }
    </style>
</head>

<body>
    <textarea name="" id="message"></textarea> <button>提交</button>
    <div></div>
    <script>
        // 替换 replace
        // var str = 'andy和red';
        // // var newStr = str.replace('andy', 'baby');
        // var newStr = str.replace(/andy/, 'baby');
        // console.log(newStr);
        var text = document.querySelector('textarea');
        var btn = document.querySelector('button');
        var div = document.querySelector('div');
        btn.onclick = function() {
            div.innerHTML = text.value.replace(/激情|gay/g, '**');
        }
    </script>
</body>

</html>

Day 5 - Partial knowledge of ES6 

01 - learning objectives (target)

  • Be able to name the characteristics of variables declared using the let keyword
  • Ability to extract values ​​from arrays using destructuring assignment
  • Be able to name the properties that arrow functions have
  • Ability to receive remaining function arguments using remaining arguments
  • Ability to split arrays using the spread operator
  • Be able to say what attributes a template string has

02 - Introduction to ES6

What is ES6

The full name of ES is ECMAScript, which is a standardized specification of scripting language formulated by ECMA International Organization for Standardization. 

 ES6 is actually a general term, referring to ES2015 and subsequent versions.

Why use ES6

The birth of each standard means the improvement of language and the enhancement of functions. There are also some unsatisfactory aspects of the JavaScript language itself.

  • The variable hoisting feature increases the unpredictability of program runtime
  • The syntax is too loose, to achieve the same function, different people may write different codes

03 - New syntax for ES6

let keyword

A new keyword for declaring variables in ES6.

● Variables declared by let are only valid at the block level

if (true) {
    let a = 10;
}
console.log(a) // a is not defined

 Note: Variables declared with the let keyword have block-level scope, and variables declared with var do not have block-level scope.

● There is no variable hoisting 

console.log(a); // a is not defined 
let a = 20;

● Temporary dead zone

var tmp = 123;
  if (true) {
    tmp = 'abc';
    let tmp;
}
<script type="text/javascript">
/*
	let关键字就是用来声明变量的

	使用let关键字声明的变量具有块级作用域

	在一个大括号中 使用let关键字声明的变量才具有块级作用域 var关键字是不具备这个特点的

	防止循环变量变成全局变量

	使用let关键字声明的变量没有变量提升

	使用let关键字声明的变量具有暂时性死区特性

*/
		
/* --------let关键字就是用来声明变量的-------- */
	// let a = 10;
	// console.log(a);
		
/* --------使用let关键字声明的变量具有块级作用域-------- */
	// if (true) {
	// 	let b = 20;
	// 	console.log(b)
	// 	if (true) {
	// 		let c = 30;
	// 	}
	// 	console.log(c);
	// }
	// console.log(b)
		
/* -------在一个大括号中 使用let关键字声明的变量才具有块级作用域 var关键字是不具备这个特点的--------- */

	// if (true) {
	// 	let num = 100;
	// 	var abc = 200;
	// }
	// console.log(abc);
	// console.log(num)


/* -------防止循环变量变成全局变量--------- */
	// for (let i = 0; i < 2; i++) {}
	// console.log(i);
		

/*-----使用let关键字声明的变量没有变量提升------*/
	// console.log(a);
	// let a = 100;
		

/* -------使用let关键字声明的变量具有暂时性死区特性------- */
	var num = 10
	if (true) {
		console.log(num);
		let num = 20;
	}

</script>

classic interview questions

Illustration of classic interview questions: The key point of this question is that the variable i is global, and the value of i  in the global scope is output when the function is executed .

 

Illustration of classic interview questions: The key point of this question is that each cycle will generate a block-level scope, and the variables in each block-level scope are different. When the function is executed, the output is its own upper level (generated by the cycle) block-level scope) the value of i under the scope .

<script type="text/javascript">
	let arr = [];

	for (let i = 0; i < 2; i++) {
		arr[i] = function () {
			console.log(i);
		}
	}

	arr[0]();
	arr[1]();
</script>

const keyword

Function: Declare a constant, which is a quantity whose value (memory address) cannot change.

● Has block scope 

if (true) {
  const a = 10;
}
console.log(a) // a is not defined

● A value must be assigned when declaring a constant

const PI; // Missing initializer in const declaration

● After the constant is assigned, the value cannot be modified.

const PI = 3.14;
PI = 100; // Assignment to constant variable. 
const ary = [100, 200];
ary[0] = 'a';
ary[1] = 'b';
console.log(ary); // ['a', 'b']; 
ary = ['a', 'b']; // Assignment to constant variable.
<script type="text/javascript">
	// 使用const关键字声明的常量具有块级作用域
	// if (true) {
	// 	const a = 10;
	// 	if (true) {
	// 		const a = 20;
	// 		console.log(a);
	// 	}
	// 	console.log(a);
	// }
	// console.log(a);
		
	// 使用const关键字声明的常量必须赋初始值
	// const PI = 3.14;
		
	// 常量声明后值不可更改 
	const PI = 3.14;
	// PI = 100;
	const ary = [100, 200];
	ary[0] = 123;
	ary = [1, 2]
	console.log(ary);
</script>

The difference between let, const, and var

1. The scope of the variable declared with var is within the function where the statement is located, and there is a phenomenon of variable promotion.

2. The scope of the variable declared with let is within the code block where the statement is located, and there is no variable promotion.

3. Use const to declare a constant, and the value of the constant cannot be modified in the code that appears later. 

destructuring assignment

ES6 allows extracting values ​​from arrays and assigning values ​​to variables according to the corresponding positions. Objects can also be destructured.

array destructuring 

let [a, b, c] = [1, 2, 3];
console.log(a)
console.log(b)
console.log(c)

If the destructuring is unsuccessful, the value of the variable is undefined.

let [foo] = [];
let [bar, foo] = [1];
<script type="text/javascript">
	// 数组解构允许我们按照一一对应的关系从数组中提取值 然后将值赋值给变量
	let ary = [1,2,3];
	let [a, b, c, d, e] = ary;
	console.log(a)
	console.log(b)
	console.log(c)
	console.log(d)
	console.log(e)
</script>

object deconstruction

let person = { name: 'zhangsan', age: 20 };
let { name, age } = person;
console.log(name); // 'zhangsan' 
console.log(age); // 20
let {name: myName, age: myAge} = person; // myName myAge 属于别名
console.log(myName); // 'zhangsan' 
console.log(myAge); // 20
<script type="text/javascript">
	// 对象解构允许我们使用变量的名字匹配对象的属性 匹配成功 将对象属性的值赋值给变量
		
	let person = {name: 'lisi', age: 30, sex: '男'};
	// let { name, age, sex } = person;
	// console.log(name)
	// console.log(age)
	// console.log(sex)
		
	let {name: myName} = person;
	console.log(myName)

</script>

arrow function

A new way to define functions in ES6.

() => {} 
const fn = () => {}

 There is only one sentence of code in the function body, and the execution result of the code is the return value, so the braces can be omitted

function sum(num1, num2) {
    return num1 + num2;
}
const sum = (num1, num2) => num1 + num2;

If there is only one formal parameter, parentheses can be omitted

function fn (v) {
    return v;
}
const fn = v => v;

The arrow function does not bind the this keyword, the this in the arrow function points to the context this of the function definition location .

const obj = { name: '张三'}
function fn () {
    console.log(this);
    return () => {
      console.log(this)
    }
}
const resFn = fn.call(obj);
resFn();
<script type="text/javascript">
	// 箭头函数是用来简化函数定义语法的
	// const fn = () => {
	// 	console.log(123)
	// }
	// fn();
		
// 在箭头函数中 如果函数体中只有一句代码 并且代码的执行结果就是函数的返回值 函数体大括号可以省略
	// const sum = (n1, n2) => n1 + n2;	 
	// const result = sum(10, 20);
	// console.log(result)
		
	// 在箭头函数中 如果形参只有一个 形参外侧的小括号也是可以省略的
	// const fn = v => {
	// 	alert(v);
	// }
	// fn(20)
		
// 箭头函数不绑定this 箭头函数没有自己的this关键字 如果在箭头函数中使用this this关键字将指向箭头函数定义位置中的this
		
	function fn () {
		console.log(this);
		return () => {
			console.log(this)
		}
	}

	const obj = {name: 'zhangsan'};

	const resFn = fn.call(obj);

	resFn();
</script>

Arrow function interview questions        

<script type="text/javascript">
	
	var age = 100;

	var obj = {
		age: 20,
		say: () => {
			alert(this.age)
		}
	}
    obj.say();
</script>

remaining parameters

The rest parameter syntax allows us to represent an indefinite number of parameters as an array.

function sum (first, ...args) {
    console.log(first); // 10
    console.log(args); // [20, 30] 
}
sum(10, 20, 30)

 Remaining parameters are used in conjunction with destructuring

let students = ['wangwu', 'zhangsan', 'lisi'];
let [s1, ...s2] = students;
console.log(s1); // 'wangwu' 
console.log(s2); // ['zhangsan', 'lisi']
<script type="text/javascript">
	// const sum = (...args) => {
	// 	let total = 0;
	// 	args.forEach(item => total += item);
	// 	return total;
	// };

	// console.log(sum(10, 20));
	// console.log(sum(10, 20, 30));
		

	let ary1 = ['张三' , '李四', '王五'];
	let [s1, ...s2] = ary1;
	console.log(s1)
	console.log(s2)

</script>

04 - ES6 built-in object extensions

Extension methods for Array 

spread operator (expansion syntax) 

The spread operator converts an array or object into a comma-separated sequence of arguments.

let ary = [1, 2, 3];
...ary // 1, 2, 3
console.log(...ary); // 1 2 3
console.log(1, 2, 3)

The spread operator can be applied to merge arrays.

// 方法一
let ary1 = [1, 2, 3];
let ary2 = [3, 4, 5];
let ary3 = [...ary1, ...ary2];
// 方法二
ary1.push(...ary2);

Convert an array-like or iterable object to a real array

let oDivs = document.getElementsByTagName('div');
oDivs = [...oDivs];
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>扩展运算符</title>
</head>
<body>
	<div>1</div>
	<div>4</div>
	<div>3</div>
	<div>6</div>
	<div>2</div>
	<div>5</div>
	<script type="text/javascript">
		// 扩展运算符可以将数组拆分成以逗号分隔的参数序列
		// let ary = ["a", "b", "c"];
		// ...ary // "a", "b", "c"
		// console.log(...ary)
		// console.log("a", "b", "c")
		
		// 扩展运算符应用于数组合并
		// let ary1 = [1, 2, 3];
		// let ary2 = [4, 5, 6];
		// // ...ary1 // 1, 2, 3
		// // ...ary1 // 4, 5, 6
		// let ary3 = [...ary1, ...ary2];
		// console.log(ary3)

		// 合并数组的第二种方法
		// let ary1 = [1, 2, 3];
		// let ary2 = [4, 5, 6];

		// ary1.push(...ary2);
		// console.log(ary1)
		
		// 利用扩展运算符将伪数组转换为真正的数组
		var oDivs = document.getElementsByTagName('div');
		console.log(oDivs)
		var ary = [...oDivs];
		ary.push('a');
		console.log(ary);
	</script>
</body>
</html>

Constructor method: Array.from()

Convert an array-like or iterable object to a real array

let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

The method can also accept the second parameter, which is similar to the map method of the array, which is used to process each element and put the processed value into the returned array.

let arrayLike = {
    "0": 1,
    "1": 2,
    "length": 2
}
let newAry = Array.from(aryLike, item => item *2)
<script type="text/javascript">
	// var arrayLike = {
	// 	"0": "张三",
	// 	"1": "李四",
	// 	"2": "王五",
	// 	"length": 3
	// }

	// var ary = Array.from(arrayLike);
	// console.log(ary)
		
	var arrayLike = {
		"0": "1",
		"1": "2",
		"length": 2
	}

	var ary = Array.from(arrayLike, item => item * 2)
	console.log(ary)
</script>

Instance method: find()

Used to find the first array member that meets the criteria, if not found return undefined.

let ary = [{
    id: 1,
    name: '张三‘
}, {
    id: 2,
    name: '李四‘
}];
let target = ary.find((item, index) => item.id == 2)
<script type="text/javascript">
	var ary = [{
		id: 1,
		name: '张三'
	}, {
		id: 2,
		name: '李四'
	}];
	let target = ary.find(item => item.id == 3);
	console.log(target)
</script>

Instance method: findIndex() 

 Used to find the position of the first array member that meets the criteria, if not found, return -1

let ary = [1, 5, 10, 15];
let index = ary.findIndex((value, index) => value > 9);
console.log(index); // 2
<script type="text/javascript">
	let ary = [10, 20, 50];
	let index = ary.findIndex(item => item > 15);
	console.log(index)
</script>

Instance method: includes()

Indicates whether an array contains the given value, returns a Boolean value.

[1, 2, 3].includes(2) // true 
[1, 2, 3].includes(4) // false
<script type="text/javascript">
	let ary = ["a", "b", "c"];

	let result = ary.includes('a')
	console.log(result)
	result = ary.includes('e')
	console.log(result)
</script>

Extension methods for String

template string 

ES6's new method of creating strings is defined using backticks.

let name = `zhangsan`;

 Variables can be resolved in template strings.

let name = '张三';
let sayHello = `hello,my name is ${name}`; // hello, my name is zhangsan

Newlines are allowed in template strings

let result = {
    name: 'zhangsan',
    age: 20,
    sex: '男'
}
let html = ` <div>
    <span>${result.name}</span>
    <span>${result.age}</span>
    <span>${result.sex}</span>
</div> `;

Functions can be called in template strings .

const sayHello = function () {
    return '哈哈哈哈 追不到我吧 我就是这么强大';
};
let greet = `${sayHello()} 哈哈哈哈`;
console.log(greet); // 哈哈哈哈 追不到我吧 我就是这么强大 哈哈哈哈
<script type="text/javascript">
	// let name = `张三`;
	// let sayHello = `Hello, 我的名字叫${name}`;
	// console.log(sayHello);
		
	// let result = {
	// 	name: "zhangsan",
	// 	age: 20
	// };
	// let html = `
	// 	<div>
	// 		<span>${result.name}</span>
	// 		<span>${result.age}</span>
	// 	</div>
	// `;
	// console.log(html);
	
	const fn = () => {
		return '我是fn函数'
	}

	let html = `我是模板字符串 ${fn()}`;
	console.log(html)

</script>

Instance methods: startsWith() and endsWith()

● startsWith(): indicates whether the parameter string is at the head of the original string, and returns a Boolean value

● endsWith(): indicates whether the parameter string is at the end of the original string, and returns a Boolean value 

let str = 'Hello world!';
str.startsWith('Hello') // true 
str.endsWith('!') // true
<script type="text/javascript">
	let str = 'Hello ECMAScript 2015';
	let r1 = str.startsWith('Hello');
	console.log(r1);
	let r2 = str.endsWith('2016');
	console.log(r2)
</script>

Instance method: repeat()

The repeat method means to repeat the original string n times and return a new string.

'x'.repeat(3) // "xxx" 
'hello'.repeat(2) // "hellohello"
<script type="text/javascript">
	console.log("y".repeat(5))
</script>

Set data structure

ES6 provides a new data structure Set. It is similar to an array, but the values ​​​​of the members are all unique, and there are no duplicate values.

Set itself is a constructor used to generate the Set data structure.

const s = new Set();

 The Set function can accept an array as a parameter for initialization.

const set = new Set([1, 2, 3, 4, 4]);

instance method

● add(value): add a value and return the Set structure itself

● delete(value): delete a value and return a Boolean value indicating whether the deletion is successful

● has(value): returns a Boolean value indicating whether the value is a member of Set

● clear(): clear all members, no return value 

const s = new Set();
s.add(1).add(2).add(3); // 向 set 结构中添加值
s.delete(2) // 删除 set 结构中的2值
s.has(1) // 表示 set 结构中是否有1这个值 返回布尔值
s.clear() // 清除 set 结构中的所有值

traverse

The instance of the Set structure, like an array, also has a forEach method, which is used to perform some operation on each member and has no return value.

s.forEach(value => console.log(value))

<script type="text/javascript">
	// const s1 = new Set();
	// console.log(s1.size)

	// const s2 = new Set(["a", "b"]);
	// console.log(s2.size)

	// const s3 = new Set(["a","a","b","b"]);
	// console.log(s3.size)
	// const ary = [...s3];
	// console.log(ary)
		
	// const s4 = new Set();
	// 向set结构中添加值 使用add方法
	// s4.add('a').add('b');
	// console.log(s4.size)

	// 从set结构中删除值 用到的方法是delete
	// const r1 = s4.delete('c');
	// console.log(s4.size)
	// console.log(r1);

	// 判断某一个值是否是set数据结构中的成员 使用has
	// const r2 = s4.has('d');
	// console.log(r2)

	// 清空set数据结构中的值 使用clear方法
	// s4.clear();
	// console.log(s4.size);
		
	// 遍历set数据结构 从中取值
	const s5 = new Set(['a', 'b', 'c']);
	s5.forEach(value => {
		console.log(value)
	})

</script>

This is the end here. This article mainly includes the PPT and example code of the ES6 part of the dark horse front-end tutorial on station B. I hope it will be helpful to everyone. If there are any mistakes in the article, please point them out in the comment area, thank you!

Guess you like

Origin blog.csdn.net/weixin_44566194/article/details/127568441