JS advanced knowledge summary

1. this points to the question

This points to: The point of this cannot be determined in the function definition. Only when the function is executed can it be determined who this points to. In general, the point of this is the object that calls it.

Generally divided into the following three situations:

  • In the global scope or normal function, this points to the global object window
  • In the method call, who calls this and points to whom
  • In the constructor this points to the instance of the constructor

1. In the global scope or ordinary function, this points to the global object window

The function call in the global scope is called by the window object, but when calling, it is generally omitted window., that is, it is fn()actuallywindow.fn

console.log(this); // Window {window: Window, …}
function fn() {
    
    
  console.log(this); // Window {window: Window, …}
}

fn(); // 等同于window.fn()
// 等同于window.setTimeout()
setTimeout(function () {
    
    
  console.log(this); // Window {window: Window, …}
}, 1000);

2. Who calls this in the method call and points to whom

obj = {
    
    
  fn: function () {
    
    
    console.log(this); // {fn: ƒ}
  }
};

obj.fn(); // obj对象调用了fn方法
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <button>点击一下</button>
    <script>
      var btn = document.querySelector("button");

      // btn调用了匿名函数
      btn.addEventListener("click", function () {
      
      
        console.log(this); // <button>点击一下</button>
      });
    </script>
  </body>
</html>

3. In the constructor, this points to the instance of the constructor

When creating an object, a new space will be opened, and this will point to this object

function Person() {
    
    
  console.log(this); // Person {}
}

var person = new Person(); // this指向的是person实例对象

2. Advanced objects

2.1 Definition and use of objects

1. Create objects using literals

// 创建对象
var obj = {
    
    
  name: "Bill",
  age: 18,
  sex: "男",
  sayHi: function () {
    
    
    console.log("hi");
  }
};

// 获取对象的属性
console.log(obj.age);
console.log(obj["age"]);

// 调用对象的方法
obj.sayHi();

2. Use the new keyword to create an object

// 创建空对象
var obj = new Object(); 

// 设置对象的属性和方法
obj.name = "Bill";
obj.age = 18;
obj.sex = "男";
obj.sayHi = function () {
    
    
  console.log("hi");
};

// 获取对象的属性
console.log(obj.age);
console.log(obj["age"]);

// 调用对象的方法
obj.sayHi();

Note: It is not recommended to use the new keyword to create objects

2.2 Object Accessor

Getterand the role Setterof :

  • Provides a more concise syntax
  • Allow properties and methods to have the same syntax
  • Can ensure better data quality

Note: The method name ofgetter and cannot be the same as the property namesetter

2.2.1 Getter

Getter: Use getthe keyword to get the attribute value of the object.

var person = {
    
    
  name: "Bill",
  age: 18,
  get uname() {
    
    
    return this.name;
  },
  get uage() {
    
    
    return this.age;
  }
};

console.log(person.uname); // Bill
console.log(person.uage); // 18

2.2.2 Setter

Setter: Use setthe keyword to set the attribute value of the object.

var person = {
    
    
  name: "Bill",
  age: 18,
  set uname(value) {
    
    
    this.name = value;
  },
  set uage(value) {
    
    
    this.age = value;
  }
};

person.uname = "Jackson";
person.uage = 20;
console.log(person.name, person.age); // Jackson 20

2.3 Object Constructor

Object constructor: It is a constructor, which can create objects of the same type by calling the constructor through newkeywords .

The role of the constructor: using 2.1the method of creating objects in the section, only a single object can be created, but through the constructor, many objects of the same type can be created.

1. Use the constructor to create multiple objects of the same type

// 1.定义构造函数
function Person(name, age, sex) {
    
    
  this.name = name;
  this.age = age;
  this.sex = sex;
  this.sayHi = function () {
    
    
    console.log("hi");
  };
}

// 2.调用构造函数来创建对象
var teacher = new Person("Jackson", 40, "male");
var student = new Person("Bill", 18, "male");

// 3.获取对象的属性
console.log(teacher.name); // Jackson
console.log(student.name); // Bill

// 4.调用对象的方法
teacher.sayHi(); // hi
student.sayHi(); // hi

Analysis: Two object instances teacherand student, and the two object instances have the same properties and methods

2. Add properties and methods to objects

function Person(name, age, sex) {
    
    
  this.name = name;
  this.age = age;
  this.sex = sex;
  this.sayHi = function () {
    
    
    console.log("hi");
  };
}

var student = new Person("Bill", 18, "male");

// 为对象添加属性
student.nationality = "English";

// 为对象添加方法
student.sayHello = function () {
    
    
  console.log("hello");
};

console.log(student);

2.4 Object Prototype

