The function function of javascript learning in detail

A function is a block of code that can be called repeatedly. The function can also accept input parameters, and different parameters have unique corresponding return values.

overview

function declaration

JavaScript has three ways of declaring functions.

(1) function command

functionThe code block declared by the command is a function. functionThe command is followed by the function name, and the function name is followed by a pair of parentheses, which are the parameters passed into the function. The body of the function is enclosed in curly braces.

function print(s) {
  console.log(s);
}

The above code names a printfunction, and using this form later print(), you can call the corresponding code. This is called a function declaration (Function Declaration).

(2) Function expression

In addition to functiondeclaring functions with commands, you can also use variable assignment.

var print = function(s) {
  console.log(s);
};

This way of writing assigns an anonymous function to a variable. At this time, this anonymous function is also called function expression (Function Expression), because only expressions can be placed on the right side of the equal sign of the assignment statement.

When a function is declared using a function expression, functionthe command is not followed by the function name. If you add a function name, the function name is only valid inside the function body, and invalid outside the function body.

var print = function x(){
  console.log(typeof x);
};
x
// ReferenceError: x is not defined
print()
// function

In the above code, the function name is added to the function expression x. This is xonly available inside the function body, referring to the function expression itself, and is not available anywhere else. This way of writing has two uses, one is to call itself inside the function body, and the other is to facilitate debugging (when the debugging tool displays the function call stack, it will display the function name instead of showing that this is an anonymous function). Therefore, it is also very common to declare functions in the following form.

var f = function f() {};

It should be noted that the expression of the function needs to add a semicolon at the end of the statement to indicate the end of the statement. Function declarations do not need a semicolon after the closing curly brace. In general, the two ways of declaring functions are slightly different and can be considered approximately equivalent.

(3) Function constructor

The third way to declare a function is Functionas a constructor.

var add = new Function(
  'x',
  'y',
  'return x + y'
);
// Equivalent to
function add(x, y) {
  return x + y;
}

In the above code, Functionthe constructor accepts three parameters, except that the last parameter is the add"function body" of the function, and the other parameters are addthe parameters of the function.

You can pass any number of parameters to Functionthe constructor, only the last parameter will be treated as the function body, if there is only one parameter, it will be the function body.

var foo = new Function(
  'return "hello world";'
);
// Equivalent to
function foo() {
  return 'hello world';
}

FunctionThe constructor does not need to use newthe command, and the return result is exactly the same.

Overall, this way of declaring functions is so unintuitive that almost no one uses it.

Duplicate declaration of function

If the same function is declared multiple times, later declarations override earlier ones.

function f() {
  console.log(1);
}
f() // 2
function f() {
  console.log(2);
}
f() // 2

In the above code, the latter function declaration overrides the previous one. Also, because of function name promotion (see below), it is important to note that the previous declaration is invalid at any time.

The parenthesis operator, the return statement, and recursion

When calling a function, use the parenthesis operator. In the parentheses, you can add the parameters of the function.

function add(x, y) {
  return x + y;
}
add(1, 1) // 2

In the above code, the function name is followed by a pair of parentheses, and the function will be called.

The statement inside the function body returnmeans return. When the JavaScript engine encounters returna statement, it directly returns returnthe value of the expression that follows, and even if there are statements behind, it will not be executed. In other words, returnthe expression in the statement is the return value of the function. returnstatement is not required, if not, the function returns nothing, or returns undefined.

A function can call itself, which is called recursion. The following is the code to calculate the Fibonacci sequence through recursion.

function fib(num) {
  if (num === 0) return 0;
  if (num === 1) return 1;
  return fib(num - 2) + fib(num - 1);
}

fib(6) // 8

In the above code, fibthe function is called again fib, and the sixth element of the Fibonacci sequence is calculated to be 8.

first class citizen

The JavaScript language treats functions as values, on the same level as other values ​​(numbers, strings, booleans, etc.). Wherever you can use a value, you can use a function. For example, functions can be assigned to variables and properties of objects, passed as parameters to other functions, or returned as the result of functions. A function is just a value that can be executed, and there is nothing special about it.

Because functions are equal to other data types, functions are also called first-class citizens in the JavaScript language.

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

// assign the function to a variable
var operator = add;

// function as parameter and return value
function a(op){
  return op;
}
a(add)(1, 1)
// 2

