this 去哪?

本文写于 2020 年 4 月 26 日

let obj = {
foo() {
console.log(this)
},
}
let bar = obj.foo
obj.foo() // 打印出的 this 是 obj
bar() // 打印出的 this 是 window

最后两行函数的值为什么不一样???

之前关于函数的文章里写过了,let bar = obj.foo可以让bar()obj.foo()等价,那为什么 this 指向不一样?

在学 React 的时候,很多人会发现有个很烦人的操作,就是在constructor里面,需要bind(this)

首先需要从函数的调用开始讲起。

ES5 里面有三种函数调用形式:

foo(p1, p2)
console.log('================')
obj.foo(p1, p2)
console.log('================')
foo.call(obj, p1, p2)
/*
* 或者apply或者bind,这三个都是用来绑定this的
*/

乍看之下,前两种简单,后面一种复杂。很多人就选择完全不使用后面的call()

但实际上,后面的才是我们真正的写法,前面的都可以等价的变成该种写法:

func.call(context, p1, p2)

foo(p1, p2) 等价于 foo.call(undefined, p1, p2)

obj.foo(p1, p2) 等价于 obj.foo.call(obj, p1, p2)

很多人特别喜欢死记硬背这个 this 的指向,“谁调用 this 就指向谁”blablabla……

但实际上,this 是要为我们所用的,我想让你指向谁,你就要指向谁。我们不应该被它牵着走。

先看foo(p1, p2)中的 this 如何确定。

当你写下面代码时:

function foo() {
console.log(this)
}
foo()

等价于

function foo() {
console.log(this)
}
foo.call(undefined) // 可以简写为 foo.call()

按理说打印出来的 this 应该就是 undefined 了吧,但是浏览器里有一条规则:

如果你传的第一个参数是null或者undefined, window 对象就是默认的。因此上面的打印结果是 window。

如果希望这里的 this 不是 window 该怎么做呢?

很简单:

func.call(obj) // 那么里面的 this 就是 obj 对象了

再看obj.foo(p1, p2) 里的 this 如何确定:

let obj = {
foo() {
console.log(this)
},
}
obj.foo()

他本身的指向就是 obj 自己,所以写成call()也就是:obj.foo.call(obj)

回到最上面的代码。

let obj = {
foo() {
console.log(this)
},
}
let bar = obj.foo
obj.foo() // 转换为 obj.foo.call(obj),this 就是 obj
bar()
// 转换为 bar.call()
// 由于没有传 context
// 所以 this 就是 undefined
// 最后浏览器给你一个默认的 this —— window 对象

提一个有趣的用法:如果把函数放到数组里,然后数组[]调用函数,this 指向哪里呢?

function fn() {
console.log(this)
}
let arr = [fn, fn2]
arr[0]()

这里面的 this 是什么呢?

我们可以把arr[0]()理解为arr.0(),虽然后者的语法错了,但是形式与转换代码里的obj.foo(p1, p2)对应上了!

arr[0]() => arr.0() => arr.0.call(arr)

那么里面的 this 就是 arr 了。

总之,this 就是你 call 一个函数时,传入的第一个参数。

(完)

