## 函数定义

``````// 写法一：函数声明（推荐写法）
function sum (num1, num2) {
return num1 + num2;
}

// 写法二：函数表达式（推荐写法）
var sum = function(num1, num2){
return num1 + num2;
};

// 写法三：Function 构造函数（不推荐写法）
var sum = new Function("num1", "num2", "return num1 + num2");
``````

``````function sum(num1, num2){
return num1 + num2;
}
console.log(sum(10,10));        // 20

var anotherSum = sum;
console.log(anotherSum(10,10)); // 20

sum = null;
console.log(anotherSum(10,10)); // 20
``````

## 没有重载

``````function addSomeNumber(num){
return num + 100;
}

function addSomeNumber(num) {
return num + 200;
}

var result = addSomeNumber(100);    // 300
``````

``````var addSomeNumber = function (num){
return num + 100;
};

addSomeNumber = function (num) {
return num + 200;
};

var result = addSomeNumber(100);    // 300
``````

## 函数声明与函数表达式

``````console.log(sum(10,10)); // 20
function sum(num1, num2){
return num1 + num2;
}
``````

``````console.log(sum(10,10)); // Uncaught TypeError: sum is not a function
var sum = function(num1, num2){
return num1 + num2;
};
``````

## 作为值的函数

``````function callSomeFunction(someFunction, someArgument){
return someFunction(someArgument);
}
``````

``````function add10(num){
return num + 10;
}

var result1 = callSomeFunction(add10, 10);
console.log(result1);   // 20

function getGreeting(name){
return "Hello, " + name;
}

var result2 = callSomeFunction(getGreeting, "Nicholas");
console.log(result2);   // "Hello, Nicholas"
``````

``````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 data = [{name: "Zachary", age: 28}, {name: "Nicholas", age: 29}];

data.sort(createComparisonFunction("name"));
console.log(data[0].name);  // Nicholas

data.sort(createComparisonFunction("age"));
console.log(data[0].name);  // Zachary
``````

## 函数的形参和实参

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

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

``````var trueFactorial = factorial;

factorial = function(){
return 0;
};

console.log(trueFactorial(5));  // 120
console.log(factorial(5));      // 0
``````

``````window.color = "red";
var o = { color: "blue" };

function sayColor(){
console.log(this.color);
}
sayColor();     // "red"

o.sayColor = sayColor;
o.sayColor();   // "blue"
``````

ECMAScript 5也规范化了另一个函数对象的属性 `caller`。这个属性中保存着「调用当前函数的函数的引用」，如果是在全局作用域中调用当前函数，它的值为 `null`。例如：

``````function outer(){
inner();
}

function inner(){
console.log(arguments.callee.caller);
}

outer();
``````

## 函数的属性和方法

JavaScript 中的函数是对象，因此函数也有属性和方法。每个函数都包含两个属性：`length``prototype`。其中，`length` 属性表示函数希望接收的命名参数的个数，如下面的例子所示。

``````function sayName(name){
console.log(name);
}

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

function sayHi(){
console.log("hi");
}

console.log(sayName.length);      // 1
console.log(sum.length);          // 2
console.log(sayHi.length);        // 0
``````

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

function callSum1(num1, num2){
return sum.apply(this, arguments);  // 传入 arguments 对象
}

function callSum2(num1, num2){
return sum.apply(this, [num1, num2]);  // 传入数组
}

console.log(callSum1(10,10));   // 20
console.log(callSum2(10,10));   // 20
``````

`call()` 方法与 `apply()` 方法的作用相同，它们的区别仅在于接收参数的方式不同。对于 `call()` 方法而言，第一个参数是 `this` 值没有变化，变化的是其余参数都直接传递给函数。换句话说，在使用 `call()` 方法时，传递给函数的参数必须逐个列举出来，如下面的例子所示。

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

function callSum(num1, num2){
return sum.call(this, num1, num2);
}

console.log(callSum(10,10));   // 20
``````

``````window.color = "red";
var o = { color: "blue" };

function sayColor(){
console.log(this.color);
}
sayColor();                // red

sayColor.call(this);       // red
sayColor.call(window);     // red
sayColor.call(o);          // blue
``````

## 关卡

``````// 挑战一，合并任意个数的字符串
var concat = function(){
// 待实现方法体
}
console.log(concat('st','on','e'));  // stone
``````
``````// 挑战二，输出指定位置的斐波那契数列
var fioacciSequece = function(count){
// 待实现方法体
}
console.log(fioacciSequece(12));  // 0、1、1、2、3、5、8、13、21、34、55、89
``````
``````// 挑战三，三维数组或 n 维数组去重，使用 arguments 重写
var arr = [2,3,4,[2,3,[2,3,4,2],5],3,5,[2,3,[2,3,4,2],2],4,3,6,2];
var unique = function(arr){
// 待实现方法体
}
console.log(unique(arr)); // [2,3,4,5,6]
``````

