iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >你真的了解JavaScript的作用域与闭包吗
  • 838
分享到

你真的了解JavaScript的作用域与闭包吗

2024-04-02 19:04:59 838人浏览 八月长安
摘要

目录一、作用域二、闭包总结一、作用域 1.作用域总体来说就是根据名称查找变量的一套规则。js查找变量的方式有两种:LHS和RHS。 LHS(left hand side)大致可以理解

一、作用域

1.作用域总体来说就是根据名称查找变量的一套规则。js查找变量的方式有两种:LHS和RHS。

LHS(left hand side)大致可以理解为给某个变量赋值,在赋值符(=)的左边;RHS(right hand side)是指找到某个变量的源值,如在赋值符(=)的右边。

举个例子说明,对于 a = 10; a = b; 这两个语句。

var a 这里就是LHS查询,查找当前作用域是否有a这个变量来给a进行赋值,如果有则进行赋值;如果没有,在非严格模式下JS引擎会自动创建一个变量a来进行赋值;在严格模式下JS引擎会抛出ReferenceError错误。

a = b;这个语句,对于b这个变量是进行RHS查询,查找b这个变量的值。如果成功查询,则进行赋值操作;如果查询失败,则抛出ReferenceError错误。如果查询成功,但是对这个变量的操作有问题,就会抛出TypeError错误。如b只是一个普通的变量,却当成函数使用(b())。

2.JS是基于词法作用域的。指在你写代码时将变量和函数写在哪里决定的,而不是调用顺序决定的。

举个例子

var num = 1;
function a() {
    console.log(num); // 1
}
function b() {
    var num = 2;
    a();
}
b();

当按照顺序执行b()时,在b函数作用域中定义了一个值为2的num变量,然后在b函数中调用a函数,来到a函数的作用域进行调用(而不是在b函数作用域),找到全局变量num = 1。

3.不同作用域间是互相不会影响的,重复定义变量是不会发生错误的。

举个例子

var i = 1;
var j = 2;
function a(){
    var i = 3;
    var j = 4;
    console.log(i,j); // 3,4
}
function b(){
    var i = 5;
    var j = 6;
    console.log(i,j); // 5,6
}
console.log(i,j);// 1,2
a();
b();

4.for循环中,var声明的变量在全局作用域能够访问,并且值是退出循环的那个值;let声明的变量会产生块作用域,它将值重新绑定到循环迭代中。

for(var i = 0;i<5;i++){
    console.log(i); // 0 1 2 3 4
}
console.log(i); // 5
 
for(let i = 0;i<5;i++){
    console.log(i); // 0 1 2 3 4
}
console.log(i); // ReferenceError

5.每个作用域都会发生提升操作;函数声明会发生提升,但是函数表达式不会被提升;

b() // TypeErrorn() // ReferenceError,因为不会变量提升// 函数声明function a(){    console.log(num); // undefined    var num = 1;}// 函数表达式var b = function n(){    console.log('b');}

6.函数声明首先被提升,变量声明在后;

函数首先被提升可以认为是函数的优先级高于变量,重复声明的变量会被函数替代。但是其他函数声明可以覆盖之前的函数声明。

b() // TypeError
n() // ReferenceError,因为不会变量提升
// 函数声明
function a(){
    console.log(num); // undefined
    var num = 1;
}
// 函数表达式
var b = function n(){
    console.log('b');
}

二、闭包

1.闭包是基于词法作用域书写代码时的必然结果。

不论函数在哪里执行,函数都会在代码书写的位置(即函数本身在哪)来进行作用域链的查找。当函数进行作用域查找时,就形成了闭包。

也可以说是当函数被当作值进行传递的时候(如参数传递、返回值等),就会形成闭包。

举个例子

function foo() {
    var a = 2;
    function bar() {
        console.log(a);
    }
    return bar;
}
var a = 3;
var baz = foo();
baz(); // 2 

当foo函数执行时,会返回bar函数,当bar函数在全局作用域执行时,会沿着bar函数定义的地方开始进行RHS查找a变量的值。这时就产生了闭包。闭包的产生准确来说应该是函数在函数本身所处作用域之外执行,对于IIFE(立即执行函数)来说虽然创建了闭包,但是却没有真正使用闭包,因为立即执行函数的执行作用域是函数定义的作用域,虽然是闭包,但是没有使用闭包的功能。