Hoisting of function names

The JavaScript engine treats function names like variable names, so functionwhen a function is declared with a directive, the entire function is hoisted to the top of the code just like a variable declaration. Therefore, the following code will not report an error.

f();

function f() {}

On the surface, it looks like the above code calls the function before it is declared f. But in fact, due to "variable hoisting", the function fis hoisted to the head of the code, that is, it is declared before the call. However, if the function is defined with an assignment statement, JavaScript will report an error.

f();
var f = function (){};
// TypeError: undefined is not a function

The code above is equivalent to the form below.

var f;
f();
f = function () {};

The second line of the above code, fwhen called, fis only declared, and has not been assigned a value, which is equal to undefined, so an error will be reported.

Note that if the same function is declared with functiona command and an assignment statement as in the following example, the definition of the assignment statement will be used at the end due to function promotion.varvar

var f = function () {
  console.log('1');
}

function f() {
  console.log('2');
}

f() // 1

In the above example, on the surface, the function declared later fshould overwrite the previous varassignment statement, but because of function promotion, it is actually the opposite.

Function properties and methods

name attribute

The function nameproperty returns the name of the function.

function f1() {}
f1.name // "f1"

If the function is defined by variable assignment, namethe property returns the variable name.

var f2 = function () {};
f2.name // "f2"

However, the above case is only true when the value of the variable is an anonymous function. If the value of the variable is a named function, namethe property returns functionthe name of the function after the keyword.

var f3 = function myName() {};
f3.name // 'myName'

In the above code, f3.namethe name of the function expression is returned. Note that the real function name is still f3, and myNamethis name is only available inside the function body.

nameOne use of attributes is to get the name of the parameter function.

var myFunc = function () {};

function test(f) {
  console.log(f.name);
}

test(myFunc) // myFunc

In the above code, testthrough namethe attribute inside the function, you can know what function the parameter passed in is.

length property

The attribute of the function lengthreturns the number of parameters that the function is expected to pass in, that is, the number of parameters in the function definition.

function f(a, b) {}
f.length // 2

The above code defines an empty function f, and its lengthattribute is the number of parameters when it is defined. No matter how many parameters are entered when calling, lengththe attribute is always equal to 2.

lengthAttributes provide a mechanism to judge the difference between parameters at the time of definition and at the time of calling, so as to realize "method overloading" (overload) of object-oriented programming.

toString()

The method of the function toString()returns a string whose content is the source code of the function.

function f() {
  a();
  b();
  c();
}

f.toString()
// function f() {
//  a();
//  b();
//  c();
// }

In the above example, the method fof the function toString()returns fthe source code, including newline characters.

For those native functions, toString()the method returns function (){[native code]}.

Math.sqrt.toString()
// "function sqrt() { [native code] }"

The above code Math.sqrt()is a native function provided by the JavaScript engine, and toString()the method returns a hint of the native code.

Comments inside functions can also be returned.

function f() {/*
  This is a
  multiline comment
*/}

f.toString()
// "function f(){/*
// This is a
// multi-line comment
// */}"

Taking advantage of this, multi-line strings can be realized in disguise.

var multiline = function (fn) {
  var arr = fn.toString().split('\n');
  return arr.slice(1, arr.length - 1).join('\n');
};

function f() {/*
  This is a
  multiline comment
*/}

multiline(f);
// " This is a
// multi-line comment"

In the above example, fthere is a multi-line comment inside the function. After toString()the method gets fthe source code, remove the first and last two lines to get a multi-line string.

function scope

definition

Scope refers to the scope in which a variable exists. In the ES5 specification, JavaScript has only two scopes: one is global scope, variables exist throughout the program and can be read everywhere; the other is function scope, variables only exist inside functions. ES6 has added block-level scope, which is not covered in this tutorial.

For top-level functions, variables declared outside the function are global variables (global variable), which can be read inside the function.

var v = 1;

function f() {
  console.log(v);
}

f()
// 1

The above code shows that fglobal variables can be read inside the function v.

Variables defined inside a function that cannot be read outside are called "local variables".

function f(){
  var v = 1;
}

v // ReferenceError: v is not defined

In the above code, the variable vis defined inside the function, so it is a local variable that cannot be read outside the function.

Variables defined inside the function will overwrite global variables with the same name in this scope.

