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. Java 中,抽象类与接口之间有什么不同?

    Java 中,抽象类和接口有很多不同之处,但是最重要的一个是 Java 中限制一个 类只能继承一个类,但是可以实现多个接口.抽象类可以很好的定义一个家族类 的默认行为,而接口能更好的定义类型,有助于后 ...

  2. Effective Java —— 谨慎覆盖clone

    本文参考 本篇文章参考自<Effective Java>第三版第十三条"Always override toString",在<阿里巴巴Java开发手册>中 ...

  3. 用 JWT 实现小程序本地用户标识

    panda-chat-room 继上节「理解小程序 session」 ,本节我们以 jsonwebtoken 来实现小程序端的用户状态标识.如果你对小程序用户登录流程及 session 管理还有些疑惑 ...

  4. D2Admin 8月更新: 高级数据持久化|标签页右键|模块化等

    剧透:这次,D2Admin 带来了其它同类模板都没有的"花式"数据持久化功能,以及极少同类产品才有的标签页右键控制... 概述 D2Admin 7月份更新到了 1.1.5 版本 相 ...

  5. 聊一聊Web端的即时通讯

    聊一聊Web端的即时通讯 Web端实现即时通讯的方法有哪些? - 短轮询 长轮询 iframe流 Flash Socket 轮询 客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并 ...

  6. 【uniapp 开发】智能温控开关 (环状图)

    index.vue <template> <view> <view class="qiun-columns"> <uCharts id=& ...

  7. nodejs教程---基于expressJs框架,实现文件上传(upload)?

    文件上传功能在nodejs初期是一件很难实现的功能,之后出现了formidable勉强能解决这个问题,但是express框架出现之后基于这个框架开发的中间件有更好的方法来处理文件上传,这个中间件就是m ...

  8. Mybatis多表查询出现null字段

    写在前面 今天使用mybatis实现多表查询,记录一下其中遇到的坑 mybatis多表查询简介 mybatis多表查询主要有两个方式,通俗易懂的来说就是一个是查询少量属性(association),一 ...

  9. 让我们写一个 Win32 文本编辑器吧 - 2. 计划和显示

    让我们写一个 Win32 文本编辑器吧 - 2. 计划和显示 如果你已经阅读了简介,相信你已经对我们接下来要做的事情有所了解. 本文,将会把简介中基础程序修改为一个窗体应用程序.并对编辑器接下来的编辑 ...

  10. route -n 讲解

    我们经常会出现临时添加路由,或者是路由重启路由丢失等导致网络不通的情况,上网查发现很多介绍或者没有实验跟进导致理解的时候很费劲的情况,可能人家认为是比较简单的事情了,但是很多不尽然,老手也不一定能很快 ...