文章目录
前言
函数实际上就是一个对象,每一个函数都是Function的一个实例,而Function也有属性和方法,跟其他引用型类型一样。
一、创建函数
1、函数的声明方式定义
注意:此方法会函数声明提升
function fun() {
console.log('函数声明的方式定义');
}
2、函数表达式
const sum = function(a, b){
return a + b
}
3、箭头函数(跟函数表达式很像)
const sum = (a, b) => {
return a + b
}
4、Function构造函数定义(不推荐使用)
let sum = new Function("num1", "num2", "return num1 + num2")
二、理解JS函数
1、js的函数没有重载一说
2、理解参数
ECMAScript函数的参数跟大多数其他语言不同。ECMAScript函数既不关心传入的参数个数,也不关心这些参数的数据类型。定义函数时要接收两个参数,并不意味着调用时就传两个参数。你可以传一个、三个,甚至一个也不传,解释器都不会报错。
之所以会这样,主要是因为ECMAScript函数的参数在内部表现为一个数组。函数被调用时总会接收一个数组,但函数并不关心这个数组中包含什么。如果数组中什么也没有,那没问题;如果数组的元素超出了要求,那也没问题。事实上,在使用function关键字定义(非箭头)函数时,可以在函数内部访问arguments对象,从中取得传进来的每个参数值。
arguments对象是一个类数组对象(但不是Array的实例),因此可以使用中括号语法访问其中的元素(第一个参数是arguments[0],第二个参数是arguments[1])。而要确定传进来多少个参数,可以访问arguments.length属性。
函数参数定义,但调用函数时未传参数时,参数时undefined。
const sum = function(a, b){
console.log(a,b);//undefined undefined
return a + b
}
es6以后支持显示定义默认参数。
const sum = function(a = 1, b = 1){
console.log(a,b);//1 1
return a + b
}
console.log(sum()); //2
当没有传入参数时,一默认参数为准,传入的参数从第一项开始覆盖默认参数。
函数的默认参数只有在函数调用时才会求值,不会再函数定义时求值。
3、函数内部
es6以后函数内部存在两个特殊对象:arguments、this和一个new.target属性
arguments是一个包含调用函数时传入的所有参数的类数组对象(不包含默认参数,并且不会在修改参数时发生改变)。
arguments.callee是一个指向正在执行的函数的指针。通常在函数递归时使用。
this:this是把函数当成方法调用的上下文对象。
new.target :判断函数是否被当成构造函数使用。
4、递归
递归函数通常就是自己调用自己
代码如下(示例):求整数累加和
function factorial(num) {
if (num <= 1) return 1
else {
return num + factorial(num - 1)
// 配合使用arguments.callee
return num + arguments.callee(num - 1)
}
}
let sum = factorial(100);
console.log(sum); //5050
5、箭头函数
箭头函不能用作构造函数,在内部也不能使用arguments、super、new.target
6、立即调用的函数表达式(IIFE)
(function(){
let sum = 0
for(let i = 1;i <= 100; i++){
sum += i
}
console.log(sum);//输出5050
})()
7、闭包
闭包指的是哪些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的。
优点:
1.可以让一个变量长期在内存中不被释放
2.避免全局变量的污染,和全局变量不同,闭包中的变量无法被外部使用
3.私有成员的存在,无法被外部调用,只能直接内部调用
闭包可以完成的功能:1.防抖、2.节流、3.函数柯里化