var v = 1;

function f(){
  var v = 2;
  console.log(v);
}

f() // 2
v // 1

In the code above, variables vare defined both outside and inside the function. As a result, defined inside a function, local variables voverride global variables v.

Note that for varcommands, local variables can only be declared inside the function, and all variables declared in other blocks are global variables.

if (true) {
  var x = 5;
}
console.log(x);  // 5

In the above code, the variable xis declared in the conditional judgment block, and the result is a global variable that can be read outside the block.

Variable hoisting inside functions

Like the global scope, the phenomenon of "variable hoisting" will also occur inside the function scope. varThe variable declared by the command, no matter where it is, the variable declaration will be promoted to the head of the function body.

function foo(x) {
  if (x > 100) {
    var tmp = x - 100;
  }
}

// Equivalent to
function foo(x) {
  var tmp;
  if (x > 100) {
    tmp = x - 100;
  };
}

the scope of the function itself

A function itself is also a value and has its own scope. Its scope, like a variable, is the scope in which it is declared, not the scope in which it is run.

var a = 1;
var x = function () {
  console.log(a);
};

function f() {
  var a = 2;
  x();
}

f() // 1

In the above code, the function xis fdeclared outside the function, so its scope is bound to the outer layer, and the internal variable awill not get fa value in the function body, so the output 1is not 2.

In short, the scope in which the function is executed is the scope in which it was defined, not the scope in which it was called.

It's easy to make a mistake if a function Acalls a function Bwithout taking into account that the function Bdoesn't refer to the function A's internal variables.

var x = function () {
  console.log(a);
};

function y(f) {
  var a = 2;
  f();
}

y(x)
// ReferenceError: a is not defined

The above code takes the function xas a parameter and passes it into the function y. However, the function xis ydeclared outside the function body, and the scope is bound to the outer layer, so ythe internal variables of the function cannot be found a, resulting in an error.

Similarly, the function declared inside the function body, the scope is bound to the inside of the function body.

function foo() {
  var x = 1;
  function bar() {
    console.log(x);
  }
  return bar;
}

var x = 2;
var f = foo();
f() // 1

In the above code, fooa function is declared inside the function bar, barthe scope binding foo. When we foofetch execution externally bar, the variable xpoints to foothe internal x, not foothe external x. It is this mechanism that constitutes the "closure" phenomenon to be explained below.

parameter

overview

When a function is running, it sometimes needs to provide external data. Different external data will get different results. This external data is called a parameter.

function square(x) {
  return x * x;
}

square(2) // 4
square(3) // 9

The above formula xis squarethe parameter of the function. Each time you run, you need to provide this value, otherwise you won't get the result.

omission of parameters

Function parameters are not required, and JavaScript allows parameters to be omitted.

function f(a, b) {
  return a;
}

f(1, 2, 3) // 1
f(1) // 1
f() // undefined

f.length // 2

The function of the code above fdefines two parameters, but no matter how many parameters (or no parameters) are provided at runtime, JavaScript will not report an error. The value of the omitted parameter becomes undefined. It should be noted that lengththe properties of a function have nothing to do with the number of parameters actually passed in, but only reflect the number of parameters expected to be passed in by the function.

However, there is no way to omit only the first parameters and keep the latter ones. If you must omit the first parameter, you can only pass it in explicitly undefined.

function f(a, b) {
  return a;
}

f( , 1) // SyntaxError: Unexpected token ,(…)
f(undefined, 1) // undefined

In the above code, if the first parameter is omitted, an error will be reported.

delivery method

If the function parameter is a value of a primitive type (number, string, Boolean value), the transfer method is passed by value (passes by value). This means that modifying parameter values ​​​​in the function body will not affect the outside of the function.

var p = 2;

function f(p) {
  p = 3;
}
f(p);

p // 2

In the above code, the variable pis a value of a primitive type, and fthe way to pass it into the function is to pass by value. Therefore, inside the function, pthe value of is a copy of the original value, no matter how you modify it, it will not affect the original value.

However, if the function parameter is a value of a composite type (array, object, other function), the transfer method is pass by reference. That is to say, the address of the original value passed into the function, so modifying the parameter inside the function will affect the original value.

var obj = { p: 1 };

function f(o) {
  o.p = 2;
}
f(obj);