闭包的功能:函数在所处作用域之外执行时,会沿着函数定义时的作用域链进行查找。

var a = 1;
// 立即执行函数
(
    function(){
        console.log(a);
     }
)();

2.循环与闭包

观察下面的例子

for(var i = 0;i<3;i++){
    setTimeout(()=>{
        console.log(i);
    },i*500)
}

输出结果为 3 3 3,并不是想象中的 0 1 2。因为在for循环结束时,setTimeout开始执行,在执行的时候进行变量 i 的RHS查询,但是变量 i 只能在全局作用域中查到,这是变量 i 的值是退出循环的值 i = 3;

可能与你的想象结果有些许不同,如果要输出 0 1 2 该怎么做?

(1).使用IIFE形成闭包是否可行?

for (var i = 0; i < 3; i++) {
    (function () {
        setTimeout(() => {
            console.log(i);
        }, i*500)
    })()
}

结果依然是 3 3 3。因为虽然使用IIFE形成了闭包,但是在闭包中并没有 i 的值,还会沿着作用域链查找到全局 i = 3;

(2).在IIFE使用一个变量临时保存 i 值或传参

for (var i = 0; i < 3; i++) {
    (function () {
        var j = i;
        setTimeout(() => {
            console.log(j);
        }, i*500)
    })()
}
 
// 或
for (var i = 0; i < 3; i++) {
    (function (i) {
        setTimeout(() => {
            console.log(i);
        }, i*500)
    })(i)
}

结果为 0 1 2,第一个for循环闭包中有变量 j ,第二个for循环有形参 i ,都不会到达全局作用域。

(3).使用 let 生成块作用域

for(let i = 0;i<3;i++){
    setTimeout(()=>{
        console.log(i);
    },i*500)
}

结果为 0 1 2,let声明的变量会包含在块作用域中,并且作为循环变量时,每一次的迭代都会声明一次变量并将变量结果保存,当访问变量时,由于闭包的作用,会得到每次迭代的值。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!

--结束END--

本文标题: 你真的了解JavaScript的作用域与闭包吗

