Detailed introduction to JavaScript functions

1. Function introduction

A function encapsulates the code that implements a specific function. When we need to implement a specific function, we can directly call the function to implement it. There is no need to write a bunch of code every time to achieve code reuse.

Functions:
1. Encapsulate functions and improve code reuse
2. Templates (constructors) used to build objects

Functions are actually objects. Each function is an instance of the Function type and has properties and methods like other reference types. Since functions are objects, the function name is actually a pointer to the function object and will not be associated with a certain function. function binding.

2. Function declaration

grammar:

function 函数名(形参列表){
    
    
    //函数体
}

We can also write it as a function expression:

var 函数名 = function(形参列表){
    
    
    //函数体
}

example:

// 函数声明
function sum(a,b){
    
    
  return a + b
}
//函数声明之后,需要调用才能执行
// 函数调用:函数名(实参)
console.log(sum(1,2))  //3

Written as a function expression:

// 函数声明
var sum = function(a,b){
    
    
  return a + b
}
// 函数调用:函数名(实参)
console.log(sum(1,2)) //3

Function declaration promotion
Function declaration is similar to variables declared by var, and there is also declaration promotion.

sum(1,2) //在此处调用函数不会报错,因为存在函数声明提升
function sum(a,b){
    
    
  return a + b
}

Note: When declaring a function using a function expression, you cannot write the function call before the function declaration, because there is no promotion in variable assignment.

3. Function internal attributes

Function internal properties can only be accessed inside the function

arguments

arguments is an array-like object containing all parameters passed into the function. The main purpose of arguments is to save function parameters.

function foo(){
    
    
  console.log(arguments) // [Arguments] { '0': 1, '1': 2, '2': 3, '3': 4 }
  console.log(arguments[1]) // 2
}
// 当传递的实参个数超过形参的个数的时候不会报错,所有的实参都会保存在arguments里
foo(1,2,3,4) 

Note: arguments are stored in arguments, not formal parameters.

function foo(a,b = 2,c = 3){
    
    
  console.log(arguments) // [Arguments] { '0': 1 }
  console.log(b) //2
  console.log(c) //3
}
//只传了一个实参,那么arguments中就只有一个值
foo(1) 
callee attribute

The arguments object has a property called callee, which is a pointer to the function that owns the arguments object.

arguments.calleeIt's actually the function name.

// 递归求n的阶乘
function factorial(n) {
    
    
  if (n == 1) {
    
    
    return 1
  }
  return arguments.callee(n - 1) * n //arguments.callee 相当于函数名factorial
}
console.log(factorial(10));
length attribute

The length property of the arguments object returns the number of actual arguments.

function foo(){
    
    
  console.log(arguments.length) //5
}
foo(1,2,3,4,5) 

4. Regarding this pointer

this: Execution environment context object, who it points to depends on when it is called and by whom it is called.

  • In a method, this represents the object to which the method belongs.
  • If used alone, this represents the global object.
  • In a function, this represents the global object.
  • In an event, this represents the element receiving the event.
  • In explicit function binding, we can decide the point of this ourselves.

1. this in the method

In object methods, this points to the object that calls the method in which it is located. That is to say, whoever calls this method, this points to.

var person = {
    
    
  name:'叶子yes',
  sayName: function () {
    
    
    console.log(this.name); 
  }
}
//person对象调用了该方法,因此this指向person
person.sayName() // '叶子yes'
var name = 'hello'
    var person = {
    
    
      name: '叶子yes',
      sayName: function () {
    
    
        console.log(this.name);
      }
    }
var a = person.sayName
//这里是全局对象调用了sayName方法,因此this指向全局对象window,结果为'hello'
//注意:在node环境下执行时,结果为undefined
a()

2. Use this alone

If this is used alone, it points to the global object.

  • In the browser, window is the global object
  • In node, it points to a {}

In browser environment:
Insert image description here
In node environment:

console.log(this) // {}

3. Use this in functions

In a function, the owner of the function is bound to this by default.

  • In the browser, it points to window
  • In node, it points to the global object

In browser environment:
Insert image description here
In node environment:

function foo(){
    
    
  return this
}
console.log(foo())

Output result:
Insert image description here

4. this in the event

In an HTML event handler, this points to the HTML element that received the event:

<button onclick="this.style.display='none'"> 点我后我就消失了 </button> //this指向button

5. Display function binding

In JavaScript, functions are also objects, and objects have methods. apply and call are methods of function objects. These two methods are extremely powerful. They allow switching the context in which the function is executed, that is, the object bound to this. (These two methods will be discussed later)

In the following example, when we call the person1.sayName method using person2 as a parameter, this will point to person2, even though it is person1's method:

var person1 = {
    
    
  name: 'zhangsan',
  sayName: function () {
    
    
    console.log(this.name);
  }
}
var person2 = {
    
    
  name:'叶子yes'
}
//this指向person2
person1.sayName.call(person2) //叶子yes

5. Immediately execute function IIFE

IIFE: Immediately Invoked Function Expression, which means an immediately invoked function expression, that is, the function is called immediately when the function is declared.