obj.p // 2

In the above code, the address of fthe parameter object is passed into the function obj. objTherefore, properties modified inside the function pwill affect the original value.

Note that if the internal modification of the function is not a certain attribute of the parameter object, but replaces the entire parameter, the original value will not be affected at this time.

var obj = [1, 2, 3];

function f(o) {
  o = [2, 3, 4];
}
f(obj);

obj // [1, 2, 3]

In the above code, f()inside the function, the parameter object objis completely replaced with another value. The original value is not affected at this time. This is because othe value of the formal parameter ( ) is actually objthe address of the parameter, and reassignment oleads to opointing to another address, and the value stored in the original address is of course not affected.

parameter with the same name

If there is a parameter with the same name, the value that occurs last is taken.

function f(a, a) {
  console.log(a);
}

f(1, 2) // 2

In the above code, the function f()has two parameters, and the parameter names are both a. When taking a value, the latter ashall prevail, even if the latter ahas no value or is omitted, it shall prevail.

function f(a, a) {
  console.log(a);
}

f(1) // undefined

When the function is called f(), if the second parameter is not provided, athe value of is changed undefined. At this time, if you want to get athe value of the first one, you can use argumentsthe object.

function f(a, a) {
  console.log(arguments[0]);
}

f(1) // 1

arguments object

(1) Definition

Since JavaScript allows functions to have an indefinite number of parameters, a mechanism is needed to read all parameters inside the function body. This is where argumentsobjects come in.

argumentsThe object contains all the parameters of the function at runtime, arguments[0]which is the first parameter, arguments[1]the second parameter, and so on. This object can only be used inside the function body.

var f = function (one) {
  console.log(arguments[0]);
  console.log(arguments[1]);
  console.log(arguments[2]);
}

f(1, 2, 3)
// 1
// 2
// 3

In normal mode, argumentsobjects can be modified at runtime.

var f = function(a, b) {
  arguments[0] = 3;
  arguments[1] = 2;
  return a + b;
}

f(1, 1) // 5

In the above code, f()the parameters passed in when the function is called are modified to sum inside the 3function 2.

In strict mode, argumentsobjects and function parameters do not have a linkage relationship. That is, modifying argumentsthe object does not affect the actual function parameters.

var f = function(a, b) {
  'use strict'; // enable strict mode
  arguments[0] = 3;
  arguments[1] = 2;
  return a + b;
}

f(1, 1) // 2

In the above code, the function body is in strict mode, and modifying argumentsthe object at this time will not affect the real parameters aand sum b.

Through the properties argumentsof the object length, you can determine how many parameters are used when the function is called.

function f() {
  return arguments.length;
}

f(1, 2, 3) // 3
f(1) // 1
f() // 0

(2) Relationship with arrays

Note that, while argumentsmuch like an array, it is an object. Array-specific methods (such as sliceand forEach) cannot argumentsbe used directly on objects.

argumentsThe real solution, if you want your object to use array methods, is to argumentsconvert it to a real array. Here are two commonly used conversion methods: slicemethods and filling new arrays one by one.

var args = Array.prototype.slice.call(arguments);

// or
var args = [];
for (var i = 0; i < arguments.length; i++) {
  args.push(arguments[i]);
}

(3) callee attribute

argumentsThe object has a calleeproperty that returns the original function it corresponds to.

var f = function () {
  console.log(arguments.call === f);
}

f() // true

It can be used arguments.calleeto achieve the purpose of calling the function itself. This attribute is disabled in strict mode, so its use is not recommended.

Other knowledge points of functions

Closure

Closure is a difficult point of the JavaScript language, and it is also its feature. Many advanced applications rely on closures.

To understand closures, you must first understand variable scope. As mentioned earlier, JavaScript has two kinds of scopes: global scope and function scope. Global variables can be read directly inside the function.

var n = 999;

function f1() {
  console.log(n);
}
f1() // 999

In the above code, the function f1can read global variables n.

However, under normal circumstances, variables declared inside the function cannot be read from outside the function.

function f1() {
  var n = 999;
}

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

In the above code, f1the variables declared inside the function ncannot be read outside the function.

If for various reasons, you need to get the local variables in the function. Normally, this is not possible and is only possible through workarounds. That is, inside the function, define another function.

