★在JavaScript中定义一个函数有四种方式
①函数声明
②函数表达式
③ES6里箭头函数
④new Function()
㈠什么是函数声明( Function Declaration)?
⑴Function Declaration 可以定义命名的函数变量,而无需给变量赋值。Function Declaration 是一种独立的结构,不能嵌套在非功能模块中。可以将它类比为 Variable Declaration(变量声明)。就像 Variable Declaration 必须以“var”开头一样,Function Declaration 必须以“function”开头。
⑵语法:
function 函数名(参数){
要执行的代码(函数体)
}
⑶调用:
①函数名(参数)
②函数名.call(函数名,参数)
③函数名.apply(函数名,[参数])
④new 函数名(参数)
⑤定时器
⑥把函数声明变成函数表达式再调用
⑦ES6里的模版字符串
㈡什么是函数表达式(Function Expression)?
⑴Function Expression 将函数定义为表达式语句(通常是变量赋值)的一部分。通过 Function Expression 定义的函数可以是命名的,也可以是匿名的。Function Expression 不能以“function”开头。
⑵语法:
var/let/const 变量=function(参数){
要执行的代码(函数体)
}
⑶调用:
①函数名(参数)
②函数名.call(函数名,参数)
③函数名.apply(函数名,[参数])
④new 函数名(参数)
⑤直接在后面加上一对小括号
⑥定时器
⑦ES6里的模版字符串
⑧以被赋值的形式出现(根据具体形式调用)
㈢函数声明与函数表达式的区别
⑴以函数声明的方法定义的函数,函数名是必须的,而函数表达式的函数名是可选的。
(函数声明整体会被提升到当前作用域的顶部,函数表达式也提升到顶部但是只有其变量名提升)
⑵以函数声明的方法定义的函数,函数可以在函数声明之前调用,而函数表达式的函数只能在声明之后调用。
⑶以函数声明的方法定义的函数并不是真正的声明,它们仅仅可以出现在全局中,或者嵌套在其他的函数中,但是它们不能出现在循环,条件或者try/catch/finally中,而函数表达式可以在任何地方声明。换句话说,函数声明不是一个完整的语句,所以不能出现在if-else,for循环,finally,try catch语句以及with语句中。
⑷函数声明必须带有标识符(函数名称),函数表达式则可以省略
- 表达式里的名字不能在函数外面用,只能在函数内部用
- 函数有一个name属性,指向紧跟在function关键字之后的那个函数名。如果函数表达式没有名字,那name属性指向变量名
⑸JS程序在正式执行之前,会将所有var声明的变量和function声明的函数,预读到所在作用域的顶部,var声明只是将声明提前,赋值仍然保留在原位置,function声明,会将函数名称和函数体都提前,这个过程也被叫做“预解析”或者“预编译”。函数声明会被预解析,函数表达式不会。
★示例:
//1、名字
//函数声明必需带名字
function fn(){};
//function(){}; //报错,没有名字
//函数表达式可以没有名字
let fn1=function(){};
(function(){});
!function(){};
//表达式名字的作用
let fn2=function newFn(){
console.log(newFn); //可以在这里面用。有一个作用就是在这里用递归
};
fn2();
//newFn(); //报错,不能在外面用
//name属性
console.log(
fn.name, //fn
fn1.name, //fn1 表达式没有名字,name属性指向表达式变量名
fn2.name //newFn
);
//2、预解析
fn3();
function fn3(){
console.log('fn3');
}
//fn4(); //报错,不会被预解析
let fn4=function(){
console.log('fn4');
}
㈣函数声明不能直接调用的原因
⑴小括号里只能放表达式,不能放语句。
⑵function关键字即可以当作语句,也可以当作表达式。但js规定function关键字出现在行首,一律解释成语句
⑶解决方法:不要让function出现在行首
①用括号把function主体括起来,转成表达式。后面加括号运行
②借助运算符(new + - ! ~ typeof , && ||...)
因为运算符会把表达式执行,执行后得出结果了才能运算