前言

javascript中的this是啥东西?为啥我们经常被他搞得晕头转向不知所以?他是恶魔?是天使 ?是怪胎?让我们一起来揭开它那神秘的面纱。

<!--more-->

他是个啥

首先this是Javascript语言的关键字之一,指函数运行时的当前对象。那既然和函数运行有关,js中函数有哪些调用模式呢?

  1. 纯粹的函数调用

  2. 对象的方法调用

  3. 构造函数调用

  4. apply、call调用

我擦,有木有一千只草泥马在心里蹦腾不息,人家是要弄懂this,你这又是整的哪一出

我们慢慢来,一步步从这些调用模式中探究this这个神奇的远古神兽

纯粹的函数调用

函数调用 即 functionName () 模式,这也是我们使用的最多的一种方式,其属于全局调用,浏览中默认情况下函数内部的this指向window,当然是在非严格模式下。

this.name = 'qianlong';function showName () {console.log(this.name);console.log(this === window);
}showName() // qianlong
// true

对象的方法调用

当一个函数作为对象的某个属性方法被调用的时候

var obj = {name: 'qianlong',showName: function () {console.log(this.name);}
};obj.showName();
// qianlong

可以看出this指向是obj这个对象,其实本质上讲函数调用形式内部this就是指向调用它的那个对象

上面的例子相当于

window.showName()

这也是为什么可以读取到全局定义的name属性的原因。

再来

var showName = function () {console.log(this.name);},obj = {name: 'qianlong',showName: showName};obj.showName();

这个时候输出的是什么呢

结果是不变的,在js中,一切都是对象,而这里也只是将,obj的showName属性指向,showNmae函数的引用地址。

继续

当我们把showName方法赋值给了一个变量,又会有什么事情发生呢?

var obj = {name: 'qianlong',showName: function () {console.log(this.name);}
};var tempShowName = obj.showName;tempShowName()// undefined

为什么不是期望的那样输出 qianlong呢。obj的showName方法是一个对象,当把它赋值给了tempShowName变量,此时便和obj没有什么关系了,而这个时候的调用和下面是等价的。

window.tempShowName()

window上此事并没有name属性,自然输出是undefined

构造函数调用

当使用 new 去调用一个构造函数的时候,内部的this,指向的是实例化出来的对象。

var Person = function (name, sex) {this.name = name;this.sex = sex;console.log(this);
};var p1 = new Person('qianlong', 'boy');// Person {name: 'qianlong', sex: 'boy'};

构造函数也是函数,所以当你用普通调用方式调用时

var Person = function (name, sex) {this.name = name;this.sex = sex;console.log(this);
};Person('qianlong', 'boy');// 这个时候相当于给window对象添加了name和sex两个属性。window.name // 'qianlong'
window.sex // 'boy'

apply、call调用

使用call和apply方式去调用一个函数的时候,内部的this指向的是传进来的第一个参数,当第一个参数是undefined或者null的时候,依旧指向window

关于call和apply欢迎查看另一篇文章

js中call、apply、bind那些事

var showName = function () {console.log(this);};showName() // window
showName.call(undefined) // window
showName.call(null) // window
showName.call({name: 'qianlong'}) // {name: 'qianlong'}

箭头函数

在 ES6 的新规范中,加入了箭头函数,它和普通函数最不一样的一点就是 this 的指向,普通函数中的this,是运行时候决定的,而箭头函数却是定义时候就决定了。

var obj = {name: 'qianlong',showName: function () {console.log(this.name);},showNameLater: function () {setTimeout(() => {console.log(this.name);}, 1000)}
};obj.showNameLater();// qianlong
var obj = {name: 'qianlong',showName: () => {console.log(this.name);}
};obj.showName();
// undefined

一些坑

1. setTimeout

var obj = {name: 'qianlong',showName: function () {console.log(this.name);},showNameLater: function () { setTimeout(this.showName, 1000);}
};obj.showNameLater();// undefined

这里在执行setTimeout这个函数的时候传了obj的showName函数作为第一个参数,其效果与

var showName = obj.showName

是相同的。而setTimeout内部其实也是执行了传进去这个函数而已,即。

showName();

还记得这种调用方式和window.showName()是类似的效果吗?这个时候输入为undefined也就好理解了。

那么怎么解决这个问题呢,毕竟我们期望的效果是输出qianlong

var obj = {name: 'qianlong',showName: function () {console.log(this.name);},showNameLater: function () { var self = this;setTimeout(function () {self.showName();}, 1000);}
};obj.showNameLater();

或者

var obj = {name: 'qianlong',showName: function () {console.log(this.name);},showNameLater: function () { setTimeout(this.showName.bind(this), 1000);}
};obj.showNameLater();

2. setTimeout

尼玛坑爹啊,居然还是因为你。

'use strict';function show() {console.log(this);
}show(); // undefined setTimeout(show, 1); // window

在严格模式下面,函数调用的时候没有指定this的情况下,内部this的表现为undefined,但是setTimeout却不同,其内部默认还是指向window。

3. 为构造函数指定this

var Person = function (name, sex) {this.name = name;this.sex = sex;
};var p1 = new Person.call({});// Uncaught TypeError: Person.call is not a constructor

这里报错了,原因是我们去 new 了 Person.call 函数 ,这里的函数不是一个构造函数;

当然解决方式也是有的。

var Person = function (name, sex) {this.name = name;this.sex = sex;
};var p1 = new (Person.bind({}))('qianlong', 'sex');// Person {name: "qianlong", sex: "sex"}

4. 为箭头函数指定this