Function
1. The setting function is only executed once after the page is loaded.
2. Wrap the variables in the setting function in the local scope so that they will not be leaked into global variables.

Writing method:

(function(形参){
    
    
	函数体内容
})(实参);

or:

(function(形参){
    
    
	函数体内容
}(实参));

example:

(function (a) {
    
    
  console.log(123 + a); //124
})(1)
(function (a) {
    
    
  console.log(123 + a); //124
}(1))

If we write a normal function and an immediate execution function, we must pay attention to separate them with semicolons, otherwise the js compiler will parse them into one statement and report an error:

// 普通函数
function foo() {
    
    
  console.log(123);
}
foo();
// 如果后面跟的是立即执行函数,前面的结束语句必须要加分号
// 立即执行函数
(function (a) {
    
    
  console.log(123 + a);
})(123)

Usage:
1. Just like any other function, an immediately executed function can also return a value and can be assigned to other variables:

var sum = (function (a,b) {
    
    
  return a + b;
}(1,2))
console.log(sum); //3

2. You can add it in front of the immediate execution function! , + etc. to perform type conversion on the return value:

//1、返回布尔值
!function(形参){
    
    
	return true
}(实参)

//2、返回数字类型的值
+function(形参){
    
    
	return 123
}(实参)

//3、对于数字返回的是相反数,非数字返回NaN
-function(形参){
    
    
	return 123
}(实参)

//4、对于数字返回的是相反数减1,非数字返回-1
~function(形参){
    
    
	return 123
}(实参)

//5、返回undefined
void function(形参){
    
    
	函数体内容
}(实参)

3. Interview questions

//下面代码输出结果是什么
for (var i = 0; i < 6; i++) {
    
    
  function output() {
    
    
    console.log(i); 
  }
}
output() //输出结果是6,因为函数执行时,for循环已经结束,函数体中最终存的i值是6

What should we do if we want to output 0,1,2,3,4,5? At this time we can use the immediate execution function:

for (var i = 0; i < 6; i++) {
    
    
  (function (j) {
    
    
    console.log(j); //0,1,2,3,4,5
  })(i)
}
/*
因为 JS 中调用函数传递参数都是值传递 ,所以当立即执行函数执行时,
首先会把参数 i 的值复制一份,然后再创建函数作用域来执行函数,
循环6次就会创建6个作用域,所以每个输出访问的都是不同作用域的 i 的值 。
*/

6. Scope

In ES5: (There is no block-level scope in ES5)

Function scope : Variables declared in a JavaScript function will become local variables of the function.
​ Variables declared inside a function cannot be accessed outside the function.

Global scope : Variables declared outside the function will become global variables.
​ Variables declared outside the function can be accessed inside the function.
​ When functions are nested, at this time, the variables of the inner function and the outer function form a closure.

// 全局作用域定义的变量,函数作用域里是可以获取到的
var v1 = 10
v3 = 30
function foo() {
    
    
  // 函数局部作用域里面定义的变量,外界是获取不到的
  var v2 = 20
  console.log(v1, v2, v3); //10 20 30
}
foo()
console.log(v2); //ReferenceError: v2 is not defined

Insert image description here
The biggest use of scope is to isolate variables. Variables with the same name in different scopes will not conflict.

scope chain

First, let's get to know the free variables :
In the following code, console.log(a)we need to get the a variable, but a is not defined in the current scope (compare b). There are no variables defined in the current scope, which become free variables . How to get the value of the free variable - you have to go to the parent scope where the function was created. If not, always look for the upper ancestor element (this is the so-called "static scope". Static scope refers to the scope of the function. This is determined when the function is defined)

var a = 100
function fn() {
    
    
    var b = 200
    console.log(a) // 这里的a 就是一个自由变量  // 100
    console.log(b)
}
fn()

Scope chain:

The free variable will be searched along the scope to the parent scope. If the parent is not found, it will be searched layer by layer until the global scope is found but still not found, then it will be given up. This layer-by-layer relationship is the scope chain.

var a = 100
function F1() {
    
    
  var b = 200
  function F2() {
    
    
    var c = 300
    console.log(a) // 自由变量,顺作用域链向父作用域找 //100
    console.log(b) // 自由变量,顺作用域链向父作用域找 //200
    console.log(c) // 本作用域的变量  //300
  }
  F2()
}
F1()

Insert image description here

7. Function call

After the function is declared, it will not be run directly. It needs to be called before it can run.
The way to call a function is not limited to () execution.

How to call the function:

  • Function name (actual parameter list);
  • Function name.call (execution environment object, actual parameter list);
  • Function name.apply (execution environment object, actual parameter list array);
  • Function name.bind (execution environment object) (actual parameter list);

The following introduces the call, apply, and bind methods:

1. call (execution environment object, actual parameter list);

The call method is used to change the point of this. The first parameter indicates the point of this, and the following parameters indicate the actual parameters passed, which can be zero, one or more.

var obj = {
    
    
  name: '叶子yes',
  sayName: function (a,b) {
    
    
    console.log(this.name); // 叶子yes
    console.log(a,b); // 1,2
  }
}
var b = obj.sayName;
b.call(obj,1,2); // this 指向 obj
2. apply (execution environment object, actual parameter list array);

