this

普通函数的this

普通函数的this是由动态作用域决定,它总指向于它的直接调用者。具体可以分为以下四项:

  1. this总是指向它的直接调用者, 例如 obj.func() ,那么func()里的this指的是obj。
  2. 在默认情况(非严格模式,未使用 'use strict'),如果函数没有直接调用者,this为window
  3. 在严格模式下,如果函数没有直接调者,this为undefined
  4. 使用call,apply,bind绑定的,this指的是绑定的对象

箭头函数的this

箭头函数是没有绑定自己的this,函数内使用的this是由静态作用域(也成为词法作用域,参考this)决定。静态作用域就是说箭头函数里this是由定义它的代码决定,而不是执行调用箭头函数的代码。

上面的说法有时很难理解,我自己总结的方法是:找出定义箭头函数的上下文(即包含箭头函数最近的函数或者对象),那么上下文所处的父上下文即为this。具体可以参考箭头函数的示例。

普通函数示例

示例1:对象函数的this

var obj = {
  myfunc : function() {
    console.log(this);  
  }
}
obj.myfunc();

输出的是obj对象,this指的是obj。

示例2:全局函数的this

function myfunc() {
    console.log(this);
}
myfunc();

输出的是Window对象,this指的是Window

示例3:严格模式下全局函数的this

'use strict';
function myfunc() {
    console.log(this);
}
myfunc();

this为undefined,因为严格模式下,myfunc没有直接的调用者。

示例1-变形1:在obj.myfunc()方法里添加普通函数,并执行

var obj = {
  myfunc : function() {
    function innerfunc() {
     console.log(this);
    }
    innerfunc();
  }
}
obj.myfunc();

this指的是Window。这是因为innerfunc()函数执行时没有直接调用者,所有this为Window。

示例1-变形2:把obj.myfunc赋值给一个变量后调用

var obj = {
  myfunc : function() {
    console.log(this);  
  }
}
var f = obj.myfunc;
f();

this指的是Window。这是因为f()是没有直接调用者,在非严格模式下,this指的是Window。

箭头函数示例

示例5:函数内使用箭头函数

var obj = {
  myfunc : function(){
    var f = ()=>{
      console.log(this);
    }
    f();
  }
}
obj.myfunc();

this指的是obj。因为定义箭头函数的上下文为myfunc函数,myfunc函数所在的父上下文为obj。

示例6:箭头函数作为方法

var obj = {
  myfunc : ()=>{
    console.log(this);  
  }
}
obj.myfunc();

这个地方很容易误以为this指的是obj。其实this实际指的是window,因为定义箭头函数最近的上下文为obj对象(myfunc和箭头函数作为key-value的形式是平级),而obj对象的父上下文为window。

MDN web docs里说的,建议箭头函数仅用在非方法的函数(non-method function)里。

示例7:

var outeobj = {
   outfunc:function() {
     var obj = {
       myfunc : ()=>{
         console.log(this);  
       }
     }
     obj.myfunc();
   }
} outeobj.outfunc();

为了和示例6做对比,现在把obj对象添加到outerobj的outfunc里。

this指的是outobj。这是因为箭头函数最近的上下文为obj对象,而obj对象的父上下文为outobj。

