## 前言 关于函数的核心内容: - 函数有哪几种定义和调用方式 - this:函数内部的 this 指向、如何改变 this 的指向。 - 函数的严格模式 - 高阶函数:函数作为参数传递、函数作为返回值传递 - 闭包:闭包的作用 - 递归:递归的两个条件 - 深拷贝和浅拷贝的区别 ## 函数的介绍 函数:就是将一些功能或语句进行**封装**,在需要的时候,通过**调用**的形式,执行这些语句。 - **函数也是一个对象** - 使用`typeof`检查一个函数对象时,会返回function **函数的作用**: - 将大量重复的语句抽取出来,写在函数里,以后需要这些语句的时候,可以直接调用函数,避免重复劳动。 - 简化编程,让编程模块化。高内聚、低耦合。 来看个例子: ```javascript console.log("你好"); sayHello(); // 调用函数 // 定义函数 function sayHello(){ console.log("欢迎"); console.log("welcome"); } ``` ## 函数的定义 ### 方式一:函数声明(命名函数) 使用`函数声明`来创建一个函数(也就是 function 关键字)。语法: ```javascript function 函数名([形参1,形参2...形参N]){ // 备注:语法中的中括号,表示“可选” 语句... } ``` 举例: ```javascript function fun1(a, b){ return a+b; } ``` 解释如下: - function:是一个关键字。中文是“函数”、“功能”。 - 函数名字:命名规定和变量的命名规定一样。只能是字母、数字、下划线、美元符号,不能以数字开头。 - 参数:可选。 - 大括号里面,是这个函数的语句。 PS:在有些编辑器中,方法写完之后,我们在方法的前面输入`/**`,然后回车,会发现,注释的格式会自动补齐。 ### 方式二:函数表达式(匿名函数) 使用`函数表达式`来创建一个函数。语法: ```javascript var 变量名/函数名 = function([形参1,形参2...形参N]){ 语句.... } ``` 举例: ```javascript var fun2 = function() { console.log("我是匿名函数中封装的代码"); }; ``` 从方式二的举例中可以看出:所谓的“函数表达式”,其实就是将匿名函数赋值给一个变量。 ### 方式三:使用构造函数 new Function() 使用构造函数`new Function()`来创建一个对象。这种方式,用的少。 语法: ```javascript var 变量名/函数名 = new Function('形参1', '形参2', '函数体'); ``` 注意,Function 里面的参数都必须是**字符串**格式。也就是说,形参也必须放在**字符串**里;函数体也是放在**字符串**里包裹起来,放在 Function 的最后一个参数的位置。 代码举例: ```javascript var fun3 = new Function('a', 'b', 'console.log("我是函数内部的内容"); console.log(a + b);'); fun3(1, 2); // 调用函数 ``` 打印结果: ``` 我是函数内部的内容 3 ``` **分析**: 方式3的写法很少用,原因如下: - 不方便书写:写法过于啰嗦和麻烦。 - 执行效率较低:首先需要把字符串转换为 js 代码,然后再执行。 ### 总结 1、**所有的函数,都是 `Fuction` 的“实例”**(或者说是“实例对象”)。函数本质上都是通过 new Function 得到的。 2、函数既然是实例对象,那么,**函数也属于“对象”**。还可以通过如下特征,来佐证函数属于对象: (1)我们直接打印某一个函数,比如 `console.log(fun2)`,发现它的里面有`__proto__`。(这个是属于原型的知识,后续再讲) (2)我们还可以打印 `console.log(fun2 instanceof Object)`,发现打印结果为 `true`。这说明 fun2 函数就是属于 Object。 ## 函数的调用 ### 方式1:普通函数的调用 函数调用的语法: ```javascript 函数名(); ``` 或者: ``` 函数名.call(); ``` 代码举例: ```javascript function fn1() { console.log('我是函数体里面的内容1'); } function fn2() { console.log('我是函数体里面的内容2'); } fn1(); // 调用函数 fn2.call(); // 调用函数 ``` ### 方式2:通过对象的方法来调用 ```javascript var obj = { a: 'qianguyihao', fn2: function() { console.log('千古壹号,永不止步!'); }, }; obj.fn2(); // 调用函数 ``` 如果一个函数是作为一个对象的属性保存,那么,我们称这个函数是这个对象的**方法**。 PS:关于函数和方法的区别,本文的后续内容里有讲到,可以往下面翻。 ### 方式3:立即执行函数 代码举例: ```javascript (function() { console.log('我是立即执行函数'); })(); ``` 立即执行函数在定义后,会自动调用。 PS:关于立即执行函数,本文的后续内容里有讲到,可以往下面翻。 上面讲到的这三种方式,是用得最多的。接下来讲到的三种方式,暂时看不懂也没关系,可以等学完其他的知识点,再回过头来看。 ### 方式4:通过构造函数来调用 代码举例: ```javascript function Fun3() { console.log('千古壹号,永不止步~'); } new Fun3(); ``` 这种方式用得不多。 ### 方式5:绑定事件函数 代码举例: ```html