UzumakiItachi
首页
  • JavaSript
  • Vue

    • Vue2
    • Vue3
  • React

    • React_18
  • WebPack
  • 浏览器相关
  • 工程化相关
  • 工作中遇到的问题以及解决方案
  • Git
  • 面试
  • 学习
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 个人产出
  • 实用工具
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

UzumakiItachi

起风了,唯有努力生存。
首页
  • JavaSript
  • Vue

    • Vue2
    • Vue3
  • React

    • React_18
  • WebPack
  • 浏览器相关
  • 工程化相关
  • 工作中遇到的问题以及解决方案
  • Git
  • 面试
  • 学习
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 个人产出
  • 实用工具
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • JavaScript

    • 手撕Promise
    • 手撕JS八股文系列
    • 手撕观察者模式和发布订阅模式
    • 页面可见性——visibilitychange
    • JS数据类型那点事儿
    • 作用域、执行上下文和this
      • 前言
      • 作用域
        • 什么是作用域?
        • 词法作用域和动态作用域
        • 全局作用域,函数作用域,块级作用域
      • 作用域链,执行上下文
      • this
    • 防抖和节流
    • 装饰器
    • JS设计模式小结
  • CSS

  • 前端
  • JavaScript
hanhanbuku
2023-05-17
目录

作用域、执行上下文和this

# 前言

作用域和this一直都是js里令人头疼的问题,个人总结了一下自己对作用域以及this指向的一些理解。

# 作用域

# 什么是作用域?

作用域本身指的就是某个变量所能被访问的区域,也就是你在某处定义了一个变量,那么有这么一个区域内,是可以访问这个变量的。出了这个区域。你就无法访问他了。对于这种现象,就可以理解为作用域 而作用域从概念上来区分有两种,一是词法作用域,二是动态作用域。

# 词法作用域和动态作用域

词法作用域指的是变量在何处定义,他的作用域就在哪里。而动态作用域则是变量在何处被调用,则他的作用域就在何处。在js中采用的就是词法作用域

# 全局作用域,函数作用域,块级作用域

上面介绍了两种概念上的作用域,接下来介绍一下js中的三种作用域。

  • 全局作用域

全局作用域,顾名思义,就是定义在全局的变量。在代码的任何地方都可以访问全局作用域内的变量。至于是为什么,这里留个疑问。

  • 块级作用域

js本身是没有块级作用域的,也就是我们定义在{}里的变量都会被提升到全局。而在es6引入了let关键字后,就有了块级作用域下面看一段代码示例

if(true){
    var a = 1
}
console.log(a)// 1

if(true){
    let a = 1
}
console.log(a) //a is not defined
1
2
3
4
5
6
7
8
9

在没有let之前,用var声明的变量会被提升到全局,所以我们在花括号外面也能访问到a。而在使用了let之后,就会形成块级作用域,也就是变量只能再花括号内访问了,所以第二段代码会报错,提示a为定义

  • 函数作用域

最有意思的东西来了,函数作用域,他是一个能牵扯出很多东西的作用域。许许多多复杂的概念都是在他里头出现的,比如闭包,作用域链,执行上下文等等。 那么他到底是个什么东西呢,其实可以把他理解成函数体内的区域,和块级作用域相似。都是花括号包裹的这个区域,不过在函数作用域内会发生许许多多奇怪的事情 例如,在函数内访问别的变量,就会牵扯出闭包,作用域链的概念,再比如在函数体内能访问哪些变量。这就又涉及到了函数的执行上下文的概念。下面就让我来一一解答一下

# 作用域链,执行上下文

  • 执行上下文

先从执行上下文开始讲起,执行上下文又分为全局执行上下文和函数执行上下文。可以把他理解成一个对象。这个对象上包含了当前可访问的活动变量,this等一些列东西。 js自身维护了一个执行上下文栈,没当一个函数被调用时,就会创建一个函数的执行上下文,将他压入栈内。这个执行上下文包含了他父级上下文的变量。栈的最底部就是全局执行上下文。 当我们在一个函数体内访问一个变量时,首先js会在当前函数执行上下文内查找是否有这个变量,没有的话就会去父级执行上下文内查找,一直到全局执行上下文为止。这也就是上文中为什么任何地方都可以访问到全局变量了。因为全局变量就被放在全局执行上下文里头

  • 作用域链

根据执行上下文中变量查找的概念,是不是感觉很像原型链的查找,没错这种查找就可以称为是作用域链。

# this

this到底是是个什么东西?

在js中this一般分为三种

  • 在构造函数中,this指向当前被创建的对象
  • 在函数调用中,this指向调用函数的那个对象
  • 在call,bind,apply中,this指向传入的那个对象
  • 在箭头函数里,指向父级执行上下文里的this

在不同的情况下,this会有不同的含义,下面通过几段代码来更深层次的理解一下

// 在函数中
let obj = {
    hi:'嗨喽',
    sayHi:function (){
        console.log(this.hi)
    }
}

obj.sayHi() // 嗨喽

// 在构造函数中
let obj2 = new function (){
    this.name = 111
    console.log(this) //{name:111}
}
// 在箭头函数中,因为父级是全局执行上下文,里面并没有hi这个变量,所以输出undefined
let obj = {
    hi:'嗨喽',
    sayHi:()=>{
        console.log(this.hi) //undefined
    }
}
// 在call,bind,apply中,this会变成传入的那个对象
let o = {hi:'我是o的hi属性'}
obj.sayHi.call(o) //'我是o的hi属性'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
编辑 (opens new window)
上次更新: 2023/05/17, 18:06:44
JS数据类型那点事儿
防抖和节流

← JS数据类型那点事儿 防抖和节流→

最近更新
01
小程序实现全局状态管理
07-09
02
前端检测更新,自动刷新网页
06-09
03
swiper渲染大量数据的优化方案
06-06
更多文章>
Theme by Vdoing | Copyright © 2023-2025 UzumakiItachi | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式