理解JavaScript普通函数以及箭头函数里使用的this的更多相关文章

  1. JavaScript初学者必看“箭头函数”

    译者按: 箭头函数看上去只是语法的变动,其实也影响了this的作用域. 原文: JavaScript: Arrow Functions for Beginners 译者: Fundebug 为了保证可 ...

  2. JavaScript:学习笔记(5)——箭头函数=>以及实践

    JavaScript:学习笔记(5)——箭头函数=>以及实践 ES6标准新增了一种新的函数:Arrow Function(箭头函数).本文参考的链接如下: MDN箭头函数:https://dev ...

  3. JavaScript中的普通函数和箭头函数

    最近被问到了一个问题: javaScript 中的箭头函数 ( => ) 和普通函数 ( function ) 有什么区别? 我当时想的就是:这个问题很简单啊~(flag),然后做出了错误的回答 ...

  4. 深入理解javascript中的立即执行函数(function(){…})()

    投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014-06-12 我要评论 这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是 ...

  5. 深入理解javascript中的立即执行函数

    这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是用(function(){…})()包住业务代码,使用jquery时比较常见,需要的朋友可以 ...

  6. JS中的普通函数和箭头函数

    最近被问到了一个问题: >javaScript 中的箭头函数 (=>) 和普通函数 (function) 有什么区别? 我当时想的就是:这个问题很简单啊~(flag),然后做出了错误的回答 ...

  7. 理解javascript中的立即执行函数(function(){})()

    之前看了好多代码,都有用到这种函数的写法,但是都没认真的去想为什么会这样写,今天开始想学习下jquery的源码,发现jquery也是使用这种方式,用(function(window, undefine ...

  8. 理解JavaScript中的去抖函数

    何为去抖函数?在学习JavaScript去抖函数之前我们需要先弄明白这个概念.很多人都会把去抖跟节流两个概念弄混,但是这两个概念其实是很好理解的. 去抖函数(Debounce Function),是一 ...

  9. 【转】深入理解javascript中的立即执行函数(function(){…})()

    javascript和其他编程语言相比比较随意,所以javascript代码中充满各种奇葩的写法,有时雾里看花,当然,能理解各型各色的写法也是对javascript语言特性更进一步的深入理解. ( f ...

随机推荐

  1. QT 中“ std::cerr ”的使用方法【转载】

    std::cerr  标准错误输出流 std::cout 标准输出流 std::cerr 与 std::cout的最大不同是 cerr 是 不带输出缓冲 的,直接就可以输出到显示器上, 而 cout ...

  2. BZOJ2002:[HNOI2010]弹飞绵羊

    浅谈分块:https://www.cnblogs.com/AKMer/p/10369816.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php?i ...

  3. POJ2236(并查集入门)

    Wireless Network Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 22977   Accepted: 961 ...

  4. lrzsz-串口传输文件

    二.编译安装 1.解压文件,进入目录     tar –zxvf lrzsz-0.12.20.tar.bz        cd / lrzsz-0.12.20 ./configure  2../con ...

  5. Python No module named pkg_resources

    好记性不如烂笔头. I encountered the same ImportError today while trying to use pip. Somehow the setuptools p ...

  6. 2015.12.14 MDI(多文档窗口结构)设置基本解决,折腾一天,部分解决存在已久的问题。但效果仍不如临时航线的MDI窗体结构。

    创建从一个窗口弹出多个子窗口的结构叫MDI窗体结构 如果不按MDI结构管理,最简单的做法是: 在窗体A上添加菜单或按钮,在菜单或按钮事件中添加弹出B窗体代码: B b = new B(); b.sho ...

  7. Eclipse一步一步搭建SSM+Maven

          Eclipse 搭建SSM(Spring.Spring MVC .Mybatis)  利用Maven管理Jar包      一般而言,新的eclipse都已经集成了maven,如果没有那么 ...

  8. intellij idea 设置Live Template快速生成自定义代码块

    一.设置 类似于宏,话不多少,上步骤 File----->Setting 选择Live Template 新建触发规则 新建触发key 输入模版text 选择在哪个环境触发 选java 如果是其 ...

  9. junit4新框架hamcrest的assertThat

    assertThat JUnit4.4引入了Hamcrest框架,Hamcest提供了一套匹配符Matcher,这些匹配符更接近自然语言,可读性高,更加灵活 /**equalTo匹配符断言被测的tes ...

  10. Replace Pioneer注册方法

    Replace Pioneer注册方法 Replace Pioneer过期后,会弹出一个注册(Registration)窗口,其中有一个试用选项(Trial License),点击Trial Lice ...