关于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 一个函数时,传入的 context。
- 如果你的函数调用形式不是 call 形式,请按照「转换代码」将其转换为 call 形式。
以后你遇到所有跟 this 有关的笔试题,都不会有疑问了。
完。
关于this指向性的问题的更多相关文章
- 关于Python的self指向性
Python的self是指向类的实例化对像,而不是类本身,每次调用类的实例化即self指向此实例化对像,如下代码: class Person: def __init__(self,name): sel ...
- JS中this的指向性问题
一.this用于访问当前方法所属的对象,谁调用的方法,方法就属于谁 // 普通函数 let obj = { a : 12, fn() { console.log(this == obj); // tr ...
- 深入浅出聊优化:从Draw Calls到GC
前言: 刚开始写这篇文章的时候选了一个很土的题目...<Unity3D优化全解析>.因为这是一篇临时起意才写的文章,而且陈述的都是既有的事实,因而给自己“文(dou)学(bi)”加工留下的 ...
- VMware-存储断网之后无法添加vmx到清单
由于发生了单点故障,笔者最近处理了一个case,其中一些经验非常希望和大家分享. 问题原因: Technorati 标签: VMware,虚拟机,vmx,锁定,干货 某环境使用VMware的ESXi5 ...
- 如何写出让java虚拟机发生内存溢出异常OutOfMemoryError的代码
程序小白在写代码的过程中,经常会不经意间写出发生内存溢出异常的代码.很多时候这类异常如何产生的都傻傻弄不清楚,如果能故意写出让jvm发生内存溢出的代码,有时候看来也并非一件容易的事.最近通过学习< ...
- ViewController的生命周期分析和使用
iOS的SDK中提供很多原生ViewController,大大提高了我们的开发效率,下面是我的一些经验. 一.结构 按结构可以对iOS的所有ViewController分成两类:1.主要用于展示内容的 ...
- Javascript中数组方法和方法的扩展
最近一直在努力的恶补javascript中的各种知识,比如说闭包,作用域,继承,构造函数,变量,内置对象等概念.同时,也在学习着ES6的新知识.最近想给大家分享的就是数组实例方法的练习以及如何去扩展一 ...
- KEGG数据库
参考:KEGG数据库中文教程 - 博奥 &[学习笔记]KEGG数据库 - 微信 学习一个技能最主要的事情你必须知道,那就是能通过它来做什么? KEGG数据库里面有什么? 如何查询某一特定的代 ...
- NoSQL生态系统——事务机制,行锁,LSM,缓存多次写操作,RWN
13.2.4 事务机制 NoSQL系统通常注重性能和扩展性,而非事务机制. 传统的SQL数据库的事务通常都是支持ACID的强事务机制.要保证数据的一致性,通常多个事务是不可能交叉执行的,这样就导致了可 ...
随机推荐
- kmeans笔记
1.算法过程 a.随机选取k个初始点作为中心点 b.依次计算剩余所有点分别与哪个初始点距离较近,则该点属于哪个簇 c.移动中心点到现在的簇的中心 d.重复b,c两步,直到中心点不再变化算法结束 2.优 ...
- MySQL crash-safe replication【转载】
本文来自david大神的博客,innodb技术内幕的作者. http://insidemysql.blog.163.com/blog/static/202834042201385190333/ MyS ...
- dedecms自定义表单提交成功后提示信息修改和跳转链接修改
我们在用dedecms自定义表单提交成功后提示信息一般是"Dedecms 提示信息",这个要怎么改成自己想要的文字呢?还有就是提示页停留时间,目前估计就2秒,太快了,要如何设置长点 ...
- 报错解决——OSError: libdarknet.so: cannot open shared object file: No such file or directory
在python目录下打开终端,输入 python darknet.py 结果报错 Traceback (most recent call last): File “darknet.py”, line ...
- 前端开发---HTML---介绍
阅读目录 1.标签 2.HTML目录结构 3.HTML注释 一.web1.0时代的网页制作 静态网页,所谓的静态网页就是没有与用户进行交互而仅仅供读者浏览的网页,我们当时称为“牛皮癣”网页.例如一篇Q ...
- 怎样打开U盘最安全
为了避免电脑使用U盘时,通过双击,或者右击盘符时,导致把病毒感染至整个电脑,因此使用下面的方法,可使U盘病毒不被激活传播. 在取消了U盘自动运行的情况下(在组策略中一定要关闭自动运行功能,否则只要一插 ...
- Flappy Bird
在网上学习了下“65行 JavaScript 代码实现 Flappy Bird 游戏”(http://blog.jobbole.com/61842/),main.js 如下: // Initializ ...
- 实例:使用puppeteer headless方式抓取JS网页
puppeteer google chrome团队出品的puppeteer 是依赖nodejs和chromium的自动化测试库,它的最大优点就是可以处理网页中的动态内容,如JavaScript,能够更 ...
- Spark算子之aggregateByKey详解
一.基本介绍 rdd.aggregateByKey(3, seqFunc, combFunc) 其中第一个函数是初始值 3代表每次分完组之后的每个组的初始值. seqFunc代表combine的聚合逻 ...
- eclipse中Tomcat服务器缓存位置,以及清理Tomcat缓存
在Eclipse中进行Web开发,一般都会将项目直接在Eclipse中的Tomcat服务器运行,有时候修改了程序和页面之后,运行结果还是原来的 tomcat服务器中缓存的程序或者页面,需要清理缓存之后 ...