## 《JavaScript 闯关记》之函数的更多相关文章

1. 《JavaScript 闯关记》

为何写作此课程 stone 主要负责基于 Web 的企业内部管理系统的开发,虽然能够熟练地使用 JavaScript,但随着对 JavaScript 的理解越来越深,才发现自己尚未掌握其精髓. 201 ...

2. 《JavaScript闯关记》视频版硬广

<JavaScript闯关记>视频版硬广 stone 在菜航工作时,兼任内部培训讲师,主要负责 JavaScript 基础培训,2016年整理的<JavaScript闯关记>课 ...

3. 《JavaScript 闯关记》之作用域和闭包

作用域和闭包是 JavaScript 最重要的概念之一,想要进一步学习 JavaScript,就必须理解 JavaScript 作用域和闭包的工作原理. 作用域 任何程序设计语言都有作用域的概念,简单 ...

4. JavaScript 闯关记

DOM(文档对象模型)是针对 HTML 和 XML 文档的一个 API.DOM 描绘了一个层次化的节点树,允许开发人员添加.移除和修改页面的某一部分. 节点层次 DOM 可以将任何 HTML 或 XM ...

5. 《JavaScript 闯关记》之垃圾回收和内存管理

JavaScript 具有自动垃圾收集机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存.而在 C 和 C++ 之类的语言中,开发人员的一项基本 ...

6. 《JavaScript 闯关记》之原型及原型链

原型链是一种机制,指的是 JavaScript 每个对象都有一个内置的 __proto__ 属性指向创建它的构造函数的 prototype(原型)属性.原型链的作用是为了实现对象的继承,要理解原型链, ...

7. 《JavaScript 闯关记》之事件

JavaScript 程序采用了异步事件驱动编程模型.在这种程序设计风格下,当文档.浏览器.元素或与之相关的对象发生某些有趣的事情时,Web 浏览器就会产生事件(event).例如,当 Web 浏览器 ...

8. 《JavaScript 闯关记》之 DOM（下）

Element 类型 除了 Document 类型之外,Element 类型就要算是 Web 编程中最常用的类型了.Element 类型用于表现 XML 或 HTML 元素,提供了对元素标签名.子节点 ...

9. 《JavaScript 闯关记》之 DOM（上）

DOM(文档对象模型)是针对 HTML 和 XML 文档的一个 API.DOM 描绘了一个层次化的节点树,允许开发人员添加.移除和修改页面的某一部分. 节点层次 DOM 可以将任何 HTML 或 XM ...

## 随机推荐

1. 1.springMVC+spring+Mybatis的整合思路

SSM整合的过程:就是把一些东西交给spring管理,也就是添加配置文件的一个过程.那么有哪些东西我们要交给spring管理呢?大概有以下几个: 1.数据源(可配置数据库连接池) 2.SqlSessi ...

2. hdu 4960 Another OCD Patient （最短路 解法

http://acm.hdu.edu.cn/showproblem.php?pid=4960 2014 Multi-University Training Contest 9 Another OCD ...

3. X下轻量级桌面WindowMaker上手指南

layout: post title: 轻量级桌面WindowMaker上手指南 tags: x11, cygwin, raspi --- 最近工作上需要在远程Linux上运行一个桌面(我需要跑Net ...

4. 关于Linux下进程间使用共享内存和信号量通信的时的编译问题

今天在编译一个使用信号量实现进程同步时,出现了库函数不存在的问题.如下图 编译结果实际上是说,没include相应的头文件,或是头文件不存在(即系统不支持该库函数) 但我man shm_open是可以 ...

5. gdb使用_转

在编程调试中,经常出现段错误,此时可用gdb调试.具体方法为注册段错误信号处理函数,在处理函数中启动gdb.具体代码如下:void segv_handler(int no) { char buf[51 ...

6. Custom ASP.NET Application into SharePoint --整合ASP.NET应用程序到SharePoint

转:http://www.devexpertise.com/2009/02/18/integrating-a-custom-aspnet-application-into-sharepoint-par ...

7. hdu 1298 T9

字典树+DFS. #include<cstdio> #include<cstring> #include<cmath> #include<string> ...

8. LeetCode OJ 96. Unique Binary Search Trees

Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...

9. shell脚本学习系列之一---入门

参考:http://me.52fhy.com/shell-book/ 待后续整理...

10. jquery----数据增删改

简单版本 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...