文章目录
什么是函数
预先定义好内容并可以在特定时机执行的一段代码。
对象的键也可以对应一个函数。此时这个函数一般叫方法。
函数的4种定义方式
具名函数
也称显式函数。语法:
function 函数名(形参1, 形参2, ...){语句}
function add(a,b){
return a+b
}
显式函数赋给变量,通过变量调用不会出错但是通过函数名调用时会报错。
//显式函数赋给变量,通过变量调用不会出错但是通过函数名调用时会报错。
let a = function add(a,b){
return a+b
}
a(1,2) //3
add(1,2) //报错,add未被定义。
匿名函数
也称函数表达式。将函数赋给一个变量,函数本身没有自己的名字。
let a = function(a,b){
return a+b
}
[ES6]箭头函数
ES6提供的简化函数写法的方式。
语法:
(参数1,...) => {语句}
如果函数的参数只有1个,小括号可以省略。
如果函数只有1句执行语句,且该语句执行后返回一个非对象字面量,大括号可以省略,以该值作为返回值。
let a = (a,b) => a + b
如果只有1句语句,且该语句执行后返回一个对象字面量,需要在该对象上加上小括号。
let a = (a,b) => ({
"1":a, "2":b})
Function()构建
语法:
Function("形参1", "形参2", ..., "语句")
形参和语句都必须加上引号。
基本没什么用。可以提醒我们所有函数都是Function
函数构造的。
let a = Function('a','b','return a+b')
调用函数
如何调用函数
JS中的函数写好之后不会立即执行(除非是立即执行函数),只有在调用时才会执行。
调用函数的方法很简单,语法是显式函数的名字(参数1,...)
或匿名函数对应的变量(参数1,...)
。
即使一个函数不需要参数,调用时括号也是必不可少。如果不写括号,使用的是函数的内存地址。
function sayHi(){
console.log("Hello!")
}
sayHi //ƒ sayHi(){console.log("Hello!")}
sayHi() //Hello!
形参和实参
函数声明时写的参数叫做形参,调用函数时传过来的参数叫实参。
//a和b是形参
function add(a,b){
console.log(arguments)
}
//1和2是实参
add(1,2)
调用时,实参会一一复制给形参(还是浅拷贝),于是形参就可以在函数内部使用了。
//假设调用了add(1,2)
function add(a,b){
//偷偷执行了let a = 1, let b = 2
console.log(a, b) //1 2
}
实参可多可少
实参可以比形参多,多余的参数被忽略。
实参可以比形参少,没有实参的形参自动赋值undefined
。
function add(a,b){
console.log(a,b)
}
add(1,2,3) // 1 2
add(1)// 1 undefined
获取实参
每个函数在调用时生成一个arguments
对象,包含了本次调用传来的参数,可以在函数内部访问。无论实参比形参多还是少,传来几个参数就获得几个参数。
arguments
是一个伪数组。
function add(a,b){
console.log(arguments)
}
add(1,2)
/*
Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]
0: 1
1: 2
callee: ƒ add(a,b)
length: 2
Symbol(Symbol.iterator): ƒ values()
__proto__: Object
*/
函数的参数可以是另一个函数
之前提到数组有一个遍历方法forEach
。
它接受一个函数,这个函数有2个参数,分别表示元素和下标。
let a = [1,2,3]
a.forEach((item, index)=>{
console.log(`${
index}: ${
item}`)})
/*
0: 1
1: 2
2: 3
*/
问题来了,为什么这个函数的参数分别能表示元素和下标?为什么顺序不是先下标后元素?
为了理解这个问题,我们自己实现一个myEach
的方法模拟它:
//把该方法挂载到数组的原型上
Array.prototype.myEach = function(fn){
//this默认指向该数组
for(let i = 0; i < this.length; i++){
//调用时还需要把数组本身传进去,特殊情况下有用。
//函数中的函数
//关键就在这里,这个函数里的前2个参数便是元素和下标。
fn(this[i],i,this)
}
}
let a = [1,2,3]
a.myEach((item, index)=>{
console.log(`${
index}: ${
item}`)})
函数的返回值
所有函数都有返回值。想让一个函数返回一个指定的值的语法是return 表达式
。如果不写,默认返回undefined
。例如console.log("2")
也有返回值undefined
,打印出2不过是中间的一个步骤。
表达式1+2
不是函数,因此它有值,没有返回值。只有函数有返回值。
函数的调用时机
同一个函数在不同的位置调用,效果(很)可能不一样。
let a =