var show = (str) => {console.log(str);console.log(this);
};show('qianlong');
// qianlong
// windowshow.call({name: 'qianlong'}, 'qianlong');
// qianlong
// window

可以看到使用call来手动改变箭头函数中的this的时候,无法成功。 箭头函数中的 this 在定义它的时候已经决定了(执行定义它的作用域中的 this),与如何调用以及在哪里调用它无关,包括 (call, apply, bind) 等操作都无法改变它的 this。

结语

文章可能有些疏漏与错误之处,欢迎各位指正。

this - 想说爱你不容易相关推荐

  1. 程序猿悲喜录:魔都,想说爱你不容易

    程序猿悲喜录:魔都,想说爱你不容易 初入魔都 男怕入错行,女怕嫁错郎,真是一语中的,想当初为了赢取白富美,走上人生巅峰,脑袋一抽便进入了开发行业,坎坎坷坷,如今头发都秃了. 从学校出来,便留在了上海, ...

  2. 想说爱你不容易 | 使用最小 WEB API 实现文件上传(Swagger 支持)

    前言 上回,我们使用最小 WEB API 实现文件上传功能(<想说爱你不容易 | 使用最小 WEB API 实现文件上传>),虽然客户端访问是正常的,但是当打开 Swagger 页面时,发 ...

  3. Jquery想说爱你不容易

    JQuery是一套跨浏览器的JavaScript库,简化HTML与JavaScript之间的操作.由John Resig在2006年1月的BarCamp NYC上发布第一个版本.目前是由 Dave M ...

  4. 想说爱你不容易,浏览器缓存浅谈

    今天小微开店宝在测试环境发布更新的时候,同事问:"为什么我需要手动清理浏览器缓存才能看到变更?难道系统上线后也需要客户自己清理浏览器缓存吗!"看来,这个坑需要我来填了. 什么是浏览 ...

  5. Unicode - 想说爱你不容易

    这几天client要求我从一个系统导数据出来,碰到中文乱码的问题:数据存储在SQL Server 2000中,字段类型是varchar, :-) 老系统,没办法.前台用VS2005做的WinForm+ ...

  6. PK 想说爱你不容易

    上午在烟花爆了14的骨玉.下午在苍月爆了双烈鞋. 骨玉,朋友帮我要回来了.烈鞋我仓库有,自己去找来换上. 唉,每个地图都有我伤心的爆出历史. 我想起我那刚穿上就被爆的凰天,13的血饮,嗜魂,还有数不清 ...

  7. win10想说爱你不容易——安装.net3.5也是一个坑(已有完美解决方法)

    win10想说爱你不容易--安装.net3.5也是一个坑(已有完美解决方法) 参考文章: (1)win10想说爱你不容易--安装.net3.5也是一个坑(已有完美解决方法) (2)https://ww ...

  8. 教育大数据,想说爱你不容易

        近两年,"大数据"在教育领域日益成为热点名词,和"在线教育"相呼应.从今年新东方.学大等教育机构发布的教育产品来看,几乎每一款产品都会提到大数据.既然如 ...

  9. 婚恋网想说爱你不容易

    国家网信办.公安部.工信部.民政部.全国妇联等有关部门联合开展的"婚恋网站严重违规失信" 专项整治开展3个月以来,已核查处置网民有效举报线索100余件,依法关闭128家严重违规失信 ...

  10. 国产CAD想说爱你,并不容易。

    诸如标题"盗版率之痛.核心技术之殇:国产CAD....","内忧外患!国产CAD该何去何从?如何破局?"以及"宽容与严厉并存!给国产CAD一些时间&q ...

最新文章

  1. 用聚类方法结合卷积网络,实现无监督端到端图像分类
  2. ubuntu 安装Pangolin 过程_余辉亮的学习笔记的博客-CSDN博客_pangolin安装
  3. 使用Netty,我们到底在开发些什么?
  4. 漫谈可视化Prefuse(四)---被玩坏的Prefuse API
  5. 负载测试与压力测试的区别
  6. Docker入门 - 005 Docker 容器连接
  7. mysql异步查询 java_基于 mysql 异步驱动的非阻塞 Mybatis
  8. 4.5.2 循环语句
  9. cocos2d-x 2.2.3 win32程序发布注意
  10. Kotlin——中级篇(二): 属性与字段详解
  11. Django主从数据库分离配置
  12. 微课|中学生可以这样学Python(8.3节):递推算法例题讲解
  13. Linux操作系统原理与应用09(完):设备驱动
  14. FireMonkey ListView 设计期添加按钮及其 OnClick 事件
  15. [转]计算机四级网络工程师思维导图--常考重点
  16. Mac安装原版Windows7无法验证AppleSSD.sys文件数字签名解决办法
  17. 数学分析-换底公式证明
  18. 电脑微信聊天记录迁移——备份与恢复
  19. 关于PWM,SPWM,SVPWM的整理
  20. PYTHON BZ2 安装

热门文章

  1. 【驱动】uboot环境变量分析
  2. 凸透镜成像实验软件_中考物理凸透镜成像难点解析
  3. python的id方法_python中id()函数的实用研究实例
  4. uniapp 中如何使用echart_uniapp中如何引用echarts
  5. 【java】异常的分类
  6. 华为js面试题_四面腾讯与华为,大厂前端面试真BT!
  7. X-UA-Compatible
  8. MySQL如何判别InnoDB表是独立表空间还是共享表空间
  9. IOS一些显示效果和动画效果资料
  10. 多媒体视像会议中音视频矩阵的用途