this 到底指向哪里

以下如果没提及,则为严格模式。

js中作用域有两种:

  1. 词法作用域
  2. 动态作用域

词法作用域

词法作用域指在书写代码时就被确定的作用域。
看如下代码


  1. var value = 1;
  2. function foo() {
  3. console.log(value);
  4. }
  5. function bar() {
  6. var value = 2;
  7. foo();
  8. }
  9. bar();// 结果是1

动态作用域

动态作用域指在代码运行时才被确定的作用域。
js中只有this的作用域是动态作用域

this的五种绑定

初学js时,会想当然认为this遵循某一条规律,就像物理学那样,然而并不是。
this的绑定分为五种情况,这五种情况之间毫无规律可言。不过好在都很简单。

一. 默认绑定

当以如下形式执行一个函数时,this为默认绑定;


  1. func()
  • 严格模式下,this为undefined
  • 非严格模式下,this是全局对象。

与函数调用嵌套多少层如何嵌套无关


  1. /* 全是undefined */
  2. function printThis(){
  3. return this
  4. }
  5. var obj = {
  6. say(){
  7. console.log('obj.say',printThis())
  8. }
  9. }
  10. function funcB(){
  11. console.log('funcB',printThis());
  12. obj.say();
  13. }
  14. console.log('funcA',printThis())
  15. obj.say()
  16. funcB()

二. 隐式绑定

当以如下行驶执行一个函数时,this为隐式绑定;


  1. a.b.func()

此时this指向前面一个对象

赋值会改变隐式绑定this的指向

  • 方法赋值给变量

  1. class T {
  2. dotInvoke() {
  3. console.log('dotInvoke', this.sayThis())
  4. }
  5. sayThis() {
  6. return this
  7. }
  8. assignInvoke() {
  9. var sayThis = this.sayThis;
  10. console.log('assignInvoke', sayThis())
  11. }
  12. }
  13. var tt = new T();
  14. tt.dotInvoke()// 指向T
  15. tt.assignInvoke()// undefined
  • 函数被赋值成方法

  1. function printThis(){
  2. return this
  3. }
  4. var obj = {};
  5. obj.say = printThis;
  6. obj.say()/* 指向obj */
  • 赋值给参数

极为常见的是回调函数的this是undefined,因为回调函数被复制给参数,参数再调用时变成了默认绑定


  1. function asyncFun(cb){
  2. cb()
  3. }
  4. var obj = {
  5. callback(){
  6. console.log(this)
  7. }
  8. }
  9. obj.callback()/*隐式绑定 obj */
  10. asyncFun(obj.callback);/*默认绑定 undefined */

三. 箭头函数

箭头函数会让this指向最近的函数或全局作用域

  • 与最近的函数的this指向相同

  1. function foo() {
  2. // 返回一个箭头函数
  3. return (a)=>{
  4. //this 继承自 foo()
  5. return this.a
  6. }
  7. ;
  8. }
  9. var obj1 = {
  10. a: 'obj1'
  11. };
  12. var obj2 = {
  13. a: 'obj2'
  14. }
  15. var arrow1 = foo.call(obj1);
  16. var arrow2 = foo.call(obj2);
  17. var arrow3 = foo();
  18. console.log('arrow1',arrow1())/* obj1 */
  19. console.log('arrow2',arrow2())/* obj2 */
  20. console.log('arrow3',arrow3())/* undefined,严格模式下报错 */
  • 指向全局

  1. var printThis = ()=>this;
  2. console.log('printThis',printThis());/* global */
  • 指向实例

  1. class Test {
  2. printThis = ()=>{
  3. return this
  4. }
  5. }
  6. //会被babel翻译成
  7. var test = function test() {
  8. var _this = this;
  9. this.printThis = function () {
  10. return _this;
  11. };
  12. };

四. 显示绑定

call, apply, bind指定this指向

五. new绑定

构造函数,ES6中的class
new构造函数,new class时,this指向实例

总结

  1. 五种绑定,后面两种情况单一,前面两种会因为方法,函数被赋值而互相转化。
  2. 因为this处于动态作用域,而目前开发时又大量使用框架。我们写下的代码,并不总是由我们自己调用,而是被打包工具打包后,由框架调用。导致我们并不知道我们写下的函数和方法是否被框架复制过或显示绑定过而改变了this指向。以至this指向更加扑朔迷离。
  3. 写完本文顿时觉得,python里指向明确的self完爆js的this。

来源:https://segmentfault.com/a/1190000017715350

