- 函数也是一种对象
- 使用关键字 function 定义函数,用 typeof 操作符判断函数类型将返回** “function” 。**
- 函数存储在变量中,不需要函数名称,通常通过变量名来调用。
- 是唯一能执行的变量、对象
- 目的是:提高代码复用,体现了封装思想
- 函数有 属性 和 方法。
- 函数定义作为对象的属性,称之为对象方法
- 函数如果用于创建新的对象,称之为对象的构造函数
- 所有的函数,都是 Fuction 的“实例”(或者说是“实例对象”)。函数本质上都是通过 new Function 得到的。
函数定义
关键字
使用函数声明来创建一个函数,也就是 function 关键字
function 函数名(形参1,形参2...形参N){
...
}
function fun1(a, b){
return a+b;
}
表达式
将匿名函数赋值给一个变量。
var 变量名 = function(形参1,形参2...形参N){
...
}
var fun2 = function() {
console.log("我是匿名函数中封装的代码");
};
构造函数
使用构造函数new Function()
来创建一个对象,用的少。
var 变量名/函数名 = new Function('形参1', '形参2', '函数体');
var fun3 = new Function('a', 'b', 'console.log("我是函数内部的内容"); console.log(a + b);');
fun3(1, 2); // 调用函数
函数参数
- 隐藏实现
- 不会污染外部(全局)变量空间:函数执行完后变量会销毁
- 可以用来编写js模块
- JavaScript 函数对参数的值没有进行任何的检查。
- 函数参数分为显式参数和隐式参数
显式参数
functionName(parameter1, parameter2, parameter3){// 要执行的代码……}
函数显式参数在函数定义时列出。
默认参数
ES5 中如果函数在调用时未提供隐式参数,参数会默认设置为: undefined
有时这是可以接受的,但是建议最好为参数设置一个默认值
如果函数调用时设置了过多的参数,参数将无法被引用,因为无法找到对应的参数名。 只能使用 arguments 对象来调用。
自带默认带参数
ES6 支持函数带有默认参数,就判断 undefined 和 || 的操作:
function myFunction(x, y = 10) {
return x + y;
}
myFunction(0, 2) // 输出 2
myFunction(5); // 输出 15, y 参数的默认值
隐式参数
函数隐式参数在函数调用时传递给函数真正的值。
通过值传递参数
函数仅仅只是获取值。
如果函数修改参数的值,不会修改显式参数的初始值(在函数外定义)。
隐式参数的改变在函数外是不可见的。
通过对象传递参数
在函数内部修改对象的属性就会修改其初始的值。
修改对象属性可作用于函数外部(全局变量)。
修改对象属性在函数外是可见的。
实参与形参
在 JS 中,形参的默认值是 undefined。
函数作用域
- 作用域是一个变量或函数的作用范围。作用域在函数定义时,就已经确定了。
- 为了提高程序的可靠性,同时减少命名冲突。
分类(ES6以前)
全局作用域
作用于整个 script 标签内部,或者作用域一个独立的 JS 文件。
直接编写在script标签中的JS代码,都在全局作用域。
- 全局作用域在页面打开时创建,在页面关闭时销毁。
- 在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口,由浏览器创建,我们可以直接使用。
在全局作用域中:
- 创建的变量都会作为window对象的属性保存。比如在全局作用域内写
var a = 100
,这里的a
等价于window.a
。 - 创建的函数都会作为window对象的方法保存。
全局变量
- 在全局作用域下声明的变量,叫「全局变量」。在全局作用域的任何一地方,都可以访问这个变量。
- 在全局作用域下,使用 var 声明的变量是全局变量。
- 特殊情况:在函数内不使用 var 声明的变量也是全局变量(不建议这么用)。
- 当函数没有被自身的对象调用时 this 的值就会变成全局对象。
- 在 web 浏览器中全局对象是浏览器窗口(window 对象)。
- 该实例返回 this 的值是 window 对象:
- 函数作为全局对象调用,会使 this 的值成为全局对象。
- 使用 window 对象作为一个变量容易造成程序崩溃。
函数作用域(局部作用域)
作用于函数内的代码环境。(外部无法访问内部变量)
局部变量
- 定义在函数作用域的变量,叫「局部变量」。
- 在函数内部,使用 var 声明的变量是局部变量。
- 函数的形参也是属于局部变量。
全局变量和局部变量的对比
从执行效率来看全局变量和局部变量:
- 全局变量:只有浏览器关闭时才会被销毁,比较占内存。
- 局部变量:当其所在的代码块运行结束后,就会被销毁,比较节约内存空间。
就近原则
当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用。如果没有则向上一级作用域中寻找,直到找到全局作用域;如果全局作用域中依然没有找到,则会报错 ReferenceError。
在函数中要访问全局变量可以使用window对象。(比如说,全局作用域和函数作用域都定义了变量a,如果想访问全局变量,可以使用window.a)
作用域链
内部函数访问外部函数的变量,采用的是链式查找的方式来决定取哪个值,这种结构称之为作用域链。查找时,采用的是就近原则。
function fn() {
// 外部函数
function fun() {
// 内部函数
}
fun();
}
fn();//20
函数调用
- 直接调用:
函数名();
,在body中之间调用的等同于windows.函数名();
- 通过对象方法:
obj.函数名():
- call、apply方法调用:临时让fn成为obj的方法,相当于
obj.函数名()
,只是此时obj身上不一定有该函数,函数名.call(obj);
- 通过构造函数new调用:不常用,
new 函数名()
- 立即执行函数(自调用函数)调用:实际上是一个匿名自我调用的函数 (没有函数名)。
(function(){})();
立即执行函数往往只会执行一,因为没有变量保存它,执行完了之后,就找不到它了。 - 绑定事件函数调用:
btn.onclick = function(){};
- 定时器函数调用:
setInterval(function(){},time)
- JavaScript 函数有 4 种调用方式。
函数提升(Hoisting)
函数可以在声明之前调用
当 JavaScript 准备 运行脚本时,首先会在脚本中寻找全局函数声明,并创建这些函数。我们可以将其视为“初始化阶段”。
在处理完所有函数声明后,代码才被执行。所以运行时能够使用这些函数。
函数提升优于变量提升
函数返回值
- 如果return语句后不跟任何值,就相当于返回一个undefined
- return 只能返回一个值。如果用逗号隔开多个值,则以最后一个为准。
函数命名习惯
函数以 XX 开始……
- “show…” —— 显示某些内容,
- “get…” —— 返回一个值,
- “calc…” —— 计算某些内容,
- “create…” —— 创建某些内容,
- “check…” —— 检查某些内容并返回 boolean 值,等。
- “is…” —— 是否是某个内容,
函数可作为一个值使用
JavaScript 函数可作为表达式使用:
function myFunction(a, b) {
return a * b;
}
var x = myFunction(4, 3) * 2;
fn() 和 fn 的区别【重要】
- fn():调用函数。调用之后,还获取了函数的返回值。
- fn:函数对象。相当于直接获取了整个函数对象。