Constructor and prototype object: After declaring a constructor, the constructor will have a prototypeproperty, which refers to the prototype object of the constructor.

The role of the prototype object: the method of the constructor will waste memory, and the method of the constructor through the prototype allocation is shared by all objects, that is, the same block of memory can be reused to avoid wasting memory.

Several properties related to the prototype:

  • prototype
  • __proto__
  • constructor

2.4.1 prototype property

prototype: Each constructor has a prototype property, pointing to another object. This prototype is an object (prototype object), and all properties and methods of this object will be owned by the constructor.

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

Summary:
1. The prototype is an object
2. The role of the prototype object is to realize the sharing of methods

1. newEach will open up a new memory space. When the method is defined inside the constructor, it will cause memory waste.

function Person(name, age) {
    
    
  this.name = name;
  this.age = age;
  this.sayHi = function () {
    
    
    console.log("hi");
  };
}

var teacher = new Person("Jackson", 40);
var student = new Person("Bill", 18);
console.log(teacher.sayHi === student.sayHi); // false
      

Analysis: When creating two object instances of teacher and student, the two instances open up different memory spaces (including name, age attribute and sayHi method), so the addresses pointed to by these two instance methods are different. After comparison The result obtained isfalse

2. Put the method inside the constructor on the prototype object of the constructor, only open up memory space for the method once, and the method can be reused, thus avoiding memory waste.

function Person(name, age) {
    
    
  this.name = name;
  this.age = age;
}

// 将构造函数的方法定义到原型对象上
Person.prototype.sayHi = function () {
    
    
  console.log("hi");
};

var teacher = new Person("Jackson", 40);
var student = new Person("Bill", 18);
console.log(teacher.sayHi === student.sayHi); // true

Analysis: Since the sayHi method is defined on the prototype object, every time an object instance is new, the method of the instance points to the sayHi method of the prototype object (the same memory space), so the addresses pointed to by these two instance methods are the same , the result obtained after comparison istrue

2.4.2 The __proto__ attribute

__proto__: Every object has an __proto__attribute, which points to the prototypeprototype object of the constructor. The reason why the object can use prototypethe object's attributes and methods is because of __proto__the existence of the object.

1. Point to the prototype object __proto__of the constructorprototype

function Person(name, age) {
    
    
  this.name = name;
  this.age = age;
}

Person.prototype.sayHi = function () {
    
    
  console.log("hi");
};

var student = new Person("Bill", 18);
console.log(student.__proto__);

The running results are as follows: You can see __proto__that there is sayHia method, and this method is defined on prototypethe object, that is to say, __proto__it points to prototypethe prototype object

Note: here [[Prototype]]can be roughly understood as__proto__

insert image description here

2. __proto__Pointed to prototype, so the two are actually equivalent

function Person(name, age) {
    
    
  this.name = name;
  this.age = age;
}

Person.prototype.sayHi = function () {
    
    
  console.log("hi");
};

var student = new Person("Bill", 18);
console.log(student.__proto__ === Person.prototype); // true
      

2.4.3 constructor attribute

constructor: __proto__and prototypeinside both have an constructorattribute constructorcalled constructor because it points back to the constructor itself.

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

1. constructorPoint to the constructor of the prototype object reference

function Person(name, age) {
    
    
  this.name = name;
  this.age = age;
}

Person.prototype.sayHi = function () {
    
    
  console.log("hi");
};

var student = new Person("Bill", 18);
console.log(Person.prototype.constructor);
console.log(student.__proto__.constructor);
      

The result of the operation is as follows:

insert image description here

2. You can use constructorthe attribute to point the prototype object back to the original constructor

function Person(name, age) {
    
    
  this.name = name;
  this.age = age;
}

Person.prototype = {
    
    
  // 使用constructor属性,将原型对象指回Person构造函数
  constructor: Person,
  sayHi: function () {
    
    
    console.log("Hi");
  },
  sayHello: function () {
    
    
    console.log("Hello");
  }
};

var student= new Person("Bill", 18);
student.sayHi();
student.sayHello();

Note: If we assign an object to the prototype object, the prototype object will lose the constructor attribute. At this time, we need to manually add the constructor attribute back and point back to the original constructor.

2.4.4 Prototype chain

Prototype chain: JavaScript objects have a chain pointing to a prototype object. When trying to access a property of an object, it searches not only on the object, but also on the object's prototype, and on the prototype of the object's prototype, and so on until it finds a property with a matching name or reaches the prototype the end of the chain.

  • First understand the relationship between constructors, instances and prototype objects, and then understand the prototype chain
  • The prototype chain is __proto__to look up the prototype object layer by layer prototypeuntil the top prototype object is foundObject.prototype
  • In each layer of the prototype chain, there is a relationship between the constructor, the instance and the prototype object

