js闭包所用的场合以及优缺点分析

JS闭包是指函数可以访问当前环境外的变量,并在执行后保留对这些变量的引用。通俗的说,就是函数内部的函数可以访问函数外部函数的变量。下面我们来一步一步详细讲解JS闭包所用的场合以及优缺点分析。

什么是闭包

在JS中,每当创建一个函数,该函数就会创建一个作用域(scope)链。作用域链可以帮助函数在查找变量时,逐级向上进行查找,直到找到为止。而闭包,正是通过这个作用域链来实现对父级作用域中变量的访问。

闭包的用处

封装变量

JS闭包可以避免全局变量带来的命名冲突,可以将一个变量封装在一个函数内部,从而防止其他函数修改该变量。如下所示:

function createCounter() {
  var count = 0;
  return function () {
    count++;
    console.log(count);
  }
}

var counter = createCounter();
counter(); // 输出1
counter(); // 输出2
counter(); // 输出3

在上述代码中,我们首先定义了一个外部函数createCounter,并在其中定义了一个局部变量count。随后我们又定义了一个内部函数,并在内部函数中修改了count变量的值。最后将内部函数作为函数createCounter的返回值返回。

我们可以发现,在createCounter函数执行完之后,count变量并没有从内存中销毁,而是在内部函数中得以访问。这就是闭包的内存保留机制。

实现函数或对象私有化

闭包能够让我们实现一些私有方法的效果,因为闭包可以使得函数内部的变量在函数执行完毕后仍然存活在内存中,不会被垃圾回收站收回。这就可以用来实现JS中的对象私有化。如下所示:

function Point(x, y) {
  this.x = x;
  this.y = y;
  var self = this;
  var length = 0; //私有变量
  // 计算点到原点的距离
  var calcLength = function () {
    length = Math.sqrt(self.x * self.x + self.y * self.y);
  }
  calcLength();

  this.getLength = function () {
    return length;
  }
}

var point = new Point(3, 4);
console.log(point.getLength()); // 输出 5
console.log(point.length); // 输出 undefined

我们在Point函数中定义了一个私有变量length,用于保存点到原点的距离。在函数中还定义了一个私有函数calcLength用于计算长度。由于length被定义在Point函数的内部,所以我们不能直接访问到length变量。但是在Point函数中又定义了一个公有方法getLength,该方法能够返回length的值。

通过上述代码,我们可以看到,point对象虽然不能直接访问到length,但是却能够通过调用getLength方法来获取到length的值。

闭包的缺点

尽管闭包可以为我们提供很多便利,但是它也有一些缺点。

使用闭包需要注意内存泄漏问题。当函数执行完毕,内部变量仍然被占用,不会被回收,这就造成了内存泄漏。为了避免内存泄漏,我们需要注意不要在闭包中存储过多的外部变量。

闭包中的作用域链访问虽说便利,但是它对性能也有一定的影响。因为作用域链的查找步骤需要多次访问内存,效率比较低下,因此过度使用闭包会导致页面性能下降,甚至造成浏览器的卡顿。

闭包的示例

示例1:封装变量

var counter = (function() {
    var count = 0;
    return function() {
        count++;
        console.log(count);
    };
})(); // 每次调用都会自增1

counter(); // 输出1
counter(); // 输出2
counter(); // 输出3

示例2:使用闭包实现节流函数

function throttle(fn, interval) {
  var startTime = 0;
  return function() {
    var endTime = new Date().getTime();
    if(endTime - startTime > interval) {
      fn.apply(this, arguments);
      startTime = endTime;
    }
  };
}

var func = function() {
  console.log('hello world');
};

var throtFunc = throttle(func, 1000);

throtFunc();
setTimeout(throtFunc, 500);
setTimeout(throtFunc, 900);
setTimeout(throtFunc, 1200);
setTimeout(throtFunc, 1600);

