1.匿名函数
在JavaScript中,匿名函数是指没有名称的函数。它通常用于用作回调函数或立即调用函数表达式(IIFE)等场景。
示例1:定义匿名函数
var add = function(a, b) {
return a + b;
};
// 调用匿名函数
console.log(add(2, 3)); // 输出 5
示例2:立即调用函数表达式
(function() {
// 这里是函数体
})();
在这里,我们定义了一个函数并立即调用它,即使函数没有名称,它仍然可以执行其所需的操作。
总之,匿名函数是 JavaScript 中的常见编程模式,它允许我们在不污染全局命名空间的情况下定义和使用函数。
2.自调用函数
自调用函数是JavaScript中的一种特殊函数形式,也称为立即调用函数表达式(Immediately Invoked Function Expression,IIFE)。它是一个匿名函数,可以在定义时直接自动执行,不需要手动调用。
自调用函数的语法形式如下:
(function() {
// 函数体
})();
其中,匿名函数被圆括号包裹起来,紧接着又跟上一个空的圆括号,这样就创建了一个立即执行的函数。如果我们需要在函数内部传入参数,可以在定义函数时给它传入参数:
(function(x, y) {
console.log(x + y);
})(2, 3); // 输出5
自调用函数适用于需要在定义时就立即执行而不保存函数引用的场合。它可以被用于命名空间以及防止变量污染等编程模式中。
3.箭头函数
JS箭头函数(Arrow Functions)是一种简写函数表达式的语法形式。它的语法形式如下:
(argument1, argument2, …, argumentN) => {
// 函数体
}
箭头函数的特点如下:
-
简写语法:省略了function关键字,使用箭头“=>”来代替。
-
省略return关键字:如果函数体只有一行语句,则可以省略花括号和return关键字,直接返回这一行语句的结果。
-
this绑定:箭头函数中的“this”指向的是定义时所在的对象,而不是调用时的对象。
示例:
// 传统函数声明
function foo(x, y) {
return x + y;
}
// 箭头函数
const bar = (x, y) => {
return x + y;
}
// 简写语法
const baz = (x, y) => x + y;
// this绑定的示例
const person = {
name: 'Alice',
sayHello: function() {
console.log(`Hello, my name is ${this.name}`);
},
sayBye: () => {
console.log(`Bye, my name is ${this.name}`);
}
}
person.sayHello(); // 输出:Hello, my name is Alice
person.sayBye(); // 输出:Bye, my name is undefined
注意:箭头函数不能用作构造函数,因为它们没有自己的this关键字。
4.递归函数
递归函数是指在函数中调用自己本身的过程。在 JavaScript 中,递归函数可以用来解决一些复杂的问题,特别是在处理数据结构时。
以下是一个简单的递归函数例子,用来计算一个数的阶乘:
function factorial(n) {
if (n === 0) {
return 1; // 0 的阶乘为 1
} else {
return n * factorial(n - 1); // 递归调用自身
}
}
console.log(factorial(5)); // 输出 120
在这个例子中,当输入参数为 0 时,函数返回 1,否则函数返回输入参数与调用该函数传入参数为输入参数减 1 的递归结果的乘积。随着输入参数不断减少,最终递归会到达输入参数为 0 的情况,从而函数得以停止递归。
需要注意的是,在使用递归时,必须要保证递归函数能够停止,否则会导致无限递归,最终导致浏览器崩溃。
5.回调函数
JavaScript回调函数是一种在另外一个函数执行完成后执行的函数。回调函数通常作为另外一个函数的参数传递进去,然后在该函数执行完后被调用。回调函数通常用于异步操作,例如获取数据、处理数据等等,因为这些操作需要时间来完成,而JavaScript是单线程的,不能使用阻塞调用。
例如,在一个页面中,有一个按钮可以触发一个异步操作,当操作完成后,需要执行一些操作。在这种情况下,可以将需要执行的操作封装到一个回调函数中,并将该回调函数作为参数传递给异步操作,异步操作完成后就可以执行该回调函数。
下面是一个例子:
function operateAsync(callback) {
setTimeout(function() {
console.log("异步操作完成");
callback();
}, 2000);
}
function callback() {
console.log("回调函数被调用");
}
operateAsync(callback);
在这个例子中,operateAsync
是一个模拟的异步操作,它接受一个回调函数作为参数,等操作完成后,调用该回调函数。callback
就是这个回调函数,在异步操作完成后,会被调用。
输出结果如下:
异步操作完成
回调函数被调用
可以看到,异步操作完成后,回调函数被成功调用了。
6.嵌套函数
JS嵌套函数指在一个函数内部定义一个或多个函数。这些内部函数可以被外部函数调用,也可以在内部函数内部再次定义其它函数。
例如:
function outer() {
console.log('outer function');
function inner1() {
console.log('inner1 function');
}
function inner2() {
console.log('inner2 function');
}
inner1();
inner2();
}
// 调用外部函数
outer();
上面的代码中,定义了一个外部函数outer(),在其中定义了两个内部函数inner1()和inner2()。在outer()被调用时,内部函数inner1()和inner2()也被调用。内部函数可以访问外部函数的变量和参数,而外部函数不能访问内部函数的变量。
通过嵌套函数,可以有效地组织代码,并使代码更易于阅读和维护。
7.构造函数
构造函数是一种特殊类型的函数,它用于创建类或对象的实例。在 JavaScript 中,构造函数通常使用大写字母开头的函数名表示。构造函数通过 new
关键字来调用,创建一个新的对象,并将构造函数作为对象的方法来调用。
构造函数通常会在内部使用 this
关键字来定义对象的属性和方法。当构造函数被调用时,会为对象分配内存空间,并将对象的属性和方法赋值给 this
对象。最后,构造函数会返回这个对象,使得我们可以通过这个对象来访问其属性和方法。
以下是一个简单的例子,展示了如何使用构造函数来创建一个属于 Person
类的对象:
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.greeting = function() {
console.log('Hi, my name is ' + this.name + ' and I am ' + this.age + ' years old.');
};
}
var person1 = new Person('Alice', 25, 'female');
var person2 = new Person('Bob', 30, 'male');
person1.greeting(); // 输出:Hi, my name is Alice and I am 25 years old.
person2.greeting(); // 输出:Hi, my name is Bob and I am 30 years old.
在上面的例子中,Person
构造函数定义了一个 Person
类,它具有 name
、age
、gender
三个属性和 greeting
方法,用于输出一段问候语。我们使用 new
关键字调用 Person
构造函数来创建了两个 Person
对象 person1
和 person2
,并分别调用了它们的 greeting
方法输出问候语。
8.闭包
闭包(closure)是指函数内部能够访问到外部作用域的变量,即使外部作用域已经结束。在 JavaScript 中,函数和它所处的词法环境即使在函数被返回(return)后也不会被销毁,因此它可以继续访问它需要的变量。
闭包的常见用途包括:
-
保护变量不被外界修改;
-
实现函数记忆(函数缓存);
-
在模块化开发中实现私有变量和方法;
-
延长变量的生命周期等。
例如,以下代码展示了闭包的基本用法:
function outerFunction() {
let counter = 0;
function innerFunction() {
counter++;
console.log(counter);
}
return innerFunction;
}
let increment = outerFunction();
increment(); // 输出 1
increment(); // 输出 2
increment(); // 输出 3
在这个例子中,函数 innerFunction()
可以访问外部函数 outerFunction()
中的变量 counter
,并且它会在每次调用 innerFunction()
时自增并输出自己的值。函数 outerFunction()
返回 innerFunction()
,并将其赋值给变量 increment
,因此我们可以在全局作用域中调用它,并且每次调用 increment()
都会让 counter
自增并输出新的值。这就是一个简单的闭包实现。