Overview: On the difference between function declarations and function expressions

sayHi();// Correct: the function declaration is promoted
function sayHi(){
 	alert("Hi!");
}

sayHi(); // Error: the function does not exist yet
var sayHi = function(){
 	alert("Hi!");
}; 


In fact, this is invalid syntax in ECMAScript, and the JavaScript engine will try to fix the error and convert it to a reasonable state. Different browsers try to fix errors differently. Most browsers return the second declaration, ignoring condition; Firefox returns the first declaration if condition is true. So it's a dangerous way to use it.
if(condition){
 	function sayHi(){
 		alert("Hi!"); }}else {
    function sayHi(){
 		alert("Yo!"); }}// You can do that
var sayHi;
if(condition){
 	sayHi = function(){
 		alert("Hi!");
 	};
} else {
 	sayHi = function(){
 		alert("Yo!");
 	};
} 
Copy the code

Functions can also be returned as values of other functions, which may be assigned to a variable or otherwise called; Anonymous functions can be used in any case where functions are used as values.

1, the recursion

In non-strict mode, you can use arguments.callee (a pointer to the executing function) to implement recursive calls to functions

function factorial(num){
 	if (num <= 1) {return 1;
 	} else {
 		return num * factorial(num-1); }}var anotherFactorial = factorial;
factorial = null;
alert(anotherFactorial(4)); / / error!

// Both methods will not fail even if factorial=null
function factorial(num){
 	if (num <= 1) {return 1;
 	} else {
 		return num * arguments.callee(num-1); }}var factorial = (function f(num){
 	if (num <= 1) {return 1;
 	} else {
 		return num * f(num-1); }});Copy the code

2, closures

About this object

The execution environment of anonymous functions is global, so their this object usually points to window. But sometimes this may not be obvious because of the way closures are written.

var name = "The Window";
var object = {
 	name : "My Object".getNameFunc : function(){
 		return function(){
 			return this.name; }; }}; alert(object.getNameFunc()());//"The Window" (in non-strict mode)

Copy the code

In several special cases, the value of this can change unexpectedly.

var name = "The Window";
var object = {
    name: "My Object".getName: function () {
        return this.name; }}; object.getName();//"My Object"
(object.getName)(); //"My Object"
(object.getName = object.getName)(); //"The Window", in non-strict mode
Copy the code

A memory leak

If a closure holds an HTML element in its scope chain, that means that element cannot be destroyed. As shown below.

function assignHandler(){
 	var element = document.getElementById("someElement");
 	element.onclick = function(){
 		alert(element.id);
 	};
} 
Copy the code

The above code creates a closure that acts as an Element event handler, which in turn creates a circular reference. Because the anonymous function holds a reference to the live object in assignHandler(), it cannot reduce the number of references to elements. As long as anonymous functions exist, Element has at least one reference, so its memory is never reclaimed.

There are two steps to solve this problem :(1) store element.id in a variable and reference that variable in a closure (eliminating circular references) (the closure references the entire live object containing the function, which contains element.) Even if the closure does not reference Element directly, a reference will still be stored in the live object that contains the function, so you must go to the next step

function assignHandler(){
 	var element = document.getElementById("someElement");
 	var id = element.id;/ / the first step

 	element.onclick = function(){
 		alert(id);
 	};

 	element = null;/ / the second step
} 
Copy the code

3. Private variables

Privileged methods: Public methods that have access to private variables and functions

function MyObject(){
 	// Private variables and functions
 	var privateVariable = 10;
 	function privateFunction(){
 		return false;
 	}
 	// Privileged methods
 	this.publicMethod = function (){
 		privateVariable++;
 		return privateFunction();
 	};
}
Copy the code

Static private variable

Creating static private variables increases code reuse by using prototypes, but each instance does not have its own private variable.

(function(){

 	var name = "";

 	Person = function(value){
 		name = value;
 	};

 	Person.prototype.getName = function(){
 		return name;
 	};

 	Person.prototype.setName = function (value){ name = value; }; }) ();var person1 = new Person("Nicholas");
alert(person1.getName()); //"Nicholas"
person1.setName("Greg");
alert(person1.getName()); //"Greg"

var person2 = new Person("Michael");
alert(person1.getName()); //"Michael"
alert(person2.getName()); //"Michael" 
Copy the code

The module pattern

The module pattern creates private variables and privileged methods for singletons (objects with only one instance). If you have to create an object and initialize it with some data, and expose some methods to access that private data, you can use the module pattern.

 var singleton = function(){

 	// Private variables and functions
 	var privateVariable = 10;

 	function privateFunction(){
 		return false;
 	} 
	// Privileges/public methods and attributes
 	return {
 		publicProperty: true.publicMethod : function(){
 			privateVariable++;
 			return privateFunction();
 		}
 	};
}(); 
Copy the code