闭包 & 立即执行函数
https://blog.csdn.net/m0_66706006/article/details/132124323
立即执行函数,闭包函数_立即执行函数闭包
//立即执行函数的两种写法
//第一种:用括号把整个函数定义和调用包裹起来
(function(){
//function body
}())
//第二种:用括号把函数定义包裹起来,后面再加括号
(function (){
//function body
})()
//立即执行函数的参数
// 如果立即执行函数中需要全局变量,全局变量会被作为一个参数传递给立即执行函数
//(下例中的i就是一个全局变量,i代表的是实参,j是i在立即执行函数中的形参)。
(function(j){
//代码中可以使用j
})(i)闭包的概念
闭包就是能够读取其他函数内部变量的函数。
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
闭包的用途
闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
当想访问函数内部的变量时,或想把函数内部的变量抛到外面,就需要用到闭包的写法。
父函数将子函数作为返回值,再将子函数赋值给一个变量。所以子函数会存在于内存中,而子函数依赖于父函数的存在,所以父函数也会存在于内存中。也就不会被垃圾回收机制回收。
闭包的写法(用法)
在主函数function内部,定义闭包function函数。但是执行调用还是在外面的,即通过return才能调用执行
function funOne()
var num=0
function funTwo(){
num++
return num
}
return funTwo
}
var fun=funOne()6. 闭包与匿名函数结合(用法)
var funOne=(function(){
var num=0
return function(){
num++
return num
}
})()闭包和立即执行函数的区别
闭包(Closure)和立即执行函数(Immediately Invoked Function Expression,IIFE)是 JavaScript 中两个不同的概念,但它们之间存在联系。下面是它们的区别和联系:
闭包
定义:闭包是指一个函数能够记住并访问其创建时的词法作用域,即使该函数在其原始作用域之外被调用。
用途:闭包主要用于数据封装、创建私有变量、实现模块模式、柯里化函数等。
行为:闭包允许函数访问和操作外部作用域中的变量,即使外部函数已经执行完毕。
示例:
function createClosure() {
let secret = "I'm a secret!";
return function() {
console.log(secret);
};
}
const myClosure = createClosure();
myClosure(); // 访问外部作用域的变量立即执行函数
定义:IIFE 是一种在定义后立即执行的函数表达式。
用途:IIFE 主要用于创建局部作用域、避免全局变量污染、执行自执行代码块等。
行为:IIFE 执行后会立即完成其功能,通常不保留状态或在执行后继续存在。
示例:
(function() {
console.log('This will be executed immediately.');
})();联系
局部作用域:IIFE 和闭包都可以创建局部作用域,避免变量污染。
匿名函数:IIFE 通常是一个匿名函数表达式,而闭包可以是匿名或具名函数。
执行时机:IIFE 在定义后立即执行,而闭包可以在定义后随时调用,不一定立即执行。
区别
状态保持:闭包可以保持状态,因为它可以访问外部作用域的变量;IIFE 执行完毕后通常不会保留状态。
重复使用:闭包可以被多次调用,每次调用都可以访问其创建时的作用域;IIFE 执行一次后,其作用域和状态就不存在了。
目的:闭包主要用于利用作用域链的特性,而 IIFE 主要用于立即执行代码块,避免污染全局作用域。
总结来说,闭包是一种特性,它允许函数访问创建时的作用域;而 IIFE 是一种模式,它是一种立即执行的函数表达式,通常用于创建局部作用域。两者在 JavaScript 编程中都非常有用,但它们的应用场景和目的不同。
闭包和立即执行函数 带参
当然,我可以给出闭包和立即执行函数(IIFE)带参数的例子。
闭包带参数的例子:
闭包通常用于封装私有变量和函数,下面是一个带参数的闭包的例子,其中参数用于配置闭包的行为:
function createClosure(msg) {
let secretMessage = msg; // 闭包可以访问这个变量
return function() {
console.log(secretMessage);
};
}
// 创建一个闭包实例,传入参数 "Hello, Closure!"
const myClosure = createClosure("Hello, Closure!");
// 调用闭包函数,输出传递给 createClosure 的参数
myClosure(); // 输出: Hello, Closure!在这个例子中,createClosure 函数接收一个参数 msg,并在内部创建了一个闭包函数。这个闭包函数可以访问 createClosure 函数的局部变量 secretMessage。
立即执行函数带参数的例子:
IIFE 可以接收参数,并且立即执行这些参数:
(function(msg) {
console.log('IIFE with parameter:', msg);
})('Hello, IIFE!');
// 带多个参数的 IIFE
(function(name, age) {
console.log('Name:', name, 'Age:', age);
})('Alice', 30);在这个例子中,第一个 IIFE 接收一个参数 msg 并立即执行,打印出这个参数。第二个 IIFE 接收两个参数 name 和 age,同样立即执行并打印这些参数。
IIFE 带参数的用法非常适合于配置函数或工厂函数的场景,其中参数用于定制函数的行为或返回值。
闭包
闭包(Closure)是 JavaScript 中一个非常重要的特性,它指的是一个函数能够记住并访问其创建时的词法作用域,即使这个函数在其原始作用域之外被执行。简单来说,闭包允许函数访问创建时的作用域中的变量,即便函数在其原始作用域之外被调用。
以下是闭包的一些关键点:
词法作用域:在 JavaScript 中,函数可以访问它们在定义时所在的作用域中的变量,而不仅仅是调用时所在的作用域。
数据封装:闭包可以用来封装数据,使得外部代码不能直接访问这些数据,而是通过函数间接访问。
记忆功能:闭包可以“记住”每次调用时的状态,因为它们可以访问外部函数的变量。
延迟计算:闭包可以用来实现延迟计算或异步操作。
高阶函数:函数可以作为另一个函数的参数或返回值,这是闭包的一个重要应用。
下面是一个简单的闭包示例:
function createClosure() {
let secret = "I'm a secret!";
return function() {
console.log(secret);
};
}
const myClosure = createClosure();
myClosure(); // 输出: I'm a secret!在这个例子中,createClosure 函数创建了一个闭包,这个闭包可以访问 createClosure 函数内的变量 secret。即使 createClosure 函数执行完毕后,闭包仍然可以访问 secret。
闭包在 JavaScript 中有着广泛的应用,包括但不限于模块模式、事件处理器、异步编程等。理解闭包对于编写高效、可维护的 JavaScript 代码非常重要。
使用案例
闭包的使用案例非常广泛,以下是一些常见的例子:
- 数据私有化:
通过闭包,可以在函数内部创建私有变量,这些变量不能被外部直接访问,只能通过内部函数间接访问。
function createCounter() {
let count = 0;
return {
increment: function() { count++; },
decrement: function() { count--; },
value: function() { return count; }
};
}
const counter = createCounter();
console.log(counter.value()); // 0
counter.increment();
console.log(counter.value()); // 1- 模块模式:
使用闭包实现模块模式,可以封装变量和功能,防止全局命名冲突。
const myModule = (function() {
let privateVar = 'I am private';
return {
publicMethod: function() {
console.log(privateVar);
}
};
})();
myModule.publicMethod(); // 'I am private'
// privateVar is not accessible here- 函数工厂:
创建返回函数的函数,这些返回的函数可以记住创建时的状态。
function makeAdder(x) {
return function(y) {
return x + y;
};
}
const add5 = makeAdder(5);
console.log(add5(3)); // 8- 柯里化(Currying):
将一个多参数的函数转换成多个单参数的函数,每个单参数函数返回下一个参数的函数。
function curriedAdd(a) {
return function(b) {
return a + b;
};
}
const add10 = curriedAdd(10);
console.log(add10(5)); // 15- 事件处理器:
使用闭包可以持久化事件处理器的状态,即使在多次事件触发之间。
document.addEventListener('click', function() {
console.log('Button was clicked!');
});
// 每次点击都会打印消息,闭包保持了事件监听器的状态- 异步编程:
闭包在异步编程中非常有用,可以保持异步函数的状态。
async function fetchData(url) {
return new Promise(resolve => {
setTimeout(() => {
resolve('Data from ' + url);
}, 1000);
});
}
fetchData('https://api.example.com/data')
.then(data => console.log(data)); // 保持了异步操作的状态- 节流(Throttling)和防抖(Debouncing):
闭包可以用来实现节流和防抖函数,控制函数执行的频率。
// 节流示例
function throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
}闭包是 JavaScript 中非常强大的特性,它提供了一种方式来创建具有持久状态的函数,这在很多编程场景中都非常有用。
立即执行匿名函数 和 闭包的使用
立即执行匿名函数(Immediately Invoked Function Expression,简称 IIFE)是一种在定义后立即执行的匿名函数表达式。这种模式在 JavaScript 中非常常见,主要用于创建局部作用域,避免污染全局命名空间,以及执行自执行代码块。
IIFE 有几种不同的形式,以下是一些常见的示例:
基本形式
(function() {
console.log('This will be executed immediately.');
})();这个函数被定义后立即执行,输出 "This will be executed immediately."。
带参数的形式
(function(param) {
console.log('Immediate execution with parameter:', param);
})('Hello World');这个 IIFE 接受一个参数,并在执行时传递了 'Hello World'。
使用闭包
(function() {
let secret = 'I am a secret!';
this.revealSecret = function() {
console.log(secret);
};
})();
revealSecret(); // 输出: I am a secret!这个 IIFE 创建了一个闭包,并且向全局对象添加了一个 revealSecret 函数,用于访问 IIFE 的内部变量 secret。
使用在模块模式
const myModule = (function() {
let privateVar = 'I am private';
return {
publicMethod: function() {
console.log(privateVar);
}
};
})();
myModule.publicMethod(); // 输出: I am private这个 IIFE 用于实现模块模式,其中 privateVar 是私有变量,只能通过返回对象的 publicMethod 访问。
使用在异步执行
;(async function() {
console.log('This will be executed immediately with async/await.');
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('This will be executed after 1 second.');
})();这个 IIFE 使用了 async/await 语法,即使使用了 await,它仍然会立即执行。
避免在行首使用
(function() {
// Some code here...
})();在 JavaScript 中,如果 IIFE 直接写在行首,某些压缩工具可能会将其与代码块混淆。为了避免这种情况,可以在 IIFE 前加上一个分号 ;。
IIFE 是 JavaScript 中一个非常有用的模式,它提供了一种创建自包含代码块的方法,有助于保持代码的封装性和组织性。





