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

yizhihongxing

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日

相关文章

  • Javascrip基础之for循环和数组

    Javascript基础之for循环和数组 在Javascript中,for循环和数组是非常重要的基础知识点,它们可以帮助我们完成很多重要的任务,如循环迭代,数据处理等。本文将详细讲解Javascript中的for循环和数组的用法,帮助大家掌握这些重要的知识点。 for循环 for循环是一种常见的循环方式,可以重复执行指定的代码块。它的基本语法如下: for…

    JavaScript 2023年5月27日
    00
  • json格式数据的添加,删除及排序方法

    下面我来详细讲解一下“JSON格式数据的添加、删除及排序方法”。 JSON格式数据简介: JSON是一种轻量级的数据格式,它常用于web应用程序之间的数据交换,是JavaScript对象的文本表示。在JSON格式中,数据以键值对的形式存在,用逗号分隔开来。关键字和值之间用冒号“:”分隔,大括号({})用于定义对象,中括号([])用于定义数组。 下面我将分别讲…

    JavaScript 2023年5月27日
    00
  • JavaScript数组实现扁平化四种方法详解

    当我们需要处理嵌套的数组时,可能会遇到需要将它扁平化的情况。JavaScript提供了四种方法来实现数组的扁平化。 方法一:使用reduce方法 reduce() 方法对数组中的每个元素执行一个由您定义的函数,并将其输出为单个值。 所以使用reduce可以将嵌套的数组扁平化。 代码如下: function flatten(arr) { return arr.…

    JavaScript 2023年5月27日
    00
  • 详解js中的原型,原型对象,原型链

    我来为你详细讲解“详解js中的原型,原型对象,原型链”的完整攻略。 1. 原型 在 Javascript 中,每个对象都有一个原型对象(prototype)。原型是一个简单的对象,它是由对象创建函数(Object、Array、Function 等)创建的。 我们来看一个简单的示例: function Person(name, age) { this.name…

    JavaScript 2023年5月27日
    00
  • 详解JS异步加载的三种方式

    详解JS异步加载的三种方式 JS异步加载指的是JavaScript代码在浏览器中执行时,通过非阻塞IO的方式,使得代码的执行不会阻塞页面的渲染和交互,从而提升用户体验。而JS异步加载的方式主要有以下三种: 1. defer 使用 defer 属性可以将脚本的加载推迟到文档的解析和显示完成之后再执行。这个过程会是解析 HTML 文档和执行 JS 脚本并行进行的…

    JavaScript 2023年6月11日
    00
  • 深入浅析JavaScript中prototype和proto的关系

    那么我们先来简单介绍一下prototype和proto的概念。 在JavaScript中,每个对象都有一个proto属性,它指向该对象的原型。而原型又拥有一个prototype属性,它指向该原型的构造函数的原型。这里可能有些晦涩难懂,接下来我们通过例子来更详细地解释。 假设我们有如下的一个构造函数: function Person(name) { this.…

    JavaScript 2023年6月10日
    00
  • JS使用Chrome浏览器实现调试线上代码

    JS使用Chrome浏览器实现调试线上代码 背景概述 开发者在线上部署的代码出现问题时,需要及时定位问题。然而,线上代码的环境不同于本地开发环境,部署过程中也可能出现各种问题,使线上代码难以调试。因此,如何使用调试工具,在线上环境快速定位问题,显得尤为重要。 工具准备 Chrome浏览器 由于Chrome浏览器功能齐全,且被广大开发者喜爱,因此在本文中,我们…

    JavaScript 2023年6月11日
    00
  • 如何利用原生JS实现触摸滑动监听事件

    要实现触摸滑动监听事件,可以使用原生JS的Touch API。下面是一些步骤和示例代码,可以帮助你了解如何实现此功能。 获取DOM元素 将要监听的DOM元素获取到,比如: let slider = document.getElementById(‘slider’); 添加touchstart监听事件 当用户开始触摸屏幕时,会触发touchstart事件。在这…

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