内容大略

  • 一般函数的this
  • 箭头函数的this

一般函数

1.论断

先说论断,一般函数的this的指向在函数定义的时候是确定不了的,只有函数执行的时候能力确定this到底指向谁,实际上this的最终指向的是那个调用它的对象,并且是最近的那个

2.剖析

例子1:

function a(){     var user = "函数外部a";    console.log(this.user); //undefined    console.log(this); //Window}a();

咱们晓得像这种调用形式,都是window调用,所以输入如上,验证一下

例子2:

var user = "window的a";function a(){     var user = "函数外部a";    console.log(this.user); //window的a    console.log(this); //Window}a(); 

a()后面没有货色默认window.a(),调用方是window,所以此时输入“window的a”

例子3:

var o = {    user:"追梦子",    fn:function(){        console.log(this.user);  //追梦子 }}o.fn();

这里的this指向的是对象o,因为你调用这个fn是通过o.fn()执行的,那天然指向就是对象o,这里再次强调一点,this的指向在函数创立的时候是决定不了的,在调用的时候能力决定,谁调用的就指向谁,肯定要搞清楚这个。

例子4:

var user = "window追梦子"var o = {    user:"追梦子",    fn:function(){        console.log(this.user);  //追梦子 }}window.o.fn();

这里尽管最外层是window调用,然而输入的this是对象o,这跟我下面说的论断一样,this的最终指向的是那个调用它的对象,并且是最近的那个

例子5:

var o = {    user:"追梦子",    fn:function(){        console.log(this) // o        setTimeout(function(){            console.log(this);  //window        },1000)         }}o.fn();

fn被对象o触发,所以输入o,定时器和延时器塞队列,最初是由window触发的,所以输入window

箭头函数(敲黑板,重点)

1.论断

  • 在定义的时候就确认了this的指向,跟一般函数在应用的时候确认是齐全不同
  • 作用域总是指向以后作用域的上一个,上一个,上一个(很重要说3遍)!
  • 以后作用域的上一个指向的对象,就是this的指向

PS:JS的作用域个别指的是函数作用域,全局作用域,应用let那种块级作用域不算

2.剖析

例子1:

var b=11;var obj={ b:22, say:()=>{ console.log(this.b);}}obj.say();//输入的值为11

say是箭头函数,以后作用域的上一个作用域就是全局,而全局指的是window,所以输入11

例子2:

var b=11;var obj={ b:22, say:function(){  return () => {     console.log(this.b);  } }}obj.say()();//输入的值为22

say外面return的那个是箭头函数,以后作用域的上一个作用域是say函数,而后say函数作用域指的是obj,所以输入22

例子3:

var str = 'window';   const obj = {    str:'obj',    fn: ()=>{    console.log(this.str);        },    fn2: function(){    console.log(this.str)    return {        str: 'newObj',        fn: ()=>{        console.log(this.str);            }        }    }} obj.newFn = ()=>{    console.log(this.str);    } obj.fn(); //windowobj.newFn(); //windowobj.fn2().fn(); //输入obj,obj
  1. fn上一级是全局,所以是window
  2. newFn是在里面定义的,不过解析也是跟fn一样
  3. fn2是obj触发,所以输入obj,fn2外面返回了一个对象,对象外面有一个fn箭头函数,这个fn的上一级作用域是fn2(这里留神不要被newObj蛊惑)fn2指向的对象是obj,所以输入还是obj

例子4:

var obj = {  str:'obj',  fn: function(){   return {    str: 'inlineObj',    fn1: function(){     console.log(this.str);      return ()=>{      console.log(this.str);      }    },    fn2: ()=>{     console.log(this.str);     }   }  } }  obj.fn().fn1()(); //输入inlineObj,inlineObj obj.fn().fn2(); //输入obj

1.obj.fn()这里留神曾经返回了一个对象,所以触发fn1的时候,输入inlineObj,fn1外面return一个箭头函数,上一级作用域是fn1,fn1指向return的那个{},所以输入也是inlineObj
2.fn2的上一级作用域是fn,fn指向obj,所以输入obj

更改this的指向

一般函数能够改

var user = "window的a";function a(){     var user = "函数外部a";    console.log(this.user);}var obj = {    user:'obj的a'}a() //window的aa.call(obj) //obj的a

箭头函数不能够改

var obj = {  str:'obj',  fn: function(){    console.log(this.str)   },  fn2: function(){    return () => {        console.log(this.str)    }      }}var obj2 = {    str:'obj2'}obj.fn()  //objobj.fn.call(obj2) //obj2obj.fn2()() //objobj.fn2().call(obj2) //obj

能够看到,箭头函数就算用了call换了this指向,输入还是当初定义的那个范畴

一些比拟特地

点击事件

<div id="dianji">点击事件</div>document.getElementById('dianji').addEventListener('click',function(){    console.log(this); // 输入dom })document.getElementById('dianji').addEventListener('click',() =>{    console.log(this); // window })

.addEventListener后面是dom,所以一般函数触发的时候输入dom,谁调用输入谁,而箭头函数的上一级作用域是全局,所以输入window

当this碰到return

返回空对象{}

function fn()  {     this.user = '追梦子';     return {};  }new fn().user    //undefined

返回函数

function fn()  {     this.user = '追梦子';     return function aaa(){};}new fn().user    //undefined

返回数字

function fn()  {     this.user = '追梦子';     return 1;}new fn().user  //追梦子

返回null

function fn()  {     this.user = '追梦子';     return null;}new fn().user  //追梦子

下面的列子次要阐明
如果返回值是一个援用数据类型(函数,对象都属于object),那么this指向的就是那个返回的对象,如果返回值不是一个对象(根底数据类型,数值,字符串,布尔,null,undefined)那么this还是指向函数的实例。

鸣谢
非常感谢以下几位大佬的文章
彻底了解js中this的指向,不用硬背。
ES6箭头函数的this指向详解
【ES6】两个例子明确箭头函数this指向
ES6中箭头函数中的this指向