本文链接: https://www.lsjlt.com/news/144480.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 你真的了解JavaScript的作用域与闭包吗
    目录一、作用域二、闭包总结一、作用域 1.作用域总体来说就是根据名称查找变量的一套规则。JS查找变量的方式有两种:LHS和RHS。 LHS(left hand side)大致可以理解...
    99+
    2022-11-13
  • Python的闭包和装饰器你真的了解吗
    目录闭包装饰器总结闭包 闭包就是能够读取其他函数内部变量的函数。 def test1(k, b): def test1_1(x): print(k*x+b) ...
    99+
    2022-11-13
  • JavaScript 中的作用域与闭包
    目录一、JavaScript 是一门编译语言1.1 传统编译语言的编译步骤1.2 JavaScript 与传统编译语言的区别二、作用域(Scope)2.1 LHS查询 和 RHS查询...
    99+
    2022-11-13
  • Java和JavaScript的异同,你真的了解吗?
    Java和JavaScript是两种非常常见的编程语言,它们在很多方面有着相似的特性,但它们也有着很多不同之处。在本文中,我们将探讨Java和JavaScript的异同,并且演示一些代码示例来帮助你更好地理解它们。 Java和JavaS...
    99+
    2023-10-24
    javascript http 重定向
  • 你真的了解Python日志打包load的工作原理吗?
    Python是一门广泛应用于各种领域的编程语言。在日志处理方面,Python也提供了很多的库和工具。其中,日志打包和load是日志处理中常用的操作之一。本文将深入讲解Python中日志打包和load的工作原理,并演示一些实用的代码。 一、日...
    99+
    2023-10-29
    日志 打包 load
  • JavaScript的闭包与变量作用域介绍
    这篇文章主要讲解了“JavaScript的闭包与变量作用域介绍”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript的闭包与变量作用域介绍”吧!...
    99+
    2022-10-19
  • jQuery的操作属性你真的了解吗
    目录一、操作属性1、读取属性值:attr(属性名)2、修改属性值(1)attr(key,value)(2)attr(key,fn)(3)attr({属性名1:属性值,属性名2:属性值...
    99+
    2022-11-13
  • 你真的了解 PHP 面试和 JavaScript npm 吗?
    PHP和JavaScript是两种广泛应用于前端和后端的编程语言。由于其强大的功能和灵活性,它们在现代Web开发中已成为不可或缺的部分。在这篇文章中,我们将深入探讨PHP面试和JavaScript npm,以帮助您更好地了解它们的特点和用法...
    99+
    2023-09-17
    面试 javascript npm
  • Javascript的作用域、作用域链以及闭包详解
    一、javascript中的作用域 ①全局变量-函数体外部进行声明 ②局部变量-函数体内部进行声明 1)函数级作用域 javascript语言中局部变量不同于C#、Java等高级语言...
    99+
    2022-11-13
  • JavaScript深入理解作用域链与闭包详情
    目录深入作用域链与闭包作用域链[[Environment]]完善环境记录闭包函数实例什么是闭包变量绑定同一个闭包总结深入作用域链与闭包 为什么要把作用域链和闭包放在一起讲呢,它们有什...
    99+
    2022-11-13
  • Python中闭包与lambda的作用域解析
    本篇文章给大家带来了关于Python的相关知识,其中主要整理了关于lambda的作用域的相关问题,还有Python中闭包的相关内容,下面一起来看一下,希望对大家有帮助。【相关推荐:Python3视频教程 】Python闭包与lambda的作...
    99+
    2022-08-08
    python
  • Java接口面试:你真的了解如何打包吗?
    在Java开发中,接口是一种非常常见的程序设计模式,它能够让代码更加灵活和可扩展。不过,在面试中,考官往往会深入探讨接口的打包问题,因此,掌握如何打包接口是非常重要的。 接下来,本文将从以下几个方面介绍Java接口打包的相关知识: 什...
    99+
    2023-08-18
    接口 面试 打包
  • ASP和JavaScript:你真的了解函数和数组吗?
    函数和数组是编程中非常重要的概念,无论是ASP还是JavaScript都离不开它们。本文将详细讲解函数和数组的基本概念及其在ASP和JavaScript中的应用。 一、函数 函数是一段可重用的代码,可以接受输入参数并返回值。在编程中,函数...
    99+
    2023-11-13
    javascript 函数 数组
  • python的运算符与表达式你真的了解吗
    目录一、表达式二、运算符1、算术运算符2、赋值运算符3、比较运算符4、逻辑运算符5、成员关系运算6、对象实例测试7、位运算8、一元运算 :三、python运算符优先级 1、...
    99+
    2022-11-12
  • 你真的了解Linux下API的用法吗?
    Linux下的API是指应用程序接口,是操作系统提供给应用程序的一组接口,它们允许应用程序与操作系统进行交互和通信。对于Linux开发者来说,熟练掌握Linux下API的用法是非常重要的,本文将为大家介绍Linux下API的用法及其实例演示...
    99+
    2023-09-30
    数组 linux api
  • 一文了解你不知道的JavaScript闭包篇
    目录前言理解闭包升级版闭包循环和闭包模块小结前言 JavaScript语言中有一个非常重要又难以掌握,近似神话的概念-闭包。对于有一点JavaScript使用经验但从未真正理解闭包概...
    99+
    2022-11-13
    JavaScript 闭包
  • 你真的了解Python和JavaScript的日志记录技巧吗?
    Python和JavaScript是两种常用的编程语言,它们都具有强大的日志记录功能。在开发应用程序时,记录日志是非常重要的,它可以帮助开发人员诊断和解决问题,同时也可以提供有用的信息来进行性能分析和监控。 Python的日志记录技巧 Py...
    99+
    2023-08-16
    javascript 日志 编程算法
  • SpringBoot 拦截器妙用你真的了解吗
    HandlerInterceptor 详解 HandlerInterceptor 允许定制 handler 处理器执行链的工作流接口。我们可以自定义拦截器用于拦截 handlers ...
    99+
    2022-11-12
  • 你真的了解 Python 在 Linux 中的应用吗?
    Python 是一种高级编程语言,被广泛应用于各种软件开发和数据科学领域。在 Linux 操作系统中,Python 更是成为了必不可少的工具。在本文中,我们将探讨 Python 在 Linux 中的应用,并演示一些常见的代码示例。 Pyth...
    99+
    2023-09-07
    linux shell leetcode
  • 你真的了解PHP中的引用符号(&)吗
    引言 最近接手了五六年前的老项目,用的是CI2.0框架,在看框架源码的时候有个地方让我楞了一下,于是有了这篇文章。 字符&的最早历史可以追溯到公元1世纪,最早是拉丁语et ...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作