转载自知乎大神---this 的值到底是什么?一次说清楚
你可能遇到过这样的 JS 面试题:
var obj = {
foo: function(){
console.log(this)
}
}
var bar = obj.foo
obj.foo() // 打印出的 this 是 obj
bar() // 打印出的 this 是 window
请解释最后两行函数的值为什么不一样。
-------
初学者关于 this 的理解一直很模糊。今天这篇文章就要一次讲清楚了。
而且这个解释,你在别的地方看不到。看懂这篇文章,所有关于 this 的面试题,都是小菜。
有用请点赞。
函数调用
首先需要从函数的调用开始讲起。
JS(ES5)里面有三种函数调用形式:
func(p1, p2)
obj.child.method(p1, p2)
func.call(context, p1, p2) // 先不讲 apply
一般,初学者都知道前两种形式,而且认为前两种形式「优于」第三种形式。
从看到这篇文章起,你一定要记住,第三种调用形式,才是正常调用形式:
func.call(context, p1, p2)
其他两种都是语法糖,可以等价地变为 call 形式:
func(p1, p2) 等价于
func.call(undefined, p1, p2)
obj.child.method(p1, p2) 等价于
obj.child.method.call(obj.child, p1, p2)
请记下来。(我们称此代码为「转换代码」,方便下文引用)
至此我们的函数调用只有一种形式:
func.call(context, p1, p2)
这样,this 就好解释了
this,就是上面代码中的 context。就这么简单。
this 是你 call 一个函数时传的 context,由于你从来不用 call 形式的函数调用,所以你一直不知道。
先看 func(p1, p2) 中的 this 如何确定:
当你写下面代码时
function func(){
console.log(this)
}
func()
等价于
function func(){
console.log(this)
}
func.call(undefined) // 可以简写为 func.call()
按理说打印出来的 this 应该就是 undefined 了吧,但是浏览器里有一条规则:
如果你传的 context 就 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)
因此上面的打印结果是 window。
如果你希望这里的 this 不是 window,很简单:
func.call(obj) // 那么里面的 this 就是 obj 对象了
再看 obj.child.method(p1, p2) 的 this 如何确定
var obj = {
foo: function(){
console.log(this)
}
}
obj.foo()
按照「转换代码」,我们将 obj.foo() 转换为
obj.foo.call(obj)
好了,this 就是 obj。搞定。
回到题目:
var obj = {
foo: function(){
console.log(this)
}
}
var bar = obj.foo
obj.foo() // 转换为 obj.foo.call(obj),this 就是 obj
bar()
// 转换为 bar.call()
// 由于没有传 context
// 所以 this 就是 undefined
// 最后浏览器给你一个默认的 this —— window 对象
[ ] 语法
function fn (){ console.log(this) }
var arr = [fn, fn2]
arr[0]() // 这里面的 this 又是什么呢?
我们可以把 arr[0]( ) 想象为arr.0( ),虽然后者的语法错了,但是形式与转换代码里的 obj.child.method(p1, p2) 对应上了,于是就可以愉快的转换了:
arr[0]()
假想为 arr.0()
然后转换为 arr.0.call(arr)
那么里面的 this 就是 arr 了 :)
总结
- this 就是你 call 一个函数时,传入的第一个参数。(请务必背下来「this 就是 call 的第一个参数」)
- 如果你的函数调用形式不是 call 形式,请按照「转换代码」将其转换为 call 形式。
以后你遇到所有跟 this 有关的笔试题,都不会有疑问了。
完。
更多精彩教程,请看我的首页加 QQ 群。
P.S.
- 使用 new 时,情况又不一样,可以看另一篇文章《JS 的 new 到底是干什么的?》。
- 后续篇《你怎么还没搞懂 this? - 知乎专栏》
- 有人说你怎么不讲 strict mode 呢,strict mode 也会影响 this 呀。我认为 strict mode 只是影响了 context 的默认值而已,你看懂此文稍微看看 strict mode 就懂了。我只讲最重要的内容。
- 有人问怎么不讲 bind 对 this 的影响。那是因为 bind 本质就是自动在你调用一个函数的时候,把 context 换掉而已,你看看 bind 的 polyfill 就知道,其核心依然是 apply(跟 call 差不多)。
转载自知乎大神---this 的值到底是什么?一次说清楚的更多相关文章
- 转自知乎大神----JS 的 new 到底是干什么的?
大部分讲 new 的文章会从面向对象的思路讲起,但是我始终认为,在解释一个事物的时候,不应该引入另一个更复杂的事物. 今天我从「省代码」的角度来讲 new. --------------------- ...
- 转自知乎大神---什么是 JS 原型链?
我们知道 JS 有对象,比如 var obj = { name: 'obj' } 我们可以对 obj 进行一些操作,包括 「读」属性 「新增」属性 「更新」属性 「删除」属性 下面我们主要来看一下「读 ...
- 转自知乎大神----JS 闭包是什么
大名鼎鼎的闭包!这一题终于来了,面试必问. 请用自己的话简述 什么是「闭包」. 「闭包」的作用是什么. --------------------------------------- 首先来简述什么是 ...
- 项目管理模式:外瀑布内敏捷(有人称为“信封法”)--转自知乎大神:CORNERSTONE
作者:CORNERSTONE 链接:https://www.zhihu.com/question/265968122/answer/878124580 来源:知乎 著作权归作者所有.商业转载请联系作者 ...
- wire与reg的区别?转载大神!
本文转自:http://www.cnblogs.com/thymon/archive/2010/06/09/1754541.html //------------------------------- ...
- 老杜告诉你java小白到大神是怎么炼成的(转载)
老杜告诉你java小白到大神是怎么炼成的 1. 学习前的准备 一个好的学习方法(应该怎么学习更高效): 一个合格的程序员应该具备两个能力 有一个很好的指法速度(敲代码快) 有一个很好的编程思想(编程思 ...
- iOS组件化思路-大神博客研读和思考
一.大神博客研读 随着应用需求逐步迭代,应用的代码体积将会越来越大,为了更好的管理应用工程,我们开始借助CocoaPods版本管理工具对原有应用工程进行拆分.但是仅仅完成代码拆分还不足以解决业务之间的 ...
- 对话机器学习大神Yoshua Bengio(下)
对话机器学习大神Yoshua Bengio(下) Yoshua Bengio教授(个人主页)是机器学习大神之一,尤其是在深度学习这个领域.他连同Geoff Hinton老先生以及 Yann LeCun ...
- [转帖] select、poll、epoll之间的区别总结[整理] + 知乎大神解答 https://blog.csdn.net/qq546770908/article/details/53082870 不过图都裂了.
select.poll.epoll之间的区别总结[整理] + 知乎大神解答 2016年11月08日 15:37:15 阅读数:2569 http://www.cnblogs.com/Anker/p/3 ...
随机推荐
- Linux环境下使用n更新node版本失败的原因与解决
Linux环境为CentOS 6.5 64位,阿里云低配服务器...学生优惠,然而下个月即将过期,真是个悲伤的故事 很久之前就安装了node,但是一直没有进行过升级,近日因为将部分异步代码更新为采用原 ...
- 【转】Spring Boot干货系列:(一)优雅的入门篇
转自Spring Boot干货系列:(一)优雅的入门篇 前言 Spring一直是很火的一个开源框架,在过去的一段时间里,Spring Boot在社区中热度一直很高,所以决定花时间来了解和学习,为自己做 ...
- PAT甲题题解-1044. Shopping in Mars (25)-水题
n,m然后给出n个数让你求所有存在的区间[l,r],使得a[l]~a[r]的和为m并且按l的大小顺序输出对应区间.如果不存在和为m的区间段,则输出a[l]~a[r]-m最小的区间段方案. 如果两层fo ...
- 四则运算 SPEC 20160911
本文档随时可能修改,并且没有另行通知. 请确保每一次在开始修改你的代码前,读标题中的日期,如果晚于你上次阅读, 请重读一次. 教师节你去探望初中数学老师,她感叹你当年真是个优秀学生啊,从来不报怨作 业 ...
- Spherical Hashing,球哈希
1. Introduction 在传统的LSH.SSH.PCA-ITQ等哈希算法中,本质都是利用超平面对数据点进行划分,但是在D维空间中,至少需要D+1个超平面才能形成一个封闭.紧凑的区域.而球哈希方 ...
- 为elasticSearch开发c++接口
一. ElasticSearch是什么 ElasticSearch是目前开源全文搜索引擎的首选,可以快速存储,搜索和分析海量数据.Stack Overflow,Github等都在使用. Elas ...
- Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 0. 准备工作
一.关于 Python Python 是全球使用人数增长最快的编程语言!它易于入门.功能强大,从 Web 后端 到 数据分析.人工智能,到处都能看到 Python 的身影. Python 有两个主要的 ...
- 如何用Delphi开发网游外挂
1.动作式,所谓动作式,就是指用API发命令给窗口或API控制鼠标.键盘等,使游戏里的人物进行流动或者攻击,最早以前的“石器”外挂就是这种方式.2.本地修改式,这种外挂跟传统上的一些游戏修改器没有两样 ...
- 安装spring-tool-suite插件
spring-tool-suite是一个非常好用的spring插件,由于eclipse是一个很简洁的IDE,因此许多插件,需要我们自己去手动下载.而Spring-tool-suite插件即是其中之一. ...
- python315题
目录 Python基础篇 1:为什么学习Python 2:通过什么途径学习Python 3:谈谈对Python和其他语言的区别 Python的优势: 4:简述解释型和编译型编程语言 5:Python的 ...