function f1() {
  var n = 999;
  function f2() {
  console.log(n); // 999
  }
}

In the above code, the function f2is f1inside the function, and f1all local variables inside f2are visible to the right. But the reverse is not possible, f2the internal local variables f1are not visible. This is the unique "chain scope" structure of the JavaScript language. The child object will look up all the variables of the parent object level by level. Therefore, all variables of the parent object are visible to the child object, and vice versa.

Since the local variable f2can be read f1, as long as it is used f2as the return value, can't we f1read its internal variable externally!

function f1() {
  var n = 999;
  function f2() {
    console.log(n);
  }
  return f2;
}

var result = f1();
result(); // 999

In the above code, f1the return value of the function is the function f2. Since the internal variable f2can be read , the internal variable f1can be obtained externally .f1

Closures are functions f2, that is, functions that can read variables inside other functions. Since in the JavaScript language, only the sub-functions inside the function can read the internal variables, so the closure can be simply understood as "a function defined inside a function". The biggest feature of a closure is that it can "remember" the environment in which it was born, such as f2remembering the environment in which it was born f1, so f2it can get f1internal variables from it. In essence, a closure is a bridge that connects the inside of the function with the outside of the function.

There are two biggest uses of closures. One is to read the variables inside the outer function, and the other is to keep these variables in memory at all times, that is, closures can keep the environment in which they were born. Please see the following example, the closure makes the internal variable remember the operation result of the last call.

function createIncrementor(start) {
  return function () {
    return start++;
  };
}

var inc = createIncrementor(5);

inc() // 5
inc() // 6
inc() // 7

In the above code, startit is createIncrementorthe internal variable of the function. With closures, startthe state is preserved, and each call is calculated on the basis of the previous call. It can be seen from this that the closure incmakes createIncrementorthe internal environment of the function always exist. So, a closure can be seen as an interface to the inner scope of a function.

Why can closures return the internal variables of the outer function? The reason is that the closure (in the above example inc) uses the outer variable ( start), which causes the outer function ( createIncrementor) to not be released from memory. As long as the closure is not cleared by the garbage collection mechanism, the running environment provided by the outer function will not be cleared, and its internal variables will always save the current value for the closure to read.

Another use of closures is to encapsulate private properties and methods of objects.

function Person(name) {
  was _age;
  function setAge(n) {
    _age = n;
  }
  function getAge() {
    return _age;
  }

  return {
    name: name,
    getAge: getAge,
    setAge: setAge
  };
}

var p1 = Person('Zhang San');
p1.setAge(25);
p1.getAge() // 25

In the above code, Personthe internal variables of the function become the private variables of the returned object _agethrough the closure getAgeand sum.setAgep1

Note that every time the outer function runs, a new closure will be generated, and this closure will retain the internal variables of the outer function, so the memory consumption is very large. Therefore, closures cannot be abused, otherwise it will cause performance problems on the web page.

Immediately Invoked Function Expressions (IIFEs)

According to the syntax of JavaScript, parentheses ()follow the function name and indicate that the function is called. For example, print()it means calling printa function.

Sometimes, we need to call a function immediately after defining it. At this time, you cannot put parentheses after the function definition, which will cause a syntax error.

function(){ /* code */ }();
// SyntaxError: Unexpected token (

The reason for this error is that functionthis keyword can be used as both a statement and an expression.

// statement
function f() {}

// expression
var f = function f() {}

When used as an expression, the function can be called directly after the definition with parentheses.

var f = function f(){ return 1}();
f // 1

In the above code, the parentheses are added directly after the function definition to call, and no error is reported. The reason is functionthat as an expression, the engine treats the function definition as a value. In this case, no error will be reported.

In order to avoid parsing ambiguity, JavaScript stipulates that if functiona keyword appears at the beginning of a line, it will be interpreted as a statement. Therefore, after the engine sees that the beginning of the line is functiona keyword, it thinks that this paragraph is the definition of a function and should not end with parentheses, so it reports an error.

The solution to calling the function immediately after definition is not to let functionit appear at the beginning of the line, so that the engine understands it as an expression. The easiest way to deal with it is to put it in parentheses.

(function(){ /* code */ }());
// or
(function(){ /* code */ })();

The above two writing methods start with parentheses, and the engine will think that what follows is an expression rather than a function definition statement, so errors are avoided. This is called "Immediately-Invoked Function Expression", or IIFE for short.

Note that the semicolon at the end of the above two ways of writing is required. If the semicolon is omitted, an error may be reported when two IIFEs are connected.

// error
(function(){ /* code */ }())
(function(){ /* code */ }())

There is no semicolon between the two lines of the above code, JavaScript will interpret them together, and interpret the second line as the parameter of the first line.

By extension, any method that allows the interpreter to process function definitions with expressions can produce the same effect, such as the following three writing methods.

var i = function(){ return 10; }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();

It is even possible to write like the following.

!function () { /* code */ }();
~function () { /* code */ }();
-function () { /* code */ }();
+function () { /* code */ }();

Normally, this kind of "immediately executed function expression" is only used for anonymous functions. It has two purposes: one is that there is no need to name the function to avoid polluting global variables; the other is that a separate scope is formed inside the IIFE, which can encapsulate some private variables that cannot be read from the outside.

// writing one
var tmp = newData;
processData(tmp);
storeData(tmp);

// writing method two
(function () {
  var tmp = newData;
  processData(tmp);
  storeData(tmp);
}());

In the above code, writing method 2 is better than writing method 1, because it completely avoids polluting global variables.

eval command

basic usage

evalCommands accept a string as an argument and execute the string as a statement.

eval('var a = 1;');
a // 1

The above code runs the string as a statement, generating variables a.

If the argument string cannot be run as a statement, an error will be reported.

eval('3x') // Uncaught SyntaxError: Invalid or unexpected token

The strings placed evalin should have their own meaning and cannot be evalused in conjunction with other commands. For example, the following code will throw an error.

eval('return;'); // Uncaught SyntaxError: Illegal return statement

The above code will report an error because returnit cannot be used alone and must be used in a function.

If evalthe argument is not a string, it will be returned unchanged.

eval(123) // 123

evalIt does not have its own scope and is executed in the current scope, so it may modify the value of variables in the current scope, causing security problems.

var a = 1;
eval('a = 2');

a // 2

In the above code, evalthe command modifies athe value of the external variable. For this reason, evalthere are security risks.

In order to prevent this risk, JavaScript stipulates that if strict mode is used, evalvariables declared inside will not affect the outer scope.

(function f() {
  'use strict';
  eval('var foo = 123');
  console.log(foo);  // ReferenceError: foo is not defined
})()

In the above code, fthe inside of the function is in strict mode. At this time, the variables evaldeclared inside foowill not affect the outside.

However, even in strict mode, evalvariables in the current scope can still be read and written.

(function f() {
  'use strict';
  var foo = 1;
  eval('foo = 2');
  console.log(foo);  // 2
})()

In the above code, in strict mode, evalexternal variables are still rewritten internally, which shows that security risks still exist.

In short, evalthe essence is to inject code in the current scope. It is generally not recommended due to security risks and detrimental to JavaScript engine optimization execution speed. Under normal circumstances, evalthe most common occasion is to parse the string of JSON data, but the correct way should be to use the native JSON.parsemethod.

Alias ​​call for eval

As mentioned earlier, evalit is not conducive to engine optimization execution speed. What's more troublesome is that there is the following situation where the engine cannot tell what is being executed at the stage of static code analysis eval.

var m = eval;
m('var x = 1');
x // 1

In the above code, the variable mis evalan alias of . During the static code analysis phase, the engine cannot tell that m('var x = 1')what is being executed is evala command.

In order to ensure evalthat aliases do not affect code optimization, the JavaScript standard stipulates that all executions using aliases evalare evalin the global scope.

var a = 1;

function f() {
  var a = 2;
  where e = eval;
  e('console.log(a)');
}

f() // 1

In the above code, evalit is an alias call, so even if it is in a function, its scope is still the global scope, so the output is a aglobal variable. In this way, the engine can confirm e()that it will not affect the current function scope, and this line can be excluded during optimization.

evalThere are various forms of alias calls, as long as it is not a direct call, it is an alias call, because the engine can only distinguish eval()this form as a direct call.

eval.call(null, '...')
window.eval('...')
(1, eval)('...')
(eval, eval)('...')

The above forms are all evalalias calls, and the scope is the global scope.

reference link

Guess you like

Origin blog.csdn.net/zy_dreamer/article/details/132160426