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 是维护它们各自的独立性的,每次调用其中一个计数器时,通过改变这个变量的值,会改变这个闭包的词法环境,不会影响另一个闭包中的变量


注意事项

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


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

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


目录
相关文章
|
6天前
|
自然语言处理 JavaScript 前端开发
三个JavaScript面试题
摘要: - 闭包是JavaScript函数能记住词法作用域,即使在外部执行。示例:计数器函数`createCounter()`返回访问`count`的匿名函数,每次调用计数递增。 - 事件循环处理异步操作,通过检查任务队列执行回调。示例:`setTimeout`异步任务在3秒后添加到队列,待执行,输出顺序为同步任务1、2,然后异步任务1。 - 箭头函数是ES6简洁的函数定义方式,如`greet = name => `Hello, ${name}!`。它没有自己的`this`,不适用作构造函数。
25 6
|
6天前
|
前端开发 JavaScript
闭包在JavaScript中有许多应用场景
闭包在JavaScript中发挥关键作用,如封装私有变量和函数提升安全性,维护变量生命周期,实现高阶函数,模拟块级作用域,支持回调函数以处理异步操作,以及促进模块化编程,增强代码组织和管理。闭包是理解和掌握JavaScript高级特性的重要一环。
21 7
|
12天前
|
自然语言处理 JavaScript 前端开发
【JavaScript技术专栏】深入理解JavaScript作用域与闭包
【4月更文挑战第30天】了解JavaScript的关键在于掌握作用域和闭包。作用域决定变量和函数的可访问范围,分为全局(在`window`或`global`对象中)和局部(函数内部)。闭包则允许函数访问其创建时的作用域,即使在其他地方调用。它通过作用域链保存对外部变量的引用,常用于实现私有变量、模块化和柯里化。然而,不当使用闭包可能导致内存泄漏和性能下降。理解这些概念能提升代码质量,但也需谨慎处理潜在问题。
|
13天前
|
自然语言处理 前端开发 JavaScript
【Web 前端】什么是JS闭包?
【4月更文挑战第22天】【Web 前端】什么是JS闭包?
|
14天前
|
存储 JavaScript 前端开发
每日一道javascript面试题(九)函数的参数可以和函数体中的变量重名吗
每日一道javascript面试题(九)函数的参数可以和函数体中的变量重名吗
|
14天前
|
存储 JavaScript 前端开发
每日一道javascript面试题(八)你真的知道了解const吗
每日一道javascript面试题(八)你真的知道了解const吗
|
14天前
|
JavaScript 前端开发
每日一道javascript面试题(七)你真的知道箭头函数吗
每日一道javascript面试题(七)你真的知道箭头函数吗
|
14天前
|
JavaScript 前端开发
每日一道javascript面试题(六)有var和无var
每日一道javascript面试题(六)有var和无var
|
14天前
|
JavaScript 前端开发
每日一道javascript面试题(五)
每日一道javascript面试题(五)
每日一道javascript面试题(五)
|
14天前
|
前端开发 JavaScript
每日一道javascript面试题(三)
每日一道javascript面试题(三)