函数是什么
JavaScript函数是指一个特定代码块,可能包含多条语句,可以通过名字来供其它语句调用以执行。
函数名:动宾结构,驼峰写法
声明函数
ECMAScript规定了三种声明函数方式
- 构造函数(不推荐使用)
函数也是对象的一种,我们可以通过其构造函数,使用new来创建一个函数对象
var sayHello = new Function("console.log('hello world');");
- 函数声明
使用function关键字可以声明一个函数
//函数声明
function sayHello(){
console.log('hello')
}
//函数调用
sayHello()
声明不必放到调用的前面(但不要放在其他函数里面)
- 函数表达式(看作赋值过程)
var sayHello = function(){
console.log('hello');
}
sayHello()
声明必须放到调用的前面
多个参数
function printInfo(name, age, sex){
console.log(name);
console.log(age);
console.log(sex);
console.log(arguments);
//在函数内部,你可以使用arguments对象获取到该函数的所有传入参数
//arguments是类数组对象。可以通过下标的方式arguments[]获取到对应的传入参数,还有length属性,但它本身不是数组,没有数组的一些特性
}
printInfo('饥人谷', 2, 'boy') //函数调用时实参和形参是一一对应的
JS 没有重载,如何实现重载功能
在其他语言中,通过重载实现相同的函数名,输入不同类型的实参,去调用不同类型的形参。
**在 JS 中没有重载! 同名函数会覆盖。 **
但可以在函数体针对不同的参数调用执行相应的逻辑
function printPeopleInfo(name, age, sex){
if(name){
console.log(name);
}
if(age){
console.log(age);
}
if(sex){
console.log(sex);
}
}
printPeopleInfo('Byron', 26);
printPeopleInfo('Byron', 26, 'male');
返回值
有时候我们希望在函数执行后得到一个结果供别人使用,可以通过return来实现
function sum(a, b){
a++;
b++;
return a + b;
}
var result = sum(2, 3);
console.log(result);
返回值的注意点
1.如果不写return语句,函数也会默认给我们返回undefined
2.函数在执行过程中,只要遇到return就会立即结束退出函数体
function fn(a){
if(a < 0){
return;
}
//下面没用 else ,但效果一样
a++;
return a + a;
}
3.函数的返回值和 console.log()是两个不同的东西,千万不要这样
function getAge(age){
return console.log(age);//错误的写法,console.log()作为一个函数,整体的结果永远都是undefined ,表示在控制台输出
}
声明前置
var 和 function 的声明前置(变量提升、函数提升)
在一个作用域下,var 声明的变量和function 声明的函数会前置
console.log(a); //实际上的执行顺序是var a ;
var a = 3; //function sayHello(){
console.log(a); //console.log('hello'); undefined
//}
sayHello(); //console.log(a); 3
//a = 3;
function sayHello(){ //sayHello(); hello
console.log('hello');
}
而写成函数字面量式,则没有function前置
console.log(fn); //undefined //实际上的执行顺序是var fn ;
fn(); //报错 //console.log(fn); 输出fn就是undefined
// fn(); 将undefined 作为一个函数去执行,自然会报错
var fn = function(){}
var XXX =函数表达式 和 var 一个变量没什么区别
故必须遵循先有,再用的思想
函数内部的声明前置(函数内部变量提升)
function fn(){
console.log(a) //undefined //在函数内部,先声明前置var a ;
var a = 3 //console.log(a);
console.log(a) //a = 3;
} // console.log(a);
fn()
当命名冲突时
遵循“先 前置,再 覆盖”的思想
var fn = 3; //执行顺序:var fn;
function fn(){} // function fn(){} 此时fn值为函数
// fn=3
console.log(fn); // 3 //console.log(fn); 输出就是3
function fn(){} //执行顺序: function fn(){}
var fn = 3; // var fn; 如果之前已经声明了,此处没有又没有赋值,只会保持不变,还是function fn(){}
// fn=3
console.log(fn); // 3 //console.log(fn); 输出就是3
参数重名
function fn(fn){ //执行顺序:
console.log(fn); // function fn(10){
// /*var fn =10 传递实参进函数,隐藏步骤*/
var fn = 3; //var fn;
console.log(fn); //console.log(fn); 输出10
} //fn = 3;
// console.log(fn); 输出3
fn(10); //10 3 //}
作用域
在 JS 中只有函数作用域,没有块作用域
function fn(){
var a =1;
if(a > 2){
var b = 3;
}
console.log(b);
}
fn(); // undefined
console.log(a); // "ReferenceError: a is not defined
var重复声明一个已经存在的变量,原变量值不变
function fn(){}
var fn
console.log(fn) //fn还是函数 ,结果是输出function fn(){}
var a = 1
var a
var a
console.log(a) //输出1
不写var会声明一个全局的变量
这是我们在编程中应该要避免的,即使真的需要全局变量,也应该在最外层作用域使用var声明
function fn(){
a = 1;
}
fn();
console.log(a); //
递归
1.自己调用自己
2.设定终止条件
3.优点: 算法简单
4.缺点: 效率低
求 n 的阶乘 n!
function factor(n){
if(n === 1) {
return 1
}
return n * factor(n-1)
}
factor(5)
立即执行函数表达式
作用:隔离作用域
(function(){
var a = 1; //a
})()
console.log(a); //undefined
立即执行函数表达式的其他写法
(function fn1() {});
// 在数组初始化器内只能是表达式
[function fn2() {}];
// 逗号也只能操作表达式
1, function fn3() {};