# 函数声明

``````//这样也不会报错
sayHi();
function sayHi(){
}
``````

``````if(condition){
function sayHi(){
}
} else {
function sayHi(){
}
}
``````

# 函数表达式

``````sayHi(); // 报错函数不存在
var sayHi = function(){
};
``````

``````var sayHi;
if(condition){
sayHi = function(){
};
} else {
sayHi = function(){
};
}
``````

# 递归

## 最初级的版本

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

``````//将anotherFactorial指向函数
var anotherFactorial = factorial;
//将factorial指向空
factorial = null;
//再调用这个函数时，里面的factorial(num-1)就无法执行了
``````

## 第二个版本

``````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);
}
});
``````

# 闭包

``````function createComparisonFunction(propertyName) {
return function(object1, object2){
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if (value1 < value2){
return -1;
} else if (value1 > value2){
return 1;
} else {
return 0;
}
};
}
var compare = createComparisonFunction("name");
var result = compare({ name: "Nicholas" }, { name: "Greg" });
``````

## 普通函数的作用域链

``````unction compare(value1, value2){
if (value1 < value2){
return -1;
} else if (value1 > value2){
return 1;
} else {
return 0;
}
}
var result = compare(5, 10);
``````

## 闭包的作用域链

``````var compare = createComparisonFunction("name");
var result = compare({ name: "Nicholas" }, { name: "Greg" });
``````

``````compareNames = null;
``````

## 闭包与变量

``````function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(){
return i;
};
}
return result;
}
var a = createFunctions();
``````

``````function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(num){
return function(){
return num;
};
}(i);
}
return result;
}
var a = createFunctions();
``````

## 关于this对象

``````var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
``````

``````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"
``````

## 内存泄漏

``````function assignHandler(){
var element = document.getElementById("someElement");
element.onclick = function(){
};
}
``````

``````function assignHandler(){
var element = document.getElementById("someElement");
var id = element.id;
element.onclick = function(){
};
element = null;
}
``````

## 模仿块级作用域

``````var someFunction = function(){
//块级作用域
};
someFunction();
``````

``````function(){
//块级作用域
}(); //报错
``````

``````(function(){
//块级作用域
})();
``````

# 私有变量

``````function MyObject(){
var privateVariable = 10;
function privateFunction(){
return false;
}
this.publicMethod = function (){
privateVariable++;
return privateFunction();
};
}
``````

privateVariable和privateFunction()只有通过publicMethod方法才能访问。

``````function Person(name){
this.getName = function(){
return name;
};
this.setName = function (value) {
name = value;
}; }
var person = new Person("Nicholas");
person.setName("Greg");
``````

## 静态私有变量

``````(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");
person1.setName("Greg");

var person2 = new Person("Michael");
``````

## 模块模式

``````var singleton = {
name : value,
method : function () {
}
};
``````

``````var application = function(){
var components = new Array();
components.push(new BaseComponent());
return {
getComponentCount : function(){
return components.length;
},
registerComponent : function(component){
if (typeof component == "object"){
components.push(component);
}
}
};
}();
``````

## 增强的模块模式

``````var application = function(){
var components = new Array();
components.push(new BaseComponent());

var app = new BaseComponent();
app.getComponentCount = function(){
return components.length;
};
app.registerComponent = function(component){
if (typeof component == "object"){
components.push(component);
}
};
return app;
}();
``````

### 推荐阅读更多精彩内容

• 定义函数的方式有两种：函数声明和函数表达式。 函数声明的一个重要特征就是函数声明提升，意思是在执行代码前会先读取函...
oWSQo阅读 103评论 0 0
• 本章内容 函数表达式的特征 使用函数实现递归 使用闭包定义私有变量 定义函数的方式有两种：一种是函数声明，另一种就...
闷油瓶小张阅读 78评论 0 0
• 函数表达式的特征使用函数表达式递归使用闭包定义私有变量 定义函数的方式有两种：函数声明，类似变量声明用var，函数...
王海洋_前端阅读 49评论 0 0
• 最近学这块知识学得有些吃力。还有很多遗漏的地方，只能以后多看些书来弥补了。 第7章 函数表达式 函数定义的两种方式...
丨ouo丨阅读 69评论 0 1
• 一早醒来，发现周围不再是熟悉的场景。首先看到的，也不再是天花板，而是太阳初升粉红橙色的朝霞满天，有多久没有见到这么...
繁花坞阅读 4,313评论 10 15