ES4&&箭头函数中的this指向问题

问题

学习ES6箭头函数的时候,了解到箭头函数中的this与ES4中的this很不一样。ES4中this指向调用方法的对象,而ES6箭头函数中,函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
听上去并不难,但是实际应用过程中,发现自己对箭头函数中的this的判断简直一塌糊涂。不过在不断的使用、测试过程中,总算发现了一点规律,理解了什么叫做定义时所在的对象,而不是使用时所在的对象
为了便于理解,将理论与实际结合,我准备了几段代码,涉及到常见的几种情况,分析如何判断this的指向
在写这篇blog的时候,在不断的实验与思考中,我感觉自己总结出了在任何情况下都能判断this指向的规律,这是一种比较靠近原理层面的解释逻辑,经过测试,逻辑自洽且圆润。赶紧把灵感记录下来,以作备忘

演示

正式开始前有几点要牢牢记住,这算是判断this指向的总纲:

  1. 就近原则,this的判断过程就是一个沿着作用域链向上查找的过程,找到了最近的this指向就不要再向上查找了
  2. 箭头函数中实际上是没有this的,所以箭头函数中的this与上层最近的非箭头函数作用域中的this指向相同
    • 箭头函数也就这么一点特殊:箭头函数本身没有this
  3. 所有的this指向,指向的其实并不是当前对象/函数,而是当前作用域的执行环境
  4. 构造函数特殊在new操作符,会将构造函数的指向对象赋给新生的这个实例
    • 如果没有new操作符,构造函数只是一个普通的函数,定义在全局中,执行环境也是全局,this指向window

Tip:找{}大括号,当前this所属作用域是被哪个大括号包裹,一般就是this的指向,箭头函数要向上找一级大括号。

代码一:验证总纲第三点

总纲三:所有的this指向,指向的其实并不是当前对象/函数,而是当前作用域的执行环境

对象:
    let user = {
        test:this,
        show:function(){
            console.log(this);
        }
    };

    console.log(user.test);  // Window
    user.show();             // user

在这里插入图片描述
show的执行环境是user对象,user的执行环境是Window对象,这就很清楚明白了。

构造函数:
function User(name,age){

        this.age = age;
        this.name = name;
        this.test = this;

        this.show = function(){
            console.log(this);
        }
    }

    let user = new User;

    console.log(user.test);     // user
    user.show();                // user

在这里插入图片描述

解析:
show的执行环境是User,没毛病。
但是User构造函数的执行环境本来应该是Window,只是创建对象的时候,new关键字将构造函数中this赋给了新建对象user

function test(){
        console.log(this);
    }

    test();      // Window
    

普通函数中this指向它的执行环境Window,this。如果构造函数不通过new创建对象,其中的this也应该指向Window

代码二:对象中的箭头函数

 let obj = {
        a:10,
        test:this,

        show:()=>{

            }
    };

    obj.show();     // Window
    console.log(obj.test);      // Window

[外链图片转存失败(img-F7DSlPz6-1566699180946)(media/15663869460267/15664351048642.jpg)]
show为箭头函数,箭头函数本身没有this,强行使用,它的this与最近的作用域的this指向相同,即它的this与obj的this相同。obj对象的执行环境是Window,this指向Window。

代码三:回调函数

因为经常用到,这里以计时器setTimeout为例。

   setTimeout(function(){
       console.log(this);   // Window
   },500);


    let obj = {
       name:"Linya",
        age:18,
        show:function(){
            setTimeout(function(){
                console.log(this);
            },500);
        }
    };

    obj.show();     // Window

在这里插入图片描述
其实回调函数中的this是默认指向Window对象的,因为其本质上就是在函数内callback,并没有. 符号前的对象调用。

下面代码就是模拟setTimeout的执行结构

 function User(){


        this.test = function(fn){

            console.log(1);
            console.log(this);  // User
            fn();
        }
    }


    let user = new User();
    user.test(function(){
        console.log(this);  // Window

    })

test方法与setTimeout类似,都是一个对象的方法,且参数都有回调函数。其中的回调函数中的this都指向了Window。这说明回调函数中的this并不是随着作用域链向上移动,而是直接指向了最根本的Window对象

一个方法的参数如果是回调函数,那么他就无法很好的调用方法所处对象中的属性。
解决办法:使用箭头函数

 let obj = {
       name:"Linya",
        age:18,
        show:function(){
            setTimeout(()=>{
                console.log(this);
            },500);
        }
    };

    obj.show();     // Obj

箭头函数中没有this,强行使用,this指向与上一级作用域this指向相同,即与show方法的this指向相同。show的执行环境为obj,this指向obj

在这里插入图片描述

参考

JS回调函数中的this指向

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值