博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
快速理解JavaScript中this的用法与陷阱
阅读量:6470 次
发布时间:2019-06-23

本文共 1690 字,大约阅读时间需要 5 分钟。

this是 JS 这门语言的魅力之一——灵活方便又难以捉摸,即使是有经验的程序员,如果不仔细也有可能搞错,关于this的用法也成为许多公司的经典面试题。

如果你写过 Java ,你可能接触过this——一般指向当前对象,实际上,这时候this的含义已经确定了,因为Java属于编译期绑定,而JS属于运行期绑定,所以导致this的含义在运行过程中可能有多种变化。

进一步说,this和它声明环境无关,而完全取决于他的执行环境。务必牢记这句话。

//读以下代码之前,必须先阅读《哈利·波特》原著。(笑)var name = '罗恩';var aaa = {    name: '哈利',    say: function () {        console.log(this.name);    }}var bbb = {    name: '赫敏',    say: aaa.say}var ccc = aaa.say;aaa.say();    //哈利bbb.say();    //赫敏ccc();        //罗恩

我们看第一行,aaa.say()调用的是aaa对象本身的say()方法,此时this指代的是aaa对象本身,所以此时输出当然就是aaa对象的name属性值。

第二行,bbb.say();输出赫敏一定和JS新手们的常识不相符,其实只要牢记“this取决于执行环境”就能想明白。bbb对象是怎么声明自身的say方法的呢?它只是把aaa对象的say方法引用过来,注意,引用的是一个方法而非一个对象,而aaa.say存储的是一个匿名函数,所以这种写法和以下代码并没有什么区别。

var bbb = {    name: '赫敏',    say: function () {        console.log(this.name);    }}

第三行的ccc()是在最外层执行,也就是在全局对象window下。所以ccc()执行的时候this指代的就是window对象。而在window对象下声明了name属性,就相当于window.name = '罗恩',输出的当然就是罗恩

当然,也有特殊情况,那就是 setTimeout 和 setInterval 。

我把开头的aaa对象的声明改成:

var aaa = {    name: '哈利',    getName: function () {        setTimeout(function(){            console.log(this.name);        },100)    }}

仅仅是在console.log(this.name)外面套了一个setTimeout,猜猜原来三行的输出会是什么?

答案:3个罗恩

也就是说,三次this,指代的都是window对象。

关于为什么会这样,我这里暂时不详细展开,因为涉及到JS异步回调的知识,如果你仅仅想快速熟悉this的用法,那么只要记住这个特殊情况即可。这个知识点曾经是阿里还是小米的面试题。

显然,三个罗恩不是我想要的,毕竟韦斯莱夫人的孩子已经够多了。那么我们只需稍微改写一下这个方法:

getName: function () {        //在setTimeout外存储this指代的对象        var that = this;        setTimeout(function(){            //this.name变成了that.name            console.log(that.name);        },100)    }

输出就又正常了。

显然,that并不是一个关键字,只是一个大家解决这种情况时约定俗成的名字。如果你愿意,也可以叫thatGuy。当然,考虑到可能会有其他人维护你的代码,还是用that比较好。

之所以写这篇文章,是为了我下一篇文章做铺垫:

《快速理解JavaScript中apply()和call()的用法》
敬请期待~~

转载地址:http://nujko.baihongyu.com/

你可能感兴趣的文章
蔡超:入门 Go 语言必须跨越的五个思维误区
查看>>
使用Akka Actor和Java 8构建反应式应用
查看>>
curl常用命令详解
查看>>
saltstack 添加计划任务
查看>>
Puppet module命令参数介绍(六)
查看>>
《UNIX网络编程》中第一个timer_server的例子
查看>>
CISCO 路由器(4)
查看>>
网络服务搭建、配置与管理大全(Linux版)
查看>>
Silverlight 5 Beta新特性[4]文本缩进控制
查看>>
springMVC多数据源使用 跨库跨连接
查看>>
简单java在线测评程序
查看>>
录音和朗诵的实现
查看>>
Git服务端和客户端安装笔记
查看>>
Spring Security(14)——权限鉴定基础
查看>>
IntelliJ IDEA快捷键
查看>>
【iOS-cocos2d-X 游戏开发之十三】cocos2dx通过Jni调用Android的Java层代码(下)
查看>>
MongoDB的基础使用
查看>>
进程间通信——命名管道
查看>>
LINUX 重定向的知识
查看>>
ssh登陆不需要密码
查看>>