位置: 编程技术 - 正文

JS 作用域与作用域链详解(js作用域和作用域链的理解阮一峰)

编辑:rootadmin

推荐整理分享JS 作用域与作用域链详解(js作用域和作用域链的理解阮一峰),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:js作用域和作用域链的理解阮一峰,js有哪些作用域,分别是什么意思,js什么是作用域链,js什么是作用域链,js作用域与作用域链,js作用域的理解,js 作用域与作用域的关系,js作用域与作用域链,内容如对您有帮助,希望把文章链接给更多的朋友!

(1)作用域

一个变量的作用域(scope)是程序源代码中定义的这个变量的区域。

1. 在JS中使用的是词法作用域(lexical scope)

不在任何函数内声明的变量(函数内省略var的也算全局)称作全局变量(global scope)

在函数内声明的变量具有函数作用域(function scope),属于局部变量

局部变量优先级高于全局变量

函数内省略var的,会影响全局变量,因为它实际上已经被重写成了全局变量

函数作用域,就是说函数是一个作用域的基本单位,js不像c/c++那样具有块级作用域 比如 if for 等

当然了,js里边还使用到了高阶函数,其实可以理解成嵌套函数

test1()之后将调用外层函数,返回了一个内层函数,再继续(),就相应调用执行了内层函数,所以就输出 ”one"

嵌套函数涉及到了闭包,后面再谈..这里内层函数可以访问到外层函数中声明的变量name,这就涉及到了作用域链机制

2. JS中的声明提前

js中的函数作用域是指在函数内声明的所有变量在函数体内始终是可见的。并且,变量在声明之前就可以使用了,这种情况就叫做声明提前(hoisting)

tip:声明提前是在js引擎预编译时就进行了,在代码被执行之前已经有声明提前的现象产生了

比如

上边就达到了下面的效果

再试试把var去掉?这是函数内的name已经变成了全局变量,所以不再是undefined

3. 值得注意的是,上面提到的都没有传参数,如果test有参数,又如何呢?

之前说过,基本类型是按值传递的,所以传进test里面的name实际上只是一个副本,函数返回之后这个副本就被清除了。千万不要以为函数里边的name="two"把全局name修改了,因为它们是两个独立的name

(2)作用域链

上面提到的高级函数就涉及到了作用域链

1. 引入一大段话来解释:每一段js代码(全局代码或函数)都有一个与之关联的作用域链(scope chain)。

这个作用域链是一个对象列表或者链表,这组对象定义了这段代码中“作用域中”的变量。

当js需要查找变量x的值的时候(这个过程称为变量解析(variable resolution)),它会从链的第一个对象开始查找,如果这个对象有一个名为x的属性,则会直接使用这个属性的值,如果第一个对象中没有名为x的属性,js会继续查找链上的下一个对象。如果第二个对象依然没有名为x的属性,则会继续查找下一个,以此类推。如果作用域链上没有任何一个对象含有属性x,那么就认为这段代码的作用域链上不存在x,并最终抛出一个引用错误(ReferenceError)异常。

2. 作用域链举例:

在js最顶层代码中(也就是不包括任何函数定义内的代码),作用域链由一个全局对象组成。

在不包含嵌套的函数体内,作用域链上有两个对象,第一个是定义函数参数和局部变量的对象,第二个是全局对象。

在一个嵌套的函数体内,作用域上至少有三个对象。

JS 作用域与作用域链详解(js作用域和作用域链的理解阮一峰)

3. 作用域链创建规则:

当定义一个函数时(注意,是定义的时候就开始了),它实际上保存一个作用域链。

当调用这个函数时,它创建一个新的对象来储存它的参数或局部变量,并将这个对象添加保存至那个作用域链上,同时创建一个新的更长的表示函数调用作用域的“链”。

对于嵌套函数来说,情况又有所变化:每次调用外部函数的时候,内部函数又会重新定义一遍。因为每次调用外部函数的时候,作用域链都是不同的。内部函数在每次定义的时候都要微妙的差别---在每次调用外部函数时,内部函数的代码都是相同的,而且关联这段代码的作用域链也不相同。

(tip: 把上面三点理解好,记住了,最好还要能用自己的话说出来,不然就背下来,因为面试官就直接问你:请描述一下作用域链...)

举个作用域链的实用例子:

上边是个嵌套函数,相应的应该是作用域链上有三个对象那么在调用的时候,需要查找name的值,就在作用域链上查找

当成功调用test1()的时候,顺序为 test1()->test()->全局对象window 因为在test1()上就找到了name的值three,所以完成搜索返回

当成功调用test1()的时候,顺序为 test2()->test()->全局对象window 因为在test2()上没找到name的值,所以找test()中的,找到了name的值two,就完成搜索返回

还有一个例子有时候我们会犯错的,面试的时候也经常被骗到。

为什么?根据作用域链中变量的寻找规则:

这里有一个函数,它是匿名函数,既然是函数,那就在作用域链上具有一个对象,这个函数里边使用到了变量i,它自然会在作用域上寻找它。查找顺序是 这个匿名函数 -->外部的函数buttonInit() -->全局对象window

匿名函数中找不到i,自然跑到了buttonInit(), ok,在for中找到了,

这时注册事件已经结束了,不要以为它会一个一个把i放下来,因为函数作用域之内的变量对作用域内是一直可见的,就是说会保持到最后的状态