this的五种指法的更多相关文章

  1. JavaScript常见的五种数组去重的方式

    ▓▓▓▓▓▓ 大致介绍 JavaScript的数组去重问题在许多面试中都会遇到,现在做个总结 先来建立一个数组 var arr = [1,2,3,3,2,'我','我',34,'我的',NaN,NaN ...

  2. Android之数据存储的五种方法

    1.Android数据存储的五种方法 (1)SharedPreferences数据存储 详情介绍:http://www.cnblogs.com/zhangmiao14/p/6201900.html 优 ...

  3. 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型

    1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...

  4. xmlHttp.readyState的五种状态

    自己简单的总结一下 深入的了解可以看其他道友的 O(∩_∩)O readyState有五种可能的值: 0 (未初始化): (XMLHttpRequest)对象已经创建,但还没有调用open()方法. ...

  5. Redis五种数据结构简介

    Redis五种结构 1.String 可以是字符串,整数或者浮点数,对整个字符串或者字符串中的一部分执行操作,对整个整数或者浮点执行自增(increment)或者自减(decrement)操作. 字符 ...

  6. Android中Button的五种监听事件

    简单聊一下Android中Button的五种监听事件: 1.在布局文件中为button添加onClick属性,Activity实现其方法2.匿名内部类作为事件监听器类3.内部类作为监听器4.Activ ...

  7. 五种方式让你在java中读取properties文件内容不再是难题

    一.背景 最近,在项目开发的过程中,遇到需要在properties文件中定义一些自定义的变量,以供java程序动态的读取,修改变量,不再需要修改代码的问题.就借此机会把Spring+SpringMVC ...

  8. php五种常见的设计模式(转载)

    很多人都想着写博客来记录编程生活中的点滴,我也不例外,但想了好长时间不知道写什么........万事开头难,先转载一篇吧..... 设计模式 一书将设计模式引入软件社区,该书的作者是 Erich Ga ...

  9. Android_安卓为按钮控件绑定事件的五种方式

    一.写在最前面 本次,来介绍一下安卓中为控件--Button绑定事件的五种方式. 二.具体的实现 第一种:直接绑定在Button控件上: 步骤1.在Button控件上设置android:onClick ...

随机推荐

  1. 一些关于Hibernate延迟加载的误区

    最近面试别人,正好出的笔试题中有道关于Hibernate延迟加载的问题,聊天过程中发现很多人对Hibernate的延迟加载有些理解误区,写 些东东在这里,希望对大家有所帮助. 首先是第一个误区:延迟加 ...

  2. sessionStorage 和 localStorage的区别

    sessionStorage.setItem('userName',userName) // 存 sessionStorage.getItem('userName') // 取 sessionStor ...

  3. Python编码decode和encode

    常见编码介绍: GB2312编码:适用于汉字处理.汉字通信等系统之间的信息交换;GBK编码:是汉字编码标准之一,是在 GB2312-80 标准基础上的内码扩展规范,使用了双字节编码ASCII编码:是对 ...

  4. Django之单表查询——神奇的双下划线

    1.filter中的单表查询 # 查询id>1且id<4的结果 ret = models.Person.objects.filter(id__gt=1,id__lt=4) print(re ...

  5. 2019 Multi-University Training Contest 6 Snowy Smile (最大字段和变形)

    题意: 求一个子矩阵要求其矩阵内的合最大. 题解: 正常的求最大子矩阵的复杂度是O(n^3) 对于这一题说复杂度过不去,注意到这个题总共只有2000个点关键点在与这里优化 最大子矩阵可以压缩矩阵变成最 ...

  6. Asp.Net中的HttpWebRequest类与HttpWebResponse类

    相关博文:https://www.cnblogs.com/xu-yi/p/10061342.html 相关博文:https://www.cnblogs.com/zoujinhua/p/11313396 ...

  7. 2018-11-19-WPF-在image控件用鼠标拖拽出矩形

    title author date CreateTime categories WPF 在image控件用鼠标拖拽出矩形 lindexi 2018-11-19 15:35:13 +0800 2018- ...

  8. JS流程控制语句 多重判断满足你各种需求 要在多组语句中选择一组来执行,使用if..else嵌套语句。

    多重判断(if..else嵌套语句) 要在多组语句中选择一组来执行,使用if..else嵌套语句. 语法: if(条件1) { 条件1成立时执行的代码} else if(条件2) { 条件2成立时执行 ...

  9. Sightseeing Cows

    Sightseeing Cows 给出一张图,点数为L,边数P,并给出边的边权\(\{b_i\}\),再给处每个点的点权,求一条起点和终点相同的路径,并使其点权之和除以边权之和最大,注意,路径中点权只 ...

  10. mysql 表查询结果 总行数计算

    一般的查询语句是这样的 SELECT  id,name FROM SystemEvents WHERE  1=1 limit 9,10 SELECT  * FROM SystemEvents WHER ...