前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【JS】作用域(入门篇)

【JS】作用域(入门篇)

作者头像
德育处主任
发布2022-04-15 14:58:08
9560
发布2022-04-15 14:58:08
举报
文章被收录于专栏:前端数据可视化

作用域是什么?

几乎编程语言都需要实现的功能是“变量存储数据”,不然这门编程语言在当今就真的没多大优势了。

变量存储数据的正常流程是:先创建一个变量,然后把值存入该变量中。

但这些变量存活在哪里? 怎么读取这些变量的值? 如何修改变量的值? 在哪可以读取,哪里又不能读取? 每门编程语言都有一套这样的规则,而这个规则就是“作用域”。

使用 《你不知道的JavaScript 上卷》的一句话:

需要一套设计良好的规则来存储变量,并且之后可以方便地找到这些变量。这套规则被称为作用域。

js 的作用域规则并不像其他语言(比如 c、java 等)那么严谨,甚至很多时候还会让新手一头雾水。

本文要讲作用域有以下几个:

  • 全局作用域(window / global)
  • 函数作用域(function)
  • 块状作用域({})
  • 动态作用域(this 粗略讲解)

本文主要探讨日常工作中需要了解的几个点,所以并不会深入讲解 词法作用域 之类比较深的内容。

变量与常量

在了解作用域之前,需要先了解 js 的变量和常量是如何声明和使用。

js 的变量声明有 2 种:var 和 let。

使用 var 或者 let 声明变量的语法都是一样的,只是这两个关键字不同而已。

代码语言:javascript
复制
var a = 123
let b = 456

var 声明的变量,变量名可以相同,后面的声明会覆盖前面的声明。点击查看 var 用法

let 用法会更严谨,是 es6 提出来的。使用 let 声明的变量,不能重复声明。点击查看 let 用法

js 的常量声明暂时只有 1 种:const

代码语言:javascript
复制
const pi = 3.14

使用 const 声明常量,一经定义就不能再改,这里的“改”是指不能改变内存地址。

所以如果声明一个对象常量,对象内的属性是可以改的,因为这样不属于修改内存地址。 点击查看 const 用法

全局作用域

在 window 下声明的变量属于全局作用域。

比如

代码语言:javascript
复制
var a = 123

与之相对的是 局部作用域 ,比如 函数作用域块状作用域 等,下面会讲到。

注意

需要注意一点,在 js 中,如果不使用 varlet 声明的,严格来说不能叫变量。只能叫 window / global 下的一个属性。

代码语言:javascript
复制
a = 123

上面这种写法,和 var a = 123 的效果看上去差不多,但不使用 var 或 let 声明的变量实际上是挂载在 window / global 上的一个属性,而属性是可以用 delete 删除的,而变量(使用 var 和 let 声明)是不能用 delete 删除。

image.png
image.png

函数作用域

在函数内部声明的变量,属于函数作用域。在函数外是无法访问的。

代码语言:javascript
复制
function test() {
  var a = 123
  b = 456
  console.log(a)
  console.log(b)
}

test() // 输出 123,然后输出456

console.log(b) // 输出 456
console.log(a) // 报红 a is not defined

上面的例子中,虽然 b 是在 test 这个函数里面首次出现,但由于 b 没使用 var / let / const 这些关键字定义,所以 b 其实是挂载到 window / global 上的。

所以在函数外能访问 b ,却不能访问 a

块状作用域

{} 使用 let 定义的变量 和 const 定义的常量,属于块级作用域。

代码语言:javascript
复制
if (true) {
  var a = 123
  let b = 456
  const c = 789
}
console.log(a) // 输出 123
console.log(b) // 报红 b is not defined
console.log(c) // 报红 c is not defined

使用 var 在这种情况定义的变量是属于全局作用域的。

使用 letconst

动态作用域

动态作用域主要是指 this

动态作用域不关心函数和作用域是如何声明以及在何处声明的,它只关心从何处调用(箭头函数除外)。

代码语言:javascript
复制
window.a = 3
function test () {
  console.log(this.a)
}

test.bind({ a: 2 })() // 2
test() // 3

再举一个 《你不知道的JavaScript 上卷》 的例子

代码语言:javascript
复制
function foo() {
  console.log(a) // 3(不是2!)
}

function bar(){
    var a = 3
  foo()
}

var a = 2
bar()

因为当 foo() 无法找到 a 的变量引用时,会顺着调用栈在调用 foo() 的地方查找 a ,而不是在嵌套的此法作用域链上查找。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/05/03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 作用域是什么?
  • 变量与常量
  • 全局作用域
  • 函数作用域
  • 块状作用域
  • 动态作用域
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档