粥里有勺糖

vuePress-theme-reco 粥里有勺糖    2018 - 2023
粥里有勺糖 粥里有勺糖

Choose mode

  • dark
  • auto
  • light
关于我
备战春秋
  • 心得总结
  • 校招考点汇总
  • 面经汇总
  • 复习自查
技术笔记
  • 技术教程
  • 模板工程
  • 源码学习
  • 技术概念
  • 个人作品
  • 学习笔记
计算机基础
  • 算法与数据结构
  • 操作系统
  • 计算机网络
  • 设计模式
  • 剑指offer
大前端
  • javascript
  • vue
  • html
  • css
  • 🌏浏览器专题
  • Web性能优化
  • regexp
  • node
面试
  • 问解
  • javascript
  • css
  • 手撕代码
  • 性能优化
  • 综合问题
  • 面经汇总
  • 小程序
手撕代码
  • 数据结构与算法
  • javascript
  • css
个人站点
  • GitHub (opens new window)
  • 博客园 (opens new window)
  • 掘金 (opens new window)
线上作品
  • 轻取(文件收集) (opens new window)
  • 个人图床 (opens new window)
  • 考勤小程序 (opens new window)
  • 时光恋人 (opens new window)
  • 在线简历生成 (opens new window)
留言板
Github (opens new window)
author-avatar

粥里有勺糖

285

文章

40

标签

关于我
备战春秋
  • 心得总结
  • 校招考点汇总
  • 面经汇总
  • 复习自查
技术笔记
  • 技术教程
  • 模板工程
  • 源码学习
  • 技术概念
  • 个人作品
  • 学习笔记
计算机基础
  • 算法与数据结构
  • 操作系统
  • 计算机网络
  • 设计模式
  • 剑指offer
大前端
  • javascript
  • vue
  • html
  • css
  • 🌏浏览器专题
  • Web性能优化
  • regexp
  • node
面试
  • 问解
  • javascript
  • css
  • 手撕代码
  • 性能优化
  • 综合问题
  • 面经汇总
  • 小程序
手撕代码
  • 数据结构与算法
  • javascript
  • css
个人站点
  • GitHub (opens new window)
  • 博客园 (opens new window)
  • 掘金 (opens new window)
线上作品
  • 轻取(文件收集) (opens new window)
  • 个人图床 (opens new window)
  • 考勤小程序 (opens new window)
  • 时光恋人 (opens new window)
  • 在线简历生成 (opens new window)
留言板
Github (opens new window)
  • JsInterview

    • js面试题
    • async 及 await 的特点,它们的优点和缺点分别是什么?await 原理是什么?
    • 数组哪些方法会改变自身
    • for-of与for-in的区别
    • == 和 === 有什么区别
    • ES6面试问题
    • 事件的触发过程是怎么样的?知道什么是事件代理嘛?
    • 将任意类型转为Boolean的方案
    • instanceof能正确判断对象的原因是什么
    • 如何判断数组
    • 如何判断变量类型是对象
    • 为什么要使用模块化?有哪几种方式可以实现模块化,各有什么特点?
    • null是对象吗
    • 为什么0.1+0.2!=0.3
    • 对象类型和原始类型的不同之处
    • 函数参数是对象会发生什么问题
    • window.onload与document.ready执行顺序
    • 原始类型有哪些
    • Promise 的特点是什么,分别有什么优缺点?什么是 Promise 链?Promise 构造函数执行和 then 函数执行有什么区别?
    • 如何正确判断 this?箭头函数的 this 是什么?
    • typeof能否正常判断类型
    • V8 下的垃圾回收机制是怎么样的?

如何正确判断this?箭头函数的this是什么?

vuePress-theme-reco 粥里有勺糖    2018 - 2023

如何正确判断this?箭头函数的this是什么?

粥里有勺糖 2020-04-14 面试javascript

# 如何正确判断 this?箭头函数的 this 是什么?

function foo() {
  console.log(this.a)
}
var a = 1
foo() // 1

const obj = {
  a: 2,
  foo: foo
}
obj.foo() // 2

const c = new foo() // undefined
c()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  1. 对于普通函数来说,this->window
  2. 全局作用域下,this -> window
  3. 对于对象来说,谁调用函数谁就是this
  4. new 的方式,this永远被绑定在实例上
  5. 箭头函数本身是没有this,继承外层上下文绑定的this(包裹箭头函数的第一个普通函数的this)
  6. 箭头函数使用bind,call,this无效
  7. bind/call/apply 这些改变上下文的 API 了,对于这些函数来说,this 取决于第一个参数,如果第一个参数为空,那么就是 window
  8. 不管我们给函数 bind 几次,fn 中的 this 永远由第一次 bind 决定