Through the following example, analyze the relationship among constructors, instances and prototype objects, as well as the prototype chain:

function Person(name, age) {
    
    
  this.name = name;
  this.age = age;
}

Person.prototype.sayHi = function () {
    
    
  console.log("hi");
};

var student = new Person("Bill", 18);
console.log(student.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null

Analysis:
1. student.__proto__points to Person.prototype
2. Person.prototype.__proto__points to Object.prototype
3. Object.prototypeis the top-level prototype object, so Object.prototype.__proto__points tonull

1. The relationship between constructors, instances and prototype objects

insert image description here

2. Prototype chain

insert image description here

2.5 Object object

2.5.1 Management objects

Methods of managing objects:

method describe
create() Create new objects based on existing objects
defineProperty() Add or change individual properties of an object
defineProperties() Add or change multiple properties of an object property
getOwnPropertyDescriptor() Get the descriptor for a single property of an object
getOwnPropertyDescriptors() Get descriptors for all properties of an object
getOwnPropertyNames() Return all properties as an array
getPrototypeOf() Get the prototype of the object
keys() Returns enumerable properties as an array
  1. createmethod to create a new object based on an existing object
var person = {
    
    
  name: "Bill",
  age: 18,
  sayHi: function () {
    
    
    console.log("Hi");
  }
};

// 以person对象为原型,创建一个新对象student
var student = Object.create(person);
student.age = 28;

console.log(student.name); // Bill
console.log(student.age); // 28
student.sayHi(); // Hi

Analysis: student.nameand student.sayHi()can be used because the person object is the prototype of the student object, the student object inherits the properties and methods of the person object, and student.age28 is because the student object covers the age attribute of the person object

2. definePropertyMethods for adding or changing object properties

Object.defineProperty(obj, prop, descriptor)

  • obj: Object to define properties
  • prop: The name of the property to define or modify
  • descriptor: property descriptor to define or modify

Attribute descriptors are divided into data descriptors and access descriptors:

  • A data descriptor is an attribute with a value, which may or may not be writable
  • An access descriptor is an attribute described by a getter function and a setter function
  • Data descriptors and access descriptors cannot be mixed
data descriptor describe
value attribute value
writable Whether the attribute value can be changed
enumerable Whether the attribute is enumerable
configurable Whether the attribute can be deleted
access descriptor describe
get() When the property is accessed, this function is called
set() This function is called when the property value is modified

Data descriptor:

var person = {
    
    
  name: "Bill",
  age: 18,
  addr: "Shanghai"
};

// 设置name属性为只读
Object.defineProperty(person, "name", {
    
     writable: false });
person.name = "Jackson";
console.log(person.name); // Bill

// 设置age属性为不可枚举
Object.defineProperty(person, "age", {
    
     enumerable: false });
for (var i in person) {
    
    
  console.log(i); // name addr
}

// 设置addr属性为不可删除
Object.defineProperty(person, "addr", {
    
     configurable: false });
delete person.addr;
console.log(person.addr); // Shanghai

Access descriptor:

var person = {
    
    
  name: "Bill",
  age: 18,
  addr: "Shanghai"
};

// 添加getter和setter
Object.defineProperty(person, "uage", {
    
    
  get() {
    
    
    return this.age;
  },
  set(value) {
    
    
    this.age = value;
  }
});

// 访问getter
console.log(person.uage); // 18

// 访问setter
person.uage = 28;
console.log(person.uage); // 28
console.log(person.age); // 28

3. definePropertiesMethod, used to add or change object properties, can operate multiple properties of an object at the same time
Object.defineProperties(obj, props):

  • object to define properties
  • The object whose enumerable properties or modified property descriptors are to be defined

Data descriptor:

var person = {
    
    
  name: "Bill",
  age: 18,
  addr: "Shanghai"
};

// 同时定义person对象的多个属性
Object.defineProperties(person, {
    
    
  name: {
    
    
    writable: false
  },
  age: {
    
    
    enumerable: false
  },
  addr: {
    
    
    configurable: false
  }
});

// name属性只读
person.name = "Jackson";
console.log(person.name); // Bill

// age属性不可枚举
for (var i in person) {
    
    
  console.log(i); // name addr
}

// addr属性不可删除
delete person.addr;
console.log(person.addr); // Shanghai

Access descriptor:

var person = {
    
    
  name: "Bill",
  age: 18,
  addr: "Shanghai"
};

// 同时定义person对象的多个属性
Object.defineProperties(person, {
    
    
  uname: {
    
    
    get() {
    
    
      return this.name;
    },
    set(value) {
    
    
      this.name = value;
    }
  },
  uage: {
    
    
    get() {
    
    
      return this.age;
    },
    set(value) {
    
    
      this.age = value;
    }
  }
});

// 访问uname属性
console.log(person.uname); // Bill
person.uname = "Jackson";
console.log(person.uname); // Jackson

// 访问uage属性
console.log(person.uage); // 18
person.uage = 28;
console.log(person.uage); // 28

4. getOwnPropertyDescriptorand getOwnPropertyDescriptorsmethod , used to obtain the descriptor of the object property

Get the descriptor for a single property of an object:getOwnPropertyDescriptor(obj, prop)

var person = {
    
    
  name: "Bill",
  age: 18,
  addr: "Shanghai"
};

var descriptor = Object.getOwnPropertyDescriptor(person, "name");
console.log(descriptor); // {value: 'Bill', writable: true, enumerable: true, configurable: true}

Get descriptors for all properties of an object:getOwnPropertyDescriptors(obj)

var person = {
    
    
  name: "Bill",
  age: 18,
  addr: "Shanghai"
};

var descriptor = Object.getOwnPropertyDescriptors(person);
console.log(descriptor.name); // {value: 'Bill', writable: true, enumerable: true, configurable: true}
console.log(descriptor.age); // {value: 18, writable: true, enumerable: true, configurable: true}
console.log(descriptor.addr); // {value: 'Shanghai', writable: true, enumerable: true, configurable: true}

5. getOwnPropertyNamesMethod to return the attribute names of all attributes in an array

var person = {
    
    
  name: "Bill",
  age: 18,
  addr: "Shanghai"
};

var properties = Object.getOwnPropertyNames(person);
console.log(properties); // ['name', 'age', 'addr']

6. getPrototypeOfMethod, used to access the prototype of the object

var person = {
    
    
  name: "Bill",
  age: 18,
  sayHi: function () {
    
    
    console.log("Hi");
  }
};

var student = Object.create(person); // 以person对象为原型,创建一个新对象student
var prototype = Object.getPrototypeOf(student); // 获取student的原型
console.log(prototype); // {name: 'Bill', age: 18, sayHi: ƒ}

// student的原型就是person对象,而person的原型是Object的原型
console.log(prototype == person); // true
console.log(Object.getPrototypeOf(person) == Object.prototype); // true

7. keysMethod that returns enumerable properties as an array

var person = {
    
    
  name: "Bill",
  age: 18,
  addr: "Shanghai"
};

Object.defineProperty(person, "age", {
    
     enumerable: false }); // 设置age属性为不可枚举
console.log(Object.keys(person)); // ['name', 'addr']

2.5.2 Protected objects

Methods to protect objects:

method describe
preventExtensions() Prevent adding properties to objects
isExtensible() Returns true if the object is extensible
seal() Prevent adding and removing attributes
isSealed() Returns true if the object is sealed
freeze() prevent any changes to the object
isFrozen() Returns true if the object is frozen

Summary: The above preventExtensions, seal, freezeand three methods limit the object progressively.
1. preventExtensions: Objects cannot add attributes, but can modify and delete attributes
2. seal: Objects cannot add and delete attributes, but can modify attributes
3. freeze: Objects cannot add, delete, and modify attributes

1. preventExtensionsThe method makes an object non-extensible and prevents adding properties to the object

var person = {
    
    
  name: "Bill",
  age: 18
};

Object.preventExtensions(person); // 防止对象添加属性
Object.defineProperty(person, "addr", {
    
     value: "Shanghai" }); // Uncaught TypeError

2. isExtensibleMethod that returns true if the object is extensible

var person = {
    
    
  name: "Bill",
  age: 18
};

Object.preventExtensions(person);
console.log(Object.isExtensible(person)); // false

3. sealMethod, encloses an object, prevents adding new properties, and does not allow deletion of existing properties

var person = {
    
    
  name: "Bill",
  age: 18
};

Object.seal(person); // 防止对象添加和删除属性
person.addr = "Shanghai"; 
delete person.age; 
console.log(person); // {name: 'Bill', age: 18}

4. isSealedmethod that returns true if the object is sealed

var person = {
    
    
  name: "Bill",
  age: 18
};

Object.seal(person);
console.log(Object.isSealed(person)); // true

5. freezeMethod, freeze an object, that is, the object cannot add, delete and modify attributes

var person = {
    
    
  name: "Bill",
  age: 18
};

Object.freeze(person); // 防止对象添加、删除和修改属性
person.addr = "Shanghai";
delete person.age;
person.name = "Jackson";
console.log(person); // {name: 'Bill', age: 18}

6. isFrozenMethod that returns true if the object is frozen

var person = {
    
    
  name: "Bill",
  age: 18
};

Object.freeze(person);
console.log(Object.isFrozen(person)); // true

3. Advanced functions

3.1 Definition and use of functions

1. Declaration and call of ordinary functions

// 函数声明
function getSum(x, y) {
    
    
  return x + y;
}

getSum(1, 2); // 函数调用

2. Function expression

1. Functions can be defined using expressions
2. Functions defined using expressions are anonymous functions

// 函数声明
var sum = function (x, y) {
    
    
  return x + y;
};

sum(1, 2); // 函数调用

3. Function improvement

1. Hoisting: The default behavior of moving declarations to the top of the current scope
2. Functions defined using function expressions will not be hoisted

// 函数调用
getSum(1, 2);

// 函数声明
function getSum(x, y) {
    
    
  return x + y;
}

Analysis: Because the function declaration is promoted to the top of the scope, the function call is actually after the function declaration, so no error will be reported.

4. Self-invoking functions

  • Function expressions can act as "self-invocations"
  • expression followed by ()the function expression is automatically executed
  • cannot self-call a function declaration
// 函数自调用
(function () {
    
    
  console.log("Hello World");
})();
var sum = (function (x, y) {
    
    
  return x + y;
})(1, 2);

console.log(sum); // 3

5. Functions are objects

Functions are functionobjects, so functions have properties and methods

function getSum(x, y) {
    
    
  return x + y;
}

console.log(typeof getSum); // function

3.2 Function object

Function object: Each js function is a Function object.

Methods of the Function object:

  • call(): The function will be called and the this point inside the function will be changed
  • apply(): The function will be called and the this point inside the function will be changed
  • bind(): The function will not be called, and the this point inside the function can be changed

1. The three methods of call, apply and bind can change the this point inside the function.
2. The call and apply methods will call the function, but the bind method will not call the function.
3. The parameters passed by call and apply are different, and the method of passing parameters by call Yes arg1,arg2, and apply must be in the form of an array[args]

3.2.1 call

grammar:function.call(thisArg, arg1, arg2, ...)

  • function:Function name
  • thisArg: the object pointed to by this, optional
  • arg1, arg2, ...: the parameter list of the function

1. Use the call method to call the function, you can change the this point inside the function

var person = {
    
    
  name: "Bill"
};

function fn() {
    
    
  console.log(this);
}

fn(); // Window {window: Window, ...}
fn.call(person); // {name: 'Bill'}

Analysis:
1. Call the function directly, this points to the window object
2. Use the call method to point this to the person object

2. The call method can pass in parameters and get the return value of the function

var person = {
    
    
  name: "Bill"
};

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

var sum = fn.call(person, 1, 2); // {name: 'Bill'}
console.log(sum); // 3
      

3. The main application of the call method is to implement inheritance

Example: The child constructor inherits the properties of the parent constructor

// 父构造函数
function Father(name, age) {
    
    
  // this指向父构造函数的对象实例
  this.name = name;
  this.age = age;
}

// 子构造函数
function Son(name, age) {
    
    
  // this指向子构造函数的对象实例
  Father.call(this, name, age); // 修改父构造函数的this为子构造函数的this
}

var son = new Son("Bill", 18);
console.log(son); // Son {name: 'Bill', age: 18}

3.2.2 apply

grammar:function.apply(thisArg, argsArray)

  • function:Function name
  • thisArg: the object pointed to by this, optional
  • argsArray: function parameter list in array form

1. Use the apply method to call the function, you can change the this point inside the function

var person = {
    
    
  name: "Bill"
};

function fn() {
    
    
  console.log(this);
}

fn.apply(person); // {name: 'Bill'}
      

2. The apply method can pass in parameters (must be in the form of an array) and get the return value of the function

var person = {
    
    
  name: "Bill"
};

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

var sum = fn.apply(person, [1, 2]); // {name: 'Bill'}
console.log(sum); // 3
      

3. The main application of the apply method is to manipulate arrays

Example: Use apply to find the maximum value with the help of the Math object

var arr = [1, 3, 2];

// Math.max(1, 3, 2)
max = Math.max.apply(null, arr); // 通过apply将arr数组传递给了max方法
console.log(max); // 3

Analysis:
1.null means not to change
the content of this pointing to 2.arr array as a parameter list, which is passed to the max method

3.2.3 bind

grammar:function.bind(thisArg, arg1, arg2, ...)

  • function:Function name
  • thisArg: the object pointed to by this, optional
  • arg1, arg2, ...: the parameter list of the function

1. Using the bind method will change the this pointer inside the function, but will not call the function

Note: The return value of the bind method is a new function generated after the original function changes this

var person = {
    
    
  name: "Bill"
};

function fn() {
    
    
  console.log(this);
}

var f = fn.bind(person);
f(); // {name: 'Bill'}

2. The bind method can pass in parameters and get the return value of the function (new function)

var person = {
    
    
  name: "Bill"
};

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

var f = fn.bind(person, 1, 2); // f是返回的新函数
var sum = f(); // sum是f函数的返回值
console.log(sum); // 3

3. If some functions do not need to be called immediately, but want to change the this pointer inside the function, use the bind method

Example: There is a button on the page, when the button is clicked, the button is disabled, and the button is turned on after 3 seconds

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <button>点击一下</button>
    <script>
      var btn = document.querySelector("button");
      btn.onclick = function () {
      
      
        this.disabled = true; // 此处this指向的是btn
        setTimeout(
          function () {
      
      
            this.disabled = false; // 该回调函数绑定外部的this之后,此处的this也指向btn,否则指向window
          }.bind(this),
          3000
        );
      };
    </script>
  </body>
</html>

3.3 Higher-order functions

Higher-order functions: Functions that operate on other functions are called higher-order functions, which receive functions as parameters or return functions as values.

1. Functions are passed as parameters

function fn(a, b, callback) {
    
    
  console.log(a + b);
  callback && callback(); // 调用回调函数
}

// 匿名函数作为参数传递
fn(1, 2, function () {
    
    
  console.log("Hello World");
});

2. Function as return value

function fn(a, b) {
    
    
  console.log(a + b);
  // 将匿名函数作为返回值
  return function () {
    
    
    console.log("Hello World");
  };
}

f = fn(1, 2);
f();

3.4 Closures

Closure: Refers to a function that has access to variables in the scope of another function.

  • A scope can access local variables inside another function
  • A closure is a function
  • The function where the variable is defined is a closure function

1. Generation of closure

// fn为闭包
function fn() {
    
    
  var num = 10;
  function fun() {
    
    
    console.log(num); // 10
  }
  fun();
}

fn();

Analysis:
1. In funthe scope of the function, the local variable of another function fn is accessed num, so a closure is generated
2. numIt is defined in the fn function, so fnit is a closure

Make a breakpoint at the place where the closure is generated, and you can see that there is one more on the right Closure (fn), which means that fn is a closure.

insert image description here

2. The main function of closures: extending the scope of variables

// fn为闭包
function fn() {
    
    
  var num = 10;
  return function () {
    
    
    console.log(num);
  };
}

var f = fn();
f(); // 10

Analysis:
1. In the absence of a closure, the local variable numwill be fndestroyed as the function call ends.
2. With the closure, after the function fncall ends, numit is not destroyed, but waits for the function fcall . Use After the variable is numdestroyed, it extends numthe scope of the local variable

4. Abnormal

Exception: When the code is executed, various errors may occur, and an exception will be thrown when an error occurs. When an exception is thrown, the program will be interrupted and the subsequent code will not be executed. Sometimes we want the subsequent code to continue to execute. At this time, we need to use the exception handling statement.

Exception statement:

  • trystatement is able to detect errors in code blocks
  • catchstatement allows you to handle errors
  • throwstatement allows you to create custom errors
  • finallyIndicates code that will be executed regardless of the results of try and catch

1. In the case of not using exception statements, when an error occurs in the code, the program will be interrupted, and the subsequent code will not be executed

var x = y + 1; // ReferenceError
console.log("Hello World");

The running results are as follows: It can be found that after the error occurs, the subsequent output statement is not executed

insert image description here

2. try...catchStatement

Syntax: execute trythe code block first, if there is an error, then execute catchthe code block, otherwise execute the subsequent code directly

try {
    
    
     // 用于检测错误的代码块
}
 catch(err) {
    
    
     // 错误出现后执行的代码块
} 
try {
    
    
  var x = y + 1; // ReferenceError
} catch (error) {
    
    
  console.log(error); // 打印错误信息
}

console.log("Hello World");

Here erroris a built-in errorobject that provides error information when an error occurs. The error object also has two properties:
1. name: set or return the error name
2. message: set or return the error message

catchThe running results are as follows: It can be found that after an error occurs, the statement is executed , and then the subsequent code is executed, and the program is not interrupted

insert image description here

3. try...catch...finallyStatement

Syntax: try...catchdiffers from the statement in that finallythe code block in the

try {
    
    
     // 用于检测错误的代码块
}
 catch(err) {
    
    
     // 错误出现后执行的代码块
} 
finally {
    
    
     // 无论结果如何都执行的代码块
}
try {
    
    
  var x = y + 1;
} catch (error) {
    
    
  console.log(error);
} finally {
    
    
  console.log("Hi");
}

console.log("Hello World");

4. throwStatements, used to create custom errors, when used try...catchtogether , you can control the program flow and generate custom error messages

// 本例规定数字在5-10的范围,为有效数字
try {
    
    
  var x = prompt("请输入一个数字");
  if (x < 5) throw "太小";
  if (x > 10) throw "太大";
  alert("输入的数字有效");
} catch (error) {
    
    
  alert("输入的数字" + error);
}

5. The six error types of js

error type describe
EvalError Errors that have occurred in the eval() function
RangeError A number out of range error has occurred
ReferenceError An illegal reference has occurred
SyntaxError A syntax error has occurred
TypeError A type error has occurred
URIError Errors that have occurred in encodeURI()

5. JSON

JSON: JavaScript Object Notation, a syntax for storing and exchanging data.

  • JSON is a grammar, a format for writing text
  • The concept of json in js can be divided into two understandings, one is the json object and the other is the json string
  • Convert between json object and json string

json object: object in json format
json string: string in json format

5.1 JSON syntax

JSON syntax:

  • Data as key-value pairs
  • data separated by commas
  • curly braces contain object
  • Square brackets contain arrays

Note:
1. The suffix of the JSON file is .json
2. The MIME type of the JSON text isapplication/json

1. JSON data is stored in the form of key-value pairs

  • Keys must be strings, surrounded by double quotes
  • Values ​​can only be strings, numbers, json objects, arrays, booleans and null, where strings must be surrounded by double quotes

Note: JSON does not allow comments

{
    
     "name": "Bill", "age": 18 }

2. Objects and arrays in JSON

Objects and arrays in JSON can be nested within each other

{
    
    
  "name": "Bill",
  "age": 18,
  "cars": {
    
    
    "car1": "Porsche",
    "car2": "BMW",
    "car3": "Volvo"
  },
  "models": ["Cayenne", "X5", "XC60"]
}
{
    
    
  "name": "Bill",
  "age": 18,
  "cars": [
    {
    
     "name": "Porsche", "models": ["Cayenne", "Panamera"] },
    {
    
     "name": "BMW", "models": ["X5", "i3", "530Li"] },
    {
    
     "name": "Volvo", "models": ["XC60", "S60"] }
  ]
}

3. JSON object in JS

The difference between the writing of JSON objects and the writing of JSON text is that the keys of JSON objects are not surrounded by double quotes. This is because JSON objects are JS objects, and the keys of JS objects are not surrounded by double quotes.

// JSON对象
var json = {
    
    
  name: "Bill",
  age: 18,
  cars: [
    {
    
     name: "Porsche", models: ["Cayenne", "Panamera"] },
    {
    
     name: "BMW", models: ["X5", "i3", "530Li"] },
    {
    
     name: "Volvo", models: ["XC60", "S60"] }
  ]
};

// 使用objectName.property的语法访问对象属性
console.log(json.name); // Bill
console.log(json.age); // 18
console.log(json.cars[0]); // {name: 'Porsche', models: Array(2)}
console.log(json.cars[0].name); // Porsche
console.log(json.cars[0].models[0]); // Cayenne

// 使用objectName["property"]的语法访问对象属性
console.log(json["name"]); // Bill
console.log(json["age"]); // 18
console.log(json["cars"][1]); // {name: 'BMW', models: Array(3)}
console.log(json["cars"][1]["name"]); // BMW
console.log(json["cars"][1]["models"][0]); // X5
      

5.2 JSON parsing

JSON parsing: use JSON.parse()method to convert json string to json object

var jsonstr = '{"name":"Bill","age":18,"cars":{"car1":"Porsche","car2":"BMW","car3":"Volvo"}}';
var json = JSON.parse(jsonstr);
console.log(json); // {name: 'Bill', age: 18, cars: {…}}

You can also use template strings in ES6 to retain the original way of writing JSON text:

// JSON字符串
var jsonstr = `{
  "name": "Bill",
  "age": 18,
  "cars": {
    "car1": "Porsche",
    "car2": "BMW",
    "car3": "Volvo"
  }
}`;

var json = JSON.parse(jsonstr);
console.log(json); // {name: 'Bill', age: 18, cars: {…}}
      

5.3 JSON stringification

JSON stringification: use JSON.stringify()method to convert json object to json string

// JSON对象
var json = {
    
    
  name: "Bill",
  age: 18,
  cars: {
    
    
    car1: "Porsche",
    car2: "BMW",
    car3: "Volvo"
  }
};

// 将JSON对象转换为字符串
var jsonstr1 = JSON.stringify(json);
console.log(jsonstr1);

// 将JSON对象转换为字符串,并指定缩进用于美化输出
var jsonstr2 = JSON.stringify(json, null, "\t");
console.log(jsonstr2);

The result of the operation is as follows:

insert image description here

6. copy

Copy is divided into shallow copy and deep copy:

  • Shallow copy: only copy the data of the first layer, when encountering a deeper object, only copy the address of the object
  • Deep copy: copy the data of each layer

6.1 Shallow copy

1. Object.assign()The method of use can realize shallow copy

var person = {
    
    
  name: "Bill",
  age: 18,
  info: {
    
    
    telephone: "13579",
    email: "[email protected]"
  }
};

var student = {
    
    };
Object.assign(student, person); // 将person对象浅拷贝到student对象
person.age = 28;
person.info.telephone = "246810";
console.log(person);
console.log(student);

The result of the operation is as follows: person.agethe modification found did not affect the student object, but person.info.telephonethe modification did affect the student object.

Analysis: This is because person.agethe attribute value of is a simple data type, so the attribute value copied to the student object ageis a specific value, and person.infothe attribute value of is an object, so the attribute value copied to the student object infois an address. This address points to person.info. That is to say student.info === person.info, person.agethe modification does not affect the student, but person.info.telephonethe modification will affect the student

insert image description here

2. If you directly assign an object to another object, it is equivalent to giving the object an alias, which is neither a shallow copy nor a deep copy.

var person = {
    
    
  name: "Bill",
  age: 18,
  info: {
    
    
    telephone: "13579",
    email: "[email protected]"
  }
};

var student = {
    
    };
student = person; // 将person对象的地址赋值给student对象
person.age = 28;
person.info.telephone = "246810";
console.log(person);
console.log(student);

The result of the operation is as follows: when any attribute of the person object changes, the attribute of the student object also changes, because the student points to the address of the person object, that isstudent === person

insert image description here

6.2 Deep Copy

1. structuredClone()The method of use can realize deep copy

var person = {
    
    
  name: "Bill",
  age: 18,
  info: {
    
    
    telephone: "13579",
    email: "[email protected]"
  }
};

var student = structuredClone(person); // 将person对象深拷贝到student对象
person.age = 28;
person.info.telephone = "246810";
console.log(person);
console.log(student);

The results of the operation are as follows: the discovery person.ageand person.info.telephonemodification did not affect the student object.

Analysis: This is because the deep copy will copy the data of each layer. When encountering a deeper object, it will continue to traverse the attributes and attribute values ​​​​of the object and copy them instead of just copying the address of the object.

insert image description here

2. Use to for...inencapsulate a deep copy function

// 深拷贝函数
function deepCopy(newObj, oldObj) {
    
    
  for (var i in oldObj) {
    
    
    var item = oldObj[i]; // 原对象的属性值
    // 判断属性值是否为数组对象
    if (item instanceof Array) {
    
    
      newObj[i] = []; // 将新对象的第i项属性设置为数组对象
      deepCopy(newObj[i], item); // 递归调用
    }
    // 判断属性值是否为普通对象
    if (item instanceof Object) {
    
    
      newObj[i] = {
    
    }; // 将新对象的第i项属性设置为普通对象
      deepCopy(newObj[i], item); // 递归调用
    }
    // 判断属性值是否为简单数据类型
    if (!(item instanceof Object)) {
    
    
      newObj[i] = item;
    }
  }
}

var person = {
    
    
  name: "Bill",
  age: 18,
  info: {
    
    
    telephone: "13579",
    email: "[email protected]"
  },
  addr: ["Beijing", "Shanghai"]
};

var student = {
    
    };
deepCopy(student, person); // 将person对象深拷贝到student对象
person.age = 28;
person.info.telephone = "246810";
person.addr[0] = "Guangzhou";
console.log(person);
console.log(student);

The result of the operation is as follows:

insert image description here

3. Use to JSONencapsulate a deep copy function

// 深拷贝函数
function deepCopy(oldObj) {
    
    
  oldObjstr = JSON.stringify(oldObj); // 将原对象转换为字符串
  newObj = JSON.parse(oldObjstr); // 再将字符串转换为对象
  return newObj;
}

var person = {
    
    
  name: "Bill",
  age: 18,
  info: {
    
    
    telephone: "13579",
    email: "[email protected]"
  },
  addr: ["Beijing", "Shanghai"]
};

var student = deepCopy(person); // 将person对象深拷贝到student对象
person.age = 28;
person.info.telephone = "246810";
person.addr[0] = "Guangzhou";
console.log(person);
console.log(student);

operation result:

insert image description here

7. ES6

Refer to the follow-up ES6 tutorial

Guess you like

Origin blog.csdn.net/aidijava/article/details/129113467