4
头图
"Code tailor" provides technical-related information and a series of basic articles for front-end developers. Follow the "Novices of Xiaohe Mountain" public account on WeChat to get the latest articles in time.

Preface

Before starting to learn, what we want to tell you is that this article is a JavaScript of the "function" part of 060a7223c72f23 language knowledge. If you have mastered the following knowledge items, you can skip this section and go directly to the topic exercise

  • Function introduction
  • Function name
  • Function overloading
  • Function declaration and function expression
  • Function as value
  • this
  • Function recursion

If you have forgotten some parts, 👇🏻 is ready for you!

Summary

Function introduction

Functions are the core part of all programming languages because they can encapsulate statements and can be executed anywhere and any time after being defined. ECMAScript function uses function keyword statement, followed by a set of parameters, then the body of the function.

The following is the basic syntax of the function:

function functionName(arg0, arg1,...,argN) {
 //表达式
}

Below is an example:

function sayHi(name, message) {
  console.log('Hello ' + name + ', ' + message)
}

The function can be called by the function name. The parameters to be passed to the function are placed in parentheses (if there are multiple parameters, they are separated by commas).

The following is an example sayHi()

sayHi('xhs', 'do you study today?')

The output result of calling this function is "Hello xhs, do you study today?" . The parameters name and message are spliced together as a string inside the function, and finally output to the console console.log()

ECMAScript does not need to specify whether to return a value, nor does it limit the type of return value. Any function can use the return statement to return the value of the function at any time. The usage is followed by the value to be returned, and the return value can be of any type. such as:

function sum(num1, num2) {
  return num1 + num2
}

The function sum() adds two values and returns the result. Note that return statement to indicate that the function has a return value. Then you can call it like this:

const result = sum(5, 10)

It is worth noting that as long as the return is executed, the function will immediately stop executing and exit. Therefore, return statement will not be executed. such as:

function sum(num1, num2) {
  return num1 + num2

  console.log('Hello world') //不会执行
}

In this example, console.log() will not be executed because it is after the return statement, and the interpreter will stop executing the function after return

There can be multiple return statements in a function, like this:

function subtract(num1, num2) {
  if (num1 < num2) {
    return num2 - num1
  } else {
    return num1 - num2
  }
}

The subtract() function is used to calculate the difference between two values. If the first value is less than the second, use the second to subtract the first; otherwise, use the first to subtract the second. Each branch in the code has its own return statement, which returns the correct difference. return statement can also have no return value. At this time, the function will immediately stop execution and return to undefined . This usage is most commonly used to terminate function execution prematurely, not to return a value. For example, in the following example, console.log() will not be executed:

function sayHi(name, message) {
  return

  console.log('Hello ' + name + ', ' + message) // 不会执行
}
According to development experience, a function either returns a value or does not return a value. Functions that only return values under certain conditions can cause trouble, especially when debugging.

Function name

Function names are pointers to functions, so they have the same behavior as other variables that contain pointers to objects. This means that a function can have multiple function names, as shown below:

function sum(num1, num2) {
  return num1 + num2
}

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

let xhsSum = sum

console.log(xhsSum(10, 10)) // 20

sum = null

console.log(xhsSum(10, 10)) // 20

The above code defines a sum , which is used to sum two numbers. Then declare a variable xhsSum and set its value equal to sum . Note that using the function name without parentheses will access the function pointer name, but will not execute the function. At this time, both xhsSum and sum point to the same function. Calling xhsSum() can also return the result. sum setting null , the association between it and the function is cut off. And xhsSum() can still be called as usual, no problem.

Function parameters

ECMAScript function are different from most other languages. ECMAScript function does not care about the number of parameters passed in, nor the data types of these parameters. To receive two parameters when defining a function does not mean that two parameters are passed when calling. You can pass one, three, or none at all, and the interpreter will not report an error.

The reason for this is mainly because ECMAScript function are represented as an array internally. When a function is called, it will always receive an array, but the function does not care what the array contains. If there is nothing in the array, it's okay; if the elements of the array exceed the requirements, it's okay.

In fact, when using the function keyword to define a (non-arrow) function, you can access the arguments object inside the function, and get the value of each parameter passed in from it. arguments object is an array-like object (but not Array ), so you can use square bracket syntax to access its elements (the first parameter is arguments[0] , the second parameter is arguments[1] ). To determine how many parameters are passed in, you can access the arguments.length attribute. In the following example, the first parameter of the sayHi() name :

function sayHi(name, message) {
  console.log('Hello ' + name + ', ' + message)
}

