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. scrapy--使用案例

    1.scrapy框架 1.1 安装scrapy pip3 install wheel 下载twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#twis ...

  2. ros中关于节点、话题、服务以及自定义消息等在终端中的常用命令

    以下面的计算力图说明 节点相关常用命令 在终端中查看项目中有哪些节点命令:rosnode list 有了节点信息想要查看节点中到底发布订阅了哪些话题,作为服务端服务类型或者作为客户端需要的服务类型以上 ...

  3. Architecture Review Board

    Architecture Review Board What's an Architecture Review? Architecture design is not a one-time final ...

  4. HTML5打造原生应用——Ionic框架简介与Ionic Hello World

    试了试用Ionic框架打造了两个应用,然后在Google Play上架了. 程序语言答人 教你设计物联网 更有意思的是这是在一周的业余时间内完成的三个应用中的两个,接着让我们看看这个框架如何实现高效地 ...

  5. 推荐一款强大的轻量级模块化WEB前端快速开发框架--UIkit

    前言 今天给大家分享一款强大的轻量级模块化WEB前端快速开发框架--UIkit 到目前(2016-06-20)为止,UIkit在github上的Forks已达到了1350个,而Stars更是达到了69 ...

  6. 居中的css:完全指南(翻译)

    这里主要参考的是CHRIS COYIER写的一篇的文章(点击查看),主要讲了关于css水平.垂直居中的一些方法,每个方法后面都有一个demo,可以在线查看效果. 1 水平 水平居中有行内元素和块元素, ...

  7. vue打包后空白页问题全记录 (background路径,css js404,jsonp等);

    总结一下vue打包后问题全记录:大部分开发者webpack基本上都是拿来就用的(并没有系统化的研究). 一 >>> 打包之后的静态文件不能直接访问:(例如dist)打包后搭个服务器才 ...

  8. 讲清楚之 javascript 参数传值

    讲清楚之 javascript 参数传值 参数传值是指函数调用时,给函数传递配置或运行参数的行为,包括通过call.apply 进行传值. 在实际开发中,我们总结javascript参数传值分为基本数 ...

  9. MySQL 中 SQL语句大全(详细)

    sql语句总结 总结内容 1. 基本概念 2. SQL列的常用类型 3. DDL简单操作 3.1 数据库操作 3.2 表操作 4. DML操作 4.1 修改操作(UPDATE SET) 4.2 插入操 ...

  10. Visual Studio 打包和安装 exe

    # Visual Studio 打包和安装 exe > **小型项目(无复杂的库)** //VS2022 作为演示平台   > 1.解决方案配置 = Release   > 2.解决 ...