


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构造函数创建的函数在每次被调用时,都会重新编译出一个函数,递归调用会引发性能问题——你会发现你的内存很快就被耗光了。

JavaScript's application in the real world includes front-end and back-end development. 1) Display front-end applications by building a TODO list application, involving DOM operations and event processing. 2) Build RESTfulAPI through Node.js and Express to demonstrate back-end applications.

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

Understanding how JavaScript engine works internally is important to developers because it helps write more efficient code and understand performance bottlenecks and optimization strategies. 1) The engine's workflow includes three stages: parsing, compiling and execution; 2) During the execution process, the engine will perform dynamic optimization, such as inline cache and hidden classes; 3) Best practices include avoiding global variables, optimizing loops, using const and lets, and avoiding excessive use of closures.

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

Python and JavaScript have their own advantages and disadvantages in terms of community, libraries and resources. 1) The Python community is friendly and suitable for beginners, but the front-end development resources are not as rich as JavaScript. 2) Python is powerful in data science and machine learning libraries, while JavaScript is better in front-end development libraries and frameworks. 3) Both have rich learning resources, but Python is suitable for starting with official documents, while JavaScript is better with MDNWebDocs. The choice should be based on project needs and personal interests.

The shift from C/C to JavaScript requires adapting to dynamic typing, garbage collection and asynchronous programming. 1) C/C is a statically typed language that requires manual memory management, while JavaScript is dynamically typed and garbage collection is automatically processed. 2) C/C needs to be compiled into machine code, while JavaScript is an interpreted language. 3) JavaScript introduces concepts such as closures, prototype chains and Promise, which enhances flexibility and asynchronous programming capabilities.

Different JavaScript engines have different effects when parsing and executing JavaScript code, because the implementation principles and optimization strategies of each engine differ. 1. Lexical analysis: convert source code into lexical unit. 2. Grammar analysis: Generate an abstract syntax tree. 3. Optimization and compilation: Generate machine code through the JIT compiler. 4. Execute: Run the machine code. V8 engine optimizes through instant compilation and hidden class, SpiderMonkey uses a type inference system, resulting in different performance performance on the same code.

JavaScript's applications in the real world include server-side programming, mobile application development and Internet of Things control: 1. Server-side programming is realized through Node.js, suitable for high concurrent request processing. 2. Mobile application development is carried out through ReactNative and supports cross-platform deployment. 3. Used for IoT device control through Johnny-Five library, suitable for hardware interaction.


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

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

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

SecLists
SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

Atom editor mac version download
The most popular open source editor

ZendStudio 13.5.1 Mac
Powerful PHP integrated development environment