在上述示例中,我们定义了一个函数throttle,函数接收两个参数,第一个参数是要包装的函数,第二个参数表示间隔多少毫秒执行一次。throttle函数内部又返回了一个匿名函数,并在该匿名函数内部实现了函数节流的功能。最后,我们可以通过throttle函数来实现对其他函数的节流处理。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:js闭包所用的场合以及优缺点分析 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • 基于JavaScript实现回到页面顶部动画代码

    实现回到页面顶部动画的代码需要使用JavaScript,下面是一份完整攻略: 1. HTML 结构 在页面中添加一个回到顶部的按钮,可以使用一个元素(如 div 或 a 标签)作为按钮,添加样式,如下所示: <div id="back-to-top">↑ 返回顶部</div> 2. CSS 样式 需要为按钮设置样式…

    JavaScript 2023年6月10日
    00
  • JS中eval函数的使用示例

    下面是关于“JS中eval函数的使用示例”的完整攻略。 eval函数的作用及用法 eval函数可以将接受的字符串作为JavaScript代码来执行,并将执行结果返回。其最常见的用法是将字符串转换为可执行的代码,极大的增强了语言的灵活性。 eval函数的基本语法如下: eval(string) 其中,string是要执行的JavaScript代码字符串。 需要…

    JavaScript 2023年5月27日
    00
  • 面试官常问之说说js中var、let、const的区别

    让我来给你详细讲解一下“面试官常问之说说js中var、let、const的区别”。 区别概述 在JavaScript中,变量声明有三种方式:var、let和const。它们之间的区别主要在于作用域、值的可变性和赋值方式。 var: 可以重复赋值,不存在块级作用域,声明的变量会被提升到所在函数的顶部。 let: 允许块级作用域,不能重复声明,可以更改已经赋值的…

    JavaScript 2023年6月11日
    00
  • JavaScript 用fetch 实现异步下载文件功能

    下面是实现JavaScript使用fetch实现异步下载文件功能的完整攻略。 1. 前置知识 在开始操作之前,需要对以下概念有一定的了解: JavaScript fetch API Blob URL.createObjectURL() a标签的download属性 2. 原理分析 JavaScript的fetch API可以向服务器请求获取数据或者资源并进行…

    JavaScript 2023年5月27日
    00
  • Express的路由详解

    Express的路由系统非常强大,它能够帮助开发者分发请求并处理对应的响应。在这篇文章中,我将详细讲解如何使用Express的路由系统。 路由基础 在Express中,路由实际上就是一个处理程序(函数),当接收到特定的HTTP请求时,它会被执行。下面是一个基本的Express路由示例: const express = require(‘express’) c…

    JavaScript 2023年6月11日
    00
  • 使用js dom和jquery分别实现简单增删改

    下面我来详细讲解使用JS DOM和jQuery分别实现简单增删改的完整攻略。 使用JS DOM实现简单增删改 首先我们需要明确一下,JS DOM是指通过JavaScript来操作DOM元素,实现交互效果的一种技术。下面是详细的步骤: 添加元素 首先,我们需要一个按钮,并绑定一个事件,当用户点击按钮时会自动创建一个新的元素。具体代码如下: <!DOCTY…

    JavaScript 2023年6月10日
    00
  • 深入了解JavaScript中的Symbol的使用方法

    深入了解JavaScript中的Symbol的使用方法 Symbol是一种原始数据类型,它可以作为对象属性的唯一标识符。本攻略将引导您深入了解Javascript中Symbol的使用方法。 基本用法 创建Symbol对象可以使用Symbol()函数,该函数可以生成一个唯一的Symbol。 let mySymbol = Symbol(); console.lo…

    JavaScript 2023年6月10日
    00
  • 详解JavaScript中Math内置对象基本方法的使用

    详解JavaScript中Math内置对象基本方法的使用 什么是Math对象 JavaScript中的Math对象是一个内置对象。它包含了一些常用的数学计算方法,如取绝对值、四舍五入、三角函数等。我们可以使用Math对象的方法来进行计算。 常用的Math方法 Math.ceil() 向上取整 该方法用于将一个数值向上取整,即将小数部分舍入为最接近的整数。 l…

    JavaScript 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部