The same parameter value can be obtained through arguments[0] Therefore, it is also possible to rewrite the function without declaring parameters:

function sayHi() {
  console.log('Hello ' + arguments[0] + ', ' + arguments[1])
}

In the rewritten code, there are no named parameters. name and message parameters are gone, but the function can still be called. This shows that ECMAScript function are only written out for convenience, not necessarily. Unlike other languages, ECMAScript do not create function signatures that must match for subsequent calls. This is because there is no mechanism for validating named parameters. You can also check the number of passed parameters through the length arguments The following example shows that every time a function is called, the number of parameters passed in is printed out:

function getArgsNum() {
  console.log(arguments.length)
}

getArgsNum('string', 45) // 2

getArgsNum() // 0

getArgsNum(12) // 1

This example prints 2 , 0 and 1 (in order). In this case, developers can pass as many parameters as they want.

such as:

function getTotle() {
  if (arguments.length === 1) {
    console.log(arguments[0] + 10)
  } else if (arguments.length === 2) {
    console.log(arguments[0] + arguments[1])
  }
}

getTotle(10) // 20

getTotle(30, 20) // 50

This function getTotle() 10 when only one parameter is passed, and add them when passing two parameters, and then return. So getTotle(10) returns 20 , and getTotle(30,20) returns 50 . Although not as clear as the real function overloading, it is enough to make up for the lack of ECMAScript in this regard.

Another important aspect that must be understood is that arguments objects can be used with named parameters, such as:

function getTotle(num1, num2) {
  if (arguments.length === 1) {
    console.log(num1 + 10)
  } else if (arguments.length === 2) {
    console.log(arguments[0] + num2)
  }
}

In this getTotle() function, two named parameters and the arguments object are used at the same time. The named parameter num1 holds the arugments[0] , so it doesn't matter who uses it. (Similarly, num2 also holds the same value as arguments[1] arguments object is that its value will always be synchronized with the corresponding named parameter. Consider the following example:

function getTotle(num1, num2) {
  arguments[1] = 10

  console.log(arguments[0] + num2)
}

This getTotle() function rewrites the value of the second parameter to 10 . Because arguments object will be automatically synchronized to the corresponding named parameter, modifying arguments[1] will also modify num2 , so both values are 10 . But this does not mean that they all access the same memory address, they are still separated in memory, but they will remain synchronized.

Another thing to remember: if only one parameter is passed, and then arguments[1] set to a certain value, then this value will not be reflected in the second named parameter. This is because arguments object is determined by the number of parameters passed in, rather than the number of named parameters given when the function is defined. For named parameters, if this parameter is not passed when calling the function, its value is undefined . This is similar to defining a variable without initializing it.

For example, if only to getTotle() pass a parameter, then the num2 value is undefined . In strict mode, arguments will have some changes. First, arguments[1] as before will no longer affect the value of num2 Even if arguments[1] set to 10 , num2 is still the value passed in. Secondly, trying to rewrite the arguments object in the function will result in a syntax error. (The code will not be executed either.)

Function overloading

ECMAScript function cannot be overloaded like traditional programming. In other languages such as Java , a function can have two definitions, as long as the signatures (type and number of parameters received) are different. As mentioned earlier, the ECMAScript function has no signature because the parameters are represented by an array containing zero or more values. Without a function signature, there is naturally no overloading. If ECMAScript , the one defined later will override the one defined earlier. Consider the following example:

function addSomeNumber(num) {
  return num + 100
}

function addSomeNumber(num) {
  return num + 200
}
let result = addSomeNumber(100) // 300

Here, the function addSomeNumber() is defined twice. The first version 100 to the parameter, and the second version 200 . When this function is called in the last line, 300 is returned because the second definition overwrites the first one.

Function declaration and function expression

We can function , or assign a variable to a function. These two methods can be called and executed normally in most cases. However, the JavaScript engine treats function declarations and function expressions differently when loading data. JavaScript engine reads the function declaration before executing any code and generates the function definition in the execution context. The function expression must wait until the code execution reaches its line before generating the function definition in the execution context. Consider the following example:

// 没问题
console.log(sum(10, 10))

function sum(num1, num2) {
  return num1 + num2
}

The above code can run normally, because the function declaration will be read and added to the execution context before any code is executed. This process is called function declaration promotion ( function declaration hoisting ). When executing the code, the JavaScript engine will perform a scan first, and promote the found function declarations to the top of the source code tree. So even if function definitions appear after the code that calls them, the engine will lift the function declarations to the top. If you change the function declaration in the previous code to an equivalent function expression, an error will occur during execution:

