


Detailed explanation of Javascript function declaration and recursive call
The way Javascript functions are declared and called is already a tired cliché, but some things are like this. You say it once and I will say it again. Every time I see that there are four ways to call a Javascript function written in a book or blog, I will think of Kong Yiji: There are four ways to write the word "fennel". Did you make it up?
Despite its flaws, Javascript is fascinating. At the heart of Javascript's many beautiful features are functions as first-class objects. Functions are created like other normal objects, assigned to variables, passed as arguments, return values, and hold properties and methods. Functions, as top-level objects, give Javascript powerful functional programming capabilities and also bring flexibility that is not easy to control.
1. Function declaration
Variable declaration first creates an anonymous function, and then assigns it to a specified variable:
var f = function () { // function body };
Usually we don’t have to care whether the scope of the expression on the right side of the equal sign is global or certain Within a closure, because it can only be referenced through the variable f on the left side of the equal sign, what should be concerned about is the scope of the variable f. If the reference of f to the function is destroyed (f = null), and the function is not assigned to any other variable or object property, the anonymous function will be destroyed by the garbage collection mechanism because it loses all references.
You can also use function expressions to create functions:
function f() { // function body }
Different from variable expressions, this declaration method assigns a value to a built-in attribute name of the function. At the same time, assign the function to a variable with the same name in the current scope. (The name attribute of the function, configurable, enumerable and writable are all false)
function f() { // function body } console.log(f.name); // "f" console.log(f); // f()
Javascript variables have a special feature, that is, the declaration of the variable will be advanced, and the function declaration of the expression will also be The definition of the entire function is prepended, so you can use it before the function is defined:
console.log(f.name); // "f" console.log(f); // f() function f() { // function body }
The declaration of the function expression will be hoisted to the top level of the scope, try the following code, they are not the focus of this article:
var a = 0; console.log(a); // 0 or a()? function a () {}
Crockford recommends always using the first way to declare functions. He believes that the second way relaxes the requirement that functions must be declared first and then used, which can lead to confusion. (Crockford is a "conscience programmer" similar to the "conscience artist" that Russell used to compare Wittgenstein. This sentence is very difficult to pronounce)
Functional declaration
function f() {}
Look Get up is the abbreviation of
var f = function f(){};
. As for the expression of
var a = function b(){};
, create a function and assign the built-in name attribute to "b", and then assign this function to the variable a. You can use a() to call it externally, but you cannot Using b(), because the function has been assigned to a, a variable b will not be automatically created unless you declare a variable b using var b = a. Of course the name of this function is "b" not "a".
Using the Function constructor can also be used to create functions:
var f = new Function("a,b,c","return a+b+c;");
This method actually generates an anonymous function in the global scope and assigns it to the variable f.
2. Recursive calls
Recursion is used to simplify many problems, which requires calling itself in a function body:
// 一个简单的阶乘函数 var f = function (x) { if (x === 1) { return 1; } else { return x * f(x - 1); } };
The huge flexibility of functions in Javascript leads to the use of recursion Difficulty with function names. For the variable declaration above, f is a variable, so its value can be easily replaced:
var fn = f; f = function () {};
The function is a value, it is assigned to fn, and we expect to use fn( 5) A value can be calculated, but since the variable f is still referenced inside the function, it cannot work properly.
The functional declaration looks better, but it’s a pity:
function f(x) { if (x === 1) { return 1; } else { return x * f(x - 1); } } var fn = f; f = function () {}; // may been warning by browser fn(5); // NaN
It seems that once we define a recursive function, we must be careful not to change the name of the variable easily.
What we talked about above are all functional calls. There are other ways to call functions, such as calling them as object methods.
We often declare objects like this:
var obj1 = { num : 5, fac : function (x) { // function body } };
Declare an anonymous function and assign it to the object’s attribute (fac).
If we want to write a recursion here, we have to reference the property itself:
var obj1 = { num : 5, fac : function (x) { if (x === 1) { return 1; } else { return x * obj1.fac(x - 1); } } };
Of course, it will also suffer from the same problem as the function call method:
var obj2 = {fac: obj1.fac}; obj1 = {}; obj2.fac(5); // Sadness
method After being assigned to the fac attribute of obj2, obj1.fac still needs to be referenced internally, so... it failed.
Another way will be improved:
var obj1 = { num : 5, fac : function (x) { if (x === 1) { return 1; } else { return x * this.fac(x - 1); } } }; var obj2 = {fac: obj1.fac}; obj1 = {}; obj2.fac(5); // ok
Get the attributes in the context when the function is executed through this keyword, so that when obj2.fac is executed, the fac attribute of obj2 will be referenced inside the function .
But the function can also be called by modifying the context arbitrarily, that is, the universal call and apply:
obj3 = {}; obj1.fac.call(obj3, 5); // dead again
So the recursive function cannot work properly again.
We should try to solve this problem. Do you remember the function declaration method mentioned earlier?
var a = function b(){};
这种声明方式叫做内联函数(inline function),虽然在函数外没有声明变量b,但是在函数内部,是可以使用b()来调用自己的,于是
var fn = function f(x) { // try if you write "var f = 0;" here if (x === 1) { return 1; } else { return x * f(x - 1); } }; var fn2 = fn; fn = null; fn2(5); // OK
// here show the difference between "var f = function f() {}" and "function f() {}" var f = function f(x) { if (x === 1) { return 1; } else { return x * f(x - 1); } }; var fn2 = f; f = null; fn2(5); // OK
var obj1 = { num : 5, fac : function f(x) { if (x === 1) { return 1; } else { return x * f(x - 1); } } }; var obj2 = {fac: obj1.fac}; obj1 = {}; obj2.fac(5); // ok var obj3 = {}; obj1.fac.call(obj3, 5); // ok
就这样,我们有了一个可以在内部使用的名字,而不用担心递归函数被赋值给谁以及以何种方式被调用。
Javascript函数内部的arguments对象,有一个callee属性,指向的是函数本身。因此也可以使用arguments.callee在内部调用函数:
function f(x) { if (x === 1) { return 1; } else { return x * arguments.callee(x - 1); } }
但arguments.callee是一个已经准备被弃用的属性,很可能会在未来的ECMAscript版本中消失,在ECMAscript 5中"use strict"时,不能使用arguments.callee。
最后一个建议是:如果要声明一个递归函数,请慎用new Function这种方式,Function构造函数创建的函数在每次被调用时,都会重新编译出一个函数,递归调用会引发性能问题——你会发现你的内存很快就被耗光了。

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



How to use WebSocket and JavaScript to implement an online speech recognition system Introduction: With the continuous development of technology, speech recognition technology has become an important part of the field of artificial intelligence. The online speech recognition system based on WebSocket and JavaScript has the characteristics of low latency, real-time and cross-platform, and has become a widely used solution. This article will introduce how to use WebSocket and JavaScript to implement an online speech recognition system.

WebSocket and JavaScript: Key technologies for realizing real-time monitoring systems Introduction: With the rapid development of Internet technology, real-time monitoring systems have been widely used in various fields. One of the key technologies to achieve real-time monitoring is the combination of WebSocket and JavaScript. This article will introduce the application of WebSocket and JavaScript in real-time monitoring systems, give code examples, and explain their implementation principles in detail. 1. WebSocket technology

Introduction to how to use JavaScript and WebSocket to implement a real-time online ordering system: With the popularity of the Internet and the advancement of technology, more and more restaurants have begun to provide online ordering services. In order to implement a real-time online ordering system, we can use JavaScript and WebSocket technology. WebSocket is a full-duplex communication protocol based on the TCP protocol, which can realize real-time two-way communication between the client and the server. In the real-time online ordering system, when the user selects dishes and places an order

How to use WebSocket and JavaScript to implement an online reservation system. In today's digital era, more and more businesses and services need to provide online reservation functions. It is crucial to implement an efficient and real-time online reservation system. This article will introduce how to use WebSocket and JavaScript to implement an online reservation system, and provide specific code examples. 1. What is WebSocket? WebSocket is a full-duplex method on a single TCP connection.

JavaScript and WebSocket: Building an efficient real-time weather forecast system Introduction: Today, the accuracy of weather forecasts is of great significance to daily life and decision-making. As technology develops, we can provide more accurate and reliable weather forecasts by obtaining weather data in real time. In this article, we will learn how to use JavaScript and WebSocket technology to build an efficient real-time weather forecast system. This article will demonstrate the implementation process through specific code examples. We

JavaScript tutorial: How to get HTTP status code, specific code examples are required. Preface: In web development, data interaction with the server is often involved. When communicating with the server, we often need to obtain the returned HTTP status code to determine whether the operation is successful, and perform corresponding processing based on different status codes. This article will teach you how to use JavaScript to obtain HTTP status codes and provide some practical code examples. Using XMLHttpRequest

Usage: In JavaScript, the insertBefore() method is used to insert a new node in the DOM tree. This method requires two parameters: the new node to be inserted and the reference node (that is, the node where the new node will be inserted).

JavaScript is a programming language widely used in web development, while WebSocket is a network protocol used for real-time communication. Combining the powerful functions of the two, we can create an efficient real-time image processing system. This article will introduce how to implement this system using JavaScript and WebSocket, and provide specific code examples. First, we need to clarify the requirements and goals of the real-time image processing system. Suppose we have a camera device that can collect real-time image data