this 去哪?的更多相关文章

  1. 神马玩意,EntityFramework Core 1.1又更新了?走,赶紧去围观

    前言 哦,不搞SQL了么,当然会继续,周末会继续更新,估计写完还得几十篇,但是我会坚持把SQL更新完毕,绝不会烂尾,后续很长一段时间没更新的话,不要想我,那说明我是学习新的技能去了,那就是学习英语,本 ...

  2. 就这么漂来漂去---一个毕业三个月的java程序员的裸辞风波

    注:这并不是一篇技术文章,而是记录了我这几个月经历的入职,裸辞,找工作的心路历程,简单介绍一个博主的情况,我是16年毕业生,校招进了一家北京的公司,java开发,和很多年轻人一样,干了一段时间,我发现 ...

  3. 去IOE的一点反对意见以及其他

    某天在机场听见两老板在聊天,说到他们目前销售的报表老跟不上的问题,说要请一个人,专门合并和分析一些发过来的excel表格,我真想冲上去说,老板,你需要的是一个信息处理的系统,你需要咨询么.回来一直耿耿 ...

  4. IM 去中心化概念模型与架构设计

    今天打算写写关于 IM 去中心化涉及的架构模型变化和设计思路,去中心化的概念就是说用户的访问不是集中在一个数据中心,这里的去中心是针对数据中心而言的. 站在这个角度而言,实际上并非所有的业务都能做去中 ...

  5. JavaScript 函数节流和函数去抖应用场景辨析

    概述 也是好久没更新 源码解读,看着房价蹭蹭暴涨,心里也是五味杂陈,对未来充满恐惧和迷茫 ...(敢问一句你们上岸了吗) 言归正传,今天要介绍的是 underscore 中两个重要的方法,函数节流和函 ...

  6. 回车去替换铵钮的click点击功能

    某一时候,我们不想在form的所有必填的域均完成之后,再去使用mouse去点击铵钮来提交数据.而是直接按回车去focus提交的铵钮来提交. 可以写jQuery script程序:

  7. app使用微信支付成功后,点击返回到该app却跳到另外一个app去了

    刚接手了公司iOS的两个APP, 现在碰到了这样一个问题: 有一台iPhone在一个APP中使用了微信支付,支付成功后,点击返回到该APP,结果却跳到了另外一个APP去了. 这两个APP都是公司开发的 ...

  8. [LeetCode] Serialize and Deserialize BST 二叉搜索树的序列化和去序列化

    Serialization is the process of converting a data structure or object into a sequence of bits so tha ...

  9. [LeetCode] Serialize and Deserialize Binary Tree 二叉树的序列化和去序列化

    Serialization is the process of converting a data structure or object into a sequence of bits so tha ...

  10. openwrt下部署adbyby去广告大师 免luci 带自启动,自动开启透明代理

    最近朋友送了个360老路由器 C301,于是乎就掉进了智能路由器的坑, 玩智能路由器第一件事一定是去广告, 要么怎么对得起智能路由器- -! 路由器去广告当然首推广告屏蔽大师 www.adbyby.c ...

随机推荐

  1. centos简单命令备忘

    1.查看当前目录 [root@instance-aif30iaj bin]# df -h 2.查看指定目录 在命令后直接放目录名,比如查看"usr"目录使用情况: [root@in ...

  2. ACM - 图论 - P3385 负环

    P3385 负环 题目描述 给定一个 \(n\) 个点的有向图,请求出图中是否存在从顶点 \(1\) 出发能到达的负环. 负环的定义是:一条边权之和为负数的回路. 输入格式 本题单测试点有多组测试数据 ...

  3. 汽车最强大脑ECU和单片机是什么关系

    先上图一张,据说这是某个F1赛车的动力总成ECU. 定睛一看,这不就是两个英飞凌的单片机的合体嘛. ECU的定义 ECU原来指的是engine control unit,即发动机控制单元,特指电喷发动 ...

  4. gulp详细基础教程

    一.gulp简介 1.gulp是什么? gulp是前端开发过程中一种基于流的代码构建工具,是自动化项目的构建利器:它不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成: ...

  5. java中final变量的用法

    4.4 final变量    final变量的数值不能在初始化之后进行改变(你希望a=3,有很多用到a的场合, 你当然不能在程序中就用3来代替a). 比如: final int h = 0; 想像有一 ...

  6. 三种获取数据的方法fetch和ajax和axios

    一 .fetch用法 ( 本人比较喜欢fetch,代码精简,虽说目前axios比较流行,但是fetch很多大厂已经开始用fetch开始封装了, 我觉得以后fetch会取代axios和ajax ) 1. ...

  7. jboss学习1之EJB和JBOSS的宏观理解

    一.中间件(Middleware)         先来看一张图:         中间件,也就是图中的Middleware,他的作用是什么呢?        简单来说,中间件就是操作系统和应用程序之 ...

  8. Vue Element ui密码框校验

    <el-form-item prop="repeat_Password" class="userName_color"> <el-input ...

  9. 【论文阅读】ICLR 2022: Scene Transformer: A unified architecture for predicting future trajectories of multiple agents

    ICLR 2022: Scene Transformer: A unified architecture for predicting future trajectories of multiple ...

  10. 想减少代码量,快设置一个有感知的 Aware Spring Bean

    摘要:正常情况下,Spring 中的 Bean 对 Spring 是无感知的,Spring 框架提供了这种扩展能力,能让一个 bean 成为有感知的. 本文分享自华为云社区<有感知的 Aware ...