The apply method is basically the same as the call method, and is also used to change the pointer of this. The difference is that apply uses an array when passing actual parameters.

var obj = {
    
    
  name: '叶子yes',
  sayName: function (a,b) {
    
    
    console.log(this.name); // 叶子yes
    console.log(a,b); // 1,2
  }
}
var b = obj.sayName;
b.apply(obj,[1,2]); // this 指向 obj,实参列表要写成数组的形式

Note: If the first parameter of call and apply is null, then this points to the global object in the node environment and the window object in HTML.

var obj = {
    
    
  name: '叶子yes',
  sayName: function (a,b) {
    
    
    console.log(this); // window 或者 global
  }
}
var b = obj.sayName;
b.apply(null);
3. bind (execution environment object) (actual parameter list);

Bind is also used to change the point of this, but bind(执行环境对象)it returns a function that has not been executed yet. You need to use () to execute the function.

var obj = {
    
    
  name: '叶子yes',
  sayName: function (a,b) {
    
    
    console.log(this.name); // 叶子yes
    console.log(a,b); // 1,2
  }
}
var b = obj.sayName;
var c = b.bind(obj) //返回函数,此时还没有执行,需要再使用()来执行
console.log(c) //[Function: bound sayName]
c(1,2) //执行函数

Summary: call and apply both change this in the context and execute the function immediately. The bind method allows the corresponding function to be called whenever it wants, and parameters can be added during execution. This is their difference.

8. Callback function

Callback means calling back. The main function is finished in advance, and the function passed in is called later.

The role of the callback function: The callback function is generally used for time-consuming operations: because the main function does not have to wait for the callback function to finish executing, it can continue to execute its own code. For example, ajax request, such as processing files, etc.

Let's simply simulate the callback function:

//定义主函数,回调函数作为参数
function A(callback) {
    
    
  callback();
  console.log('我是主函数');
}
//定义回调函数
function B() {
    
    
  // 模仿延时操作
  setTimeout(() => {
    
    
    console.log('我是回调函数');
  }, 3000);
}
//调用主函数,将函数B传进去
A(B);
输出结果为:
我是主函数
我是回调函数

First output "I am the main function", and then output "I am the callback function" after 3 seconds.

9. Closure

1. What is a closure?
Simply put, a closure refers to a function that has the right to access variables in the scope of another function.

Closures are a special kind of object . It consists of two parts: a function and the environment in which the function is created. The environment consists of any local variables that were in scope when the closure was created.

2. Conditions for closure formation

There are three necessary conditions for the generation of closures:
1. Function nested functions
2. Internal functions refer to data (properties, functions) in external functions
3. Parameters and variables will not be recycled

This forms a function space that will not be destroyed.

The closure in the following example is a closure:

function func() {
    
    
  var a = 1, b = 2;

  function closure() {
    
    
    return a + b;
  }
  return closure;
}
console.log(func()()); // 3

A closure's scope chain contains its own scope, as well as the scope of its containing function and the global scope.

In the Javascript language, only subfunctions inside a function can read local variables, so closures can be simply understood as "functions defined inside a function".

So, in essence, closure is a bridge connecting the inside of the function with the outside of the function.

3. The role of closure

Closures can be used in many places. Its greatest uses are two, one is to read the variables inside the function, and the other is to keep the values ​​of these variables in memory.

function f1() {
    
    
  var n = 999;
  nAdd = function () {
    
     
  	n += 1 
  }
  function f2() {
    
    
    console.log(n);
  }
  return f2;
}
var result = f1();
result(); // 999
nAdd();
result(); // 1000

In this code, result is actually the closure f2 function. It was run twice, the first time the value was 999, the second time the value was 1000. This proves that the local variable n in function f1 is always stored in memory and is not automatically cleared after f1 is called.

Why is this so? The reason is that f1 is the parent function of f2, and f2 is assigned to a global variable, which causes f2 to always be in memory, and the existence of f2 depends on f1, so f1 is always in memory and will not be deleted after the call is completed. , recycled by the garbage collection mechanism (garbage collection).

Another noteworthy thing in this code is the line "nAdd=function(){n+=1}". First, the var keyword is not used before nAdd, so nAdd is a global variable, not a local variable. Secondly, the value of nAdd is an anonymous function, and the anonymous function itself is also a closure, so nAdd is equivalent to a setter, which can operate on local variables inside the function outside the function.

4. Points to note when using closures

(1) Since closures will cause the variables in the function to be stored in memory, which consumes a lot of memory, closures cannot be abused, otherwise it will cause performance problems on the web page, and may cause memory leaks in IE. This is IE's problem. BUG. The solution is to delete all unused local variables before exiting the function.

(2) The closure will change the value of the variable inside the parent function outside the parent function. Therefore, if you use the parent function as an object, the closure as its public method, and the internal variables as its private value, you must be careful not to Feel free to change the value of the variable inside the parent function. The scopes of multiple child functions point to the parent at the same time and are completely shared. So when the parent's variable object is modified, all child functions are affected.

Guess you like

Origin blog.csdn.net/lq313131/article/details/126291274
Recommended