JavaScript相关面试题8:闭包

简介: 注意事项如果不是某些特定任务需要使用闭包,在其它函数中创建函数是不明智的,因为闭包在处理速度和内存消耗方面对脚本性能具有负面影响例如,在创建新的对象或者类时,方法通常应该关联于对象的原型,而不是定义到对象的构造器中。原因在于每个对象的创建,方法都会被重新赋值

文章目录

说说你对闭包的理解,以及闭包使用场景

使用场景

注意事项

说说你对闭包的理解,以及闭包使用场景

一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)

也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域

在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来,作为函数内部与外部连接起来的一座桥梁


function init() {

   var name = "Mozilla"; // name 是一个被 init 创建的局部变量

   function displayName() { // displayName() 是内部函数,一个闭包

       alert(name); // 使用了父函数中声明的变量

   }

   displayName();

}

init();

1

2

3

4

5

6

7

8

displayName() 没有自己的局部变量。然而,由于闭包的特性,它可以访问到外部函数的变量


使用场景

任何闭包的使用场景都离不开这两点:

●创建私有变量

●延长变量的生命周期


一般函数的词法环境在函数返回后就被销毁,但是闭包会保存对创建时所在词法环境的引用,即便创建时所在的执行上下文被销毁,但创建时所在词法环境依然存在,以达到延长变量的生命周期的目的


在页面上添加一些可以调整字号的按钮


function makeSizer(size) {

 return function() {

   document.body.style.fontSize = size + 'px';

 };

}


var size12 = makeSizer(12);

var size14 = makeSizer(14);

var size16 = makeSizer(16);


document.getElementById('size-12').onclick = size12;

document.getElementById('size-14').onclick = size14;

document.getElementById('size-16').onclick = size16;

1

2

3

4

5

6

7

8

9

10

11

12

13

柯里化函数

柯里化的目的在于避免频繁调用具有相同参数函数的同时,又能够轻松的重用


// 假设我们有一个求长方形面积的函数

function getArea(width, height) {

   return width * height

}

// 如果我们碰到的长方形的宽老是10

const area1 = getArea(10, 20)

const area2 = getArea(10, 30)

const area3 = getArea(10, 40)


// 我们可以使用闭包柯里化这个计算面积的函数

function getArea(width) {

   return height => {

       return width * height

   }

}


const getTenWidthArea = getArea(10)

// 之后碰到宽度为10的长方形就可以这样计算面积

const area1 = getTenWidthArea(20)


// 而且如果遇到宽度偶尔变化也可以轻松复用

const getTwentyWidthArea = getArea(20)


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

使用闭包模拟私有方法

在JavaScript中,没有支持声明私有变量,但我们可以使用闭包来模拟私有方法


var Counter = (function() {

 var privateCounter = 0;

 function changeBy(val) {

   privateCounter += val;

 }

 return {

   increment: function() {

     changeBy(1);

   },

   decrement: function() {

     changeBy(-1);

   },

   value: function() {

     return privateCounter;

   }

 }

})();


var Counter1 = makeCounter();

var Counter2 = makeCounter();

console.log(Counter1.value()); /* logs 0 */

Counter1.increment();

Counter1.increment();

console.log(Counter1.value()); /* logs 2 */

Counter1.decrement();

console.log(Counter1.value()); /* logs 1 */

console.log(Counter2.value()); /* logs 0 */


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

上述通过使用闭包来定义公共函数,并令其可以访问私有函数和变量,这种方式也叫模块方式

两个计数器 Counter1 和 Counter2 是维护它们各自的独立性的,每次调用其中一个计数器时,通过改变这个变量的值,会改变这个闭包的词法环境,不会影响另一个闭包中的变量


注意事项

如果不是某些特定任务需要使用闭包,在其它函数中创建函数是不明智的,因为闭包在处理速度和内存消耗方面对脚本性能具有负面影响


例如,在创建新的对象或者类时,方法通常应该关联于对象的原型,而不是定义到对象的构造器中。

原因在于每个对象的创建,方法都会被重新赋值


目录
相关文章
|
1月前
|
JavaScript 前端开发
常见的JS面试题
【8月更文挑战第5天】 常见的JS面试题
48 3
|
23天前
|
存储 JavaScript 前端开发
2022年前端js面试题
2022年前端js面试题
19 0
|
1月前
|
JavaScript 前端开发 安全
详细讲解JavaScript中的闭包问题附代码演示
闭包是JavaScript中一关键概念,它允许内部函数访问外部函数的作用域,从而实现变量的封装与持久化。本文通过示例解释了闭包的工作原理及其优势,如数据隐藏和私有变量的实现;同时也指出了闭包可能导致的内存占用问题,强调合理使用的重要性。
21 1
|
1月前
|
JavaScript 前端开发 Java
JavaScript中的闭包概念讲解
闭包是指函数内部嵌套另一个函数,并且内部函数引用了外部函数的数据(如变量或函数)。这样的内部函数被称为闭包。以示例代码为例,`fn1` 中有两个闭包函数 `fn2` 和 `fn3`,它们都可以访问并修改 `fn1` 中的变量 `a`。
12 1
|
11天前
|
自然语言处理 JavaScript 前端开发
|
1月前
|
JavaScript 前端开发 程序员
JS小白请看!一招让你的面试成功率大大提高——规范代码
JS小白请看!一招让你的面试成功率大大提高——规范代码
|
20天前
|
自然语言处理 前端开发 JavaScript
前端进阶必读:JS闭包深度解析,掌握这一特性,你的代码将焕然一新!
【8月更文挑战第23天】闭包是JavaScript的一项高级功能,让函数能够访问和操作外部函数作用域中的变量。本文深入解析闭包概念、组成及应用场景。闭包由函数及其词法环境构成,通过在一个函数内定义另一个函数来创建。它有助于封装私有变量、维持状态和动态生成函数。然而,不当使用闭包可能导致内存泄漏或性能问题。掌握闭包对于实现模块化代码和成为优秀前端开发者至关重要。
29 0
|
30天前
|
JavaScript 前端开发 安全
JS 闭包(1)
JS 闭包(1)
23 0
|
30天前
|
JavaScript Java
JS 闭包
JS 闭包
21 0
|
30天前
|
存储 JavaScript 前端开发
JavaScript——对闭包的看法,为什么要用闭包?说一下闭包原理以及应用场景
JavaScript——对闭包的看法,为什么要用闭包?说一下闭包原理以及应用场景
28 0