示例

var p1 = 1
function fn1(){
    console.log(this.p1)
}
fn1() // 1

let obj2 = {
    p2:2,
    fn2(){
        console.log(this.p2)
    }
}
obj2.fn2() // 2

var p3 = 1
function fn3() {
    this.p3 = 3
    console.log(this.p3)
}
let fn31 = new fn3() // 3

var p4 = 4
const fn4 = ()=>{
    console.log(this.p4)
}
fn4() // 4

function fn5() {
    this.p5 = 5
    return function () {
        this.p5 = 55
        return function () {
            this.p5 = 555
            return () => {
                console.log(this.p5)
            }
        }
    }
}

fn5()()()() // 555

const fn6 = ()=>{
    console.log(this.p6)
}
fn6.bind({p6:6})() // undefined
fn6.call({p6:6}) // undefined

var p7 = 7
function fn7(){
    console.log(this.p7)
}
fn7.bind({p7:77})() // 77
fn7.bind()() // 7

function fn8(){
    console.log(this.p8)
}
fn8 = fn8.bind({p8:8}).bind({p8:88}).bind({p8:888})
fn8() // 8
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

图片

一个笔试题

let obj2 = {
    name: 'obj2'
}

const obj = {
    name: 'obj',
    say1() {
        console.log(this.name)
    },
    obj1: {
        name: 'obj1',
        say2() {
            console.log(this.name);
        }
    },
    say3() {
        const fn = () => {
            console.log(this.name);
        }
        fn()
    },
    say4() {
        const fn = function () {
            console.log(this.name);
        }
        fn()
    },
    say5() {
        const fn = () => {
            console.log(this.name);
        }
        fn.call(obj2)
    },
    say6() {
        const fn = function () {
            console.log(this.name);
        }
        fn.call(obj2)
    }
}

let a = obj.say1
let b = obj.obj1.say2
a() 
b()
obj.say1()
obj.obj1.say2()
obj.say3()
obj.say4()
obj.say5()
obj.say6()
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
点击查看输出结果与题解
undefined
undefined
obj
obj1
obj
undefined
obj
obj2
1
2
3
4
5
6
7
8

题解

let a = obj.say1
a()
// 等价于
let a = function () {
    console.log(this.name)
}

// 这里的是普通的function
// 所以这里的this是window
// this.name --> window.name
// 结果为
undefined
1
2
3
4
5
6
7
8
9
10
11
12
let b = obj.obj1.say2
b()
// 等价于
let b = function () {
    console.log(this.name);
}
// 后续步骤与上面一致
// 结果为
undefined
1
2
3
4
5
6
7
8
9
obj.say1()
// 对于对象来说,谁调用函数谁就是this
// 所以这里this指的是obj
// 所以say1内的this.name --> obj.name
// 结果为
'obj'
1
2
3
4
5
6
obj.obj1.say2()
// 与上一个同理
// 对于对象来说,谁调用函数谁就是this
// say2内的 this.name --> obj.obj1.name
// 结果为
'obj1'
1
2
3
4
5
6
obj.say3()
// 函数内部有个箭头函数
// 箭头函数的this由其上下文决定
// 所以这里的上下文为say3 的function
// 等价于
obj = {
    // ...precode
    say3(){
        console.log(this.name);
    }
    // ...behcode
}
// 对于对象来说,谁调用函数谁就是this
// 所以这里的 this.name -> obj.name
// 结果为
'obj'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
obj.say4()
// 函数内部为普通函数
// 普通函数的this为window
// 所以其this指向window
// this.name --> window.name
// 结果为
undefined
1
2
3
4
5
6
7
obj.say5()
// 其内部为箭头函数
// 箭头函数使用call无效
// 箭头函数的this由其上下文决定
// 所以这里的this指向由包裹其的function决定
// 又因为 对于对象来说,谁调用function谁就是this
// 所以这里this 指向 obj
// this.name --> obj.name
// 结果为
'obj'
1
2
3
4
5
6
7
8
9
10
obj.say6()
// 函数内部为普通函数
// 使用call改变了其this指向
// 所以此时this 指向 obj2
// this.name --> obj2.name
// 结果为
'obj2'
1
2
3
4
5
6
7
Edit this page (opens new window)
Last Updated: 2022/5/15 12:46:34