当匿名函数要使用i的时候,注册事件完了,i已经变成了4,所以都是Button4

那怎么解决呢?

给它传值进去吧,每次循环时,再使用一个匿名函数,把for里边的i传进去,匿名函数的规则如代码

这样就可以 Button1..2..3了

4.上述就是作用域链的基本描述,另外,with语句可用于临时拓展作用域链(不推荐使用with)

语法形如:

with(object)

statement

这个with语句,将object添加到作用域链的头部,然后执行statement,最后把作用域链恢复到原始状态

简单用法:

比如给表单中各个项的值value赋值

一般可以我们直接这样

引入with后(因为使用with会产生一系列问题,所以还是使用上面那张形式吧)

另外,假如 一个对象o具有x属性,o.x = 1;那么使用

就可以转换成 o.x = 2;假如o没有定义属性x,它的功能就只是相当于 x = 2; 一个全局变量罢了。

因为with提供了一种读取o的属性的快捷方式,但他并不能创建o本身没有的属性。

以上所述就是本文的全部内容了,希望能够对大家学习javascript有所帮助。

JavaScript之数组(Array)详解 ECMAScript的数组与其他语言中的数组有着相当大的区别。虽然ECMAScript中的数组也是有序列表,但是它数组你的每一项可以保存任何类型的数据。ECMAScript

JavaScript数据类型详解 数据类型JavaScript中有5种简单数据类型(也称为基本数据类型):Undefined、Null、Boolean、Number和String。还有1种复杂数据类型——Object,Object本质上是由一

JavaScript数据类型之基本类型和引用类型的值 ECMAScript变量包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值是简单的数据段,而引用类型值指那些可能由多个值构成的对象。在将

标签: js作用域和作用域链的理解阮一峰

本文链接地址:https://www.jiuchutong.com/biancheng/382845.html 转载请保留说明!

上一篇:实现前后端数据交互方法汇总(前后端调用)

下一篇:JavaScript之数组(Array)详解(javascript数组有哪些方法)

  • 境外承包工程项下资金
  • 未交增值税是什么科目
  • 开具增值税发票哪些情形不用交税?
  • 只报个税不交社保有什么税务风险
  • 小微企业企业所得税100万元以下减半征收怎么计算
  • 增值税科目及会计处理
  • 餐饮设备租赁服务属于
  • 固定资产清理费用计入哪里
  • 房屋出租收入会计分录
  • 销售免税产品是什么意思
  • 交易性金融资产和其他权益工具投资的区别
  • 税控盘交服务费
  • 委托加工直接对外销售的消费税
  • 附加税减半征收政策从什么时候开始
  • 实习生应该如何计算个人所得税
  • 酒店应不应该为员工提供澡堂
  • 研发费用加计扣除行业
  • 进项税有余额但没有余额
  • 销售原材料收到商业承兑汇票会计分录
  • 企业收取客户利润违法吗
  • 银行定期存款利率计算
  • 购买原材料已付款怎么记账
  • 减免税款怎么入账
  • 印花税到底什么通俗一点
  • 固定资产应付账款在现金流量表中怎么体现
  • 一般纳税人设备租赁税率
  • 预付的费用没有还没有收到发票
  • 汇算清缴时所得税费用
  • mac系统怎么设置字体大小
  • 怎么注销win10系统
  • 主办会计工作主要做什么
  • 退回多缴税款账务处理
  • 查账征收的个独可以随意分配利润吗
  • 销售货物结转成本会计分录
  • php嵌入js
  • 全额拨款事业单位工资待遇
  • linux命令行怎么用
  • 路由器怎么重置网络
  • ev4是什么文件
  • 酒店采购布草如何入账
  • 土地使用税怎么交税
  • 发票开出后只收到部分款怎么处理?
  • 杜拉通河谷中的Nuestra Señora de la Hoz老修道院,西班牙塞哥维亚 (© Arco Images GmbH/Alamy)
  • https是如何保证安全的
  • 城市维护建设税是什么意思
  • 增值税扣税凭证进项税额转出情况核实函
  • 股权转让会计分录摘要怎么写
  • 增值税是如何计算的
  • 在计算应纳税所得额时,纳税人因自然灾害
  • 营改增之后发票的变化
  • 承兑汇票私人贴息双方都违法吗
  • mac卸载软件在哪里彻底卸载?
  • 基本户收到款不入账
  • 个体工商户税务注销流程
  • 工会经费计入科目
  • 预包装食品加工及销售营业执照图片
  • 发票入账但是没付款有什么税务风险
  • sqlserver开启远程
  • mysql读写分离实现原理
  • windows10显示
  • win8优化驱动器
  • mac电脑安装windows
  • mac小技巧
  • linux中vi替换
  • windows7hosts文件
  • win10玩饥荒
  • win10大更新2021要多久
  • 攻击判定是什么意思
  • Javascript获取元素的父元素
  • gridview添加数据
  • js继承怎么实现
  • java深入理解
  • python常用的库
  • python所有语句
  • 车船税保险公司代收代缴后,单位还申报不?
  • 济南高新区地税局地址
  • 沙宣发型适合什么年龄女性
  • 海口市哪个地方最漂亮
  • 国家税务总局黑龙江电子税务局下载
  • 审计报告非标准意见
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设