// 会出错
console.log(sum(10, 10))

var sum = function (num1, num2) {
  return num1 + num2
}

Function as value

Because the function name ECMAScript , the function can be used wherever variables can be used. This means that not only can you pass a function as a parameter to another function, but you can also return another function in one function.

function add10(num) {
  return num + 10
}
let result1 = callSomeFunction(add10, 10)
console.log(result1) // 20
function getGreeting(name) {
  return 'Hello, ' + name
}
let result2 = callSomeFunction(getGreeting, 'Nicholas')
console.log(result2) // "Hello, Nicholas"
function fun1(x) {
  return function (y) {
    return function (z) {
      console.log(x * y * z)
    }
  }
}
fun1(2)(3)(4) //24

this

this is a special object that has different behaviors in standard functions and arrow functions.

In the standard function, this refers to the context object that treats the function as a method call. At this time, it is usually called the this value (when the function is called in the global context of the web page, this points to the window object). Consider the following example:

window.color = 'red'

let o = {
  color: 'blue',
}

function sayColor() {
  console.log(this.color)
}

sayColor() // 'red'

o.sayColor = sayColor

o.sayColor() // 'blue'

sayColor() defined in the global context references the this object. Which object this this refers to can only be determined when the function is called. Therefore, this value may change during the execution of the code. sayColor() in the global context, the result will output red , because this points to window , and this.color equivalent to window.color . After assigning sayColor() to o and then calling o.sayColor() , this will point to o , that is, this.color equivalent to o.color blue will be displayed.

In the arrow function, this refers to the context in which the arrow function is defined. Content arrow function we will function extension of the second part of mentioned in detail in.

Function recursion

The usual form of a recursive function is that a function calls itself by name, as shown in the following example:

function factorial(num) {
  if (num <= 1) {
    return 1
  } else {
    return num * factorial(num - 1)
  }
}

This is the classic recursive factorial function. Although it is possible to write this way, if you assign this function to other variables, problems will occur:

let anotherFactorial = factorial

factorial = null

console.log(anotherFactorial(4)) // 报错

Here the factorial() function is saved in another variable anotherFactorial , and then factorial set to null , so only a reference to the original function is retained. When calling anotherFactorial() , 060a7223c73957 must be called factorial() , but because it is no longer a function, an error will occur. arguments.callee when writing recursive functions to avoid this problem. arguments.callee is a pointer to the function being executed, so it can be called recursively inside the function, as shown below:

function factorial(num) {
  if (num <= 1) {
    return 1
  } else {
    return num * arguments.callee(num - 1)
  }
}

Replace the function name with arguments.callee to ensure that there will be no problems when calling this function no matter what variables are used. Therefore, when writing recursive functions, arguments.callee is the first choice for referencing the current function. However, the code running in strict mode cannot access arguments.callee , because the access will be wrong. At this point, you can use named function expressions ( named function expression ) to achieve your goal. such as:

const factorial = function f(num) {
  if (num <= 1) {
    return 1
  } else {
    return num * f(num - 1)
  }
}

Self-test

One: What does the following code output

function callFunc(func, argument) {
  return func(argument)
}
function func1(argument) {
  console.log(argument + '.')
}
callFunc(func1, 'hello,world')

2: What does the following code output

function recursion(num) {
  if (num === 0) return 1
  else if (num % 2 === 0) return recursion(num - 1) + 1
  else return recursion(num - 1)
}

console.log(recursion(6))

160a7223c73a2b 3: What will be output when the two

func1(1, 2)
function func2(x, y) {
  console.log(x + y)
}
let func1 = func2
func2(1, 2)
function func2(x, y) {
  console.log(x + y)
}

Problem analysis

One,

Answer: 'hello,world.'

callFunc function of the 060a7223c73a9d function is actually to execute the first parameter and pass the second parameter to the first parameter as a parameter.


two,

Answer: 4

recursion is a recursive function, if num equal 0 returns 1 , if num is an even number, a result on the next front +1 , if the next odd returns a result. Its function is to num how many even numbers there are 0 So recursion(6) is 4


III,

func1(1,2) outputs ReferenceError func1 not been defined and assigned when it is called. func2(1,2) outputs 3 because function will be advanced and can be used before.


小和山的菜鸟们
377 声望2.1k 粉丝

每日进步的菜鸟,分享前端学习手册,和有心学习前端技术的小伙伴们互相探讨,一同成长。