【JavaScript】this 指向

this 指向谁?

多数情况下,this 指向调用它所在方法的那个对象
说得更通俗点,谁调的函数,this 就归谁。当调用方法没有明确对象时,this 就指向全局对象。在浏览器中,指向 window;在 Node 中,指向 Global。(严格模式下,指向 undefined
this 的指向是在调用时决定的,而不是在书写时决定的。
举个栗子:

var a = {
    
    
  b: 1,
  f: function() {
    
    
    console.log(this.b)
  }
}
var b = 2;

a.f() // 1

上面栗子调用函数f的是a,所以函数指向时this指向的就是a
变一下

var a = {
    
    
  b: 1,
  f: function() {
    
    
    console.log(this.b)
  }
}

var fn = a.f;
var b = 2;

fn() // 2

上面栗子a.f已经赋值给了fnfn执行时没有指定调用对象,即this指向全局对象调用
在变一下

var a = {
    
    
  b: 1,
  f: function() {
    
    
    console.log(this.b)
  }
}

var m = {
    
    
  b: 3,
  f: function() {
    
    
    var fn = a.f;
    fn();
  }
}

var b = 2;

m.f() // 2

上面m.f执行输出的还是2。其实还是还是上面提到的:this 的指向是在调用时决定的 关键最终调用执行输出的还是fn切没有指定调用对象,所以this还是指向的全局对象。

特殊情况

在三种特殊情境下,this 会 100% 指向 window:

  • 立即执行函数(IIFE)
  • setTimeout 中传入的函数
  • setInterval 中传入的函数
    其实这也是可以通过上面的解释来理解的,立即执行函数执行时没有明确的调用对象,还是全局对象,而setTimeout和setInterval同样如此在调用时是全局对象来调用的。
    **注意:**上面上面说的三种特殊情况是指的在对应函数内直接使用this
    比如:
(function(){
    
    
    console.log(this.b) // 2
})()
var b = 2;

并不是像下面这样:

(function(){
    
    
    var a = {
    
    
        b: 1,
        f: function() {
    
    console.log(this.b)}
    }
    a.f() // 1
})()
var b = 2;

这样调用方其实跟立即执行函数没啥关系,a.f调用对象是a

箭头函数

箭头函数是最特殊的,所以单独来讲:箭头函数的this指向是有书写时决定的而非调用时,即指向箭头函数定义时所在作用域的调用对象 记住就好。

var a = {
    
    
  b:1,
  f1: () => {
    
    
    console.log(this.b)
  },
  f2: function() {
    
    
     console.log(this.b)
  }
}
var b = 2;

a.f1(); // 2
a.f2(); // 1

上述栗子a.f1为箭头函数由于定义时是在全局作用域下,所以指向全局对象输出2a.f2普通函数指向调用对象输出1
变一下:

function Fn() {
    
    
  this.a = {
    
    
    b: 1,
    f1: () => {
    
    
      console.log(this.b);
    },
    f2: function () {
    
    
      console.log(this.b);
    },
  };
  this.b = 2;
  this.run = function () {
    
    
    this.a.f1(); // 2
    this.a.f2(); // 1
    console.log(this); // fn
  };
}
var b = 3;

const fn = new Fn();
fn.run();

上述栗子可以明显看下a.f1为箭头函数由于定义时是在fn的函数作用域下,所以指向了Fn实例化的对象fna.f2普通函数指向调用对象a输出1

备注:
浏览器环境全局作用域下var声明的变量会被挂在window上,而letconst不会,因为 let const 引入了更严格的块级作用域规则。
node环境下即便使用 var 声明的全局变量不会被挂载到全局对象上,这是因为 node的模块机制和作用域规则与浏览器环境有所不同。在node中,每个模块都有自己的作用域。当您使用 var 在模块的顶层声明一个变量时,它实际上是模块作用域内的变量,而不是全局对象的属性。

例题

var length = 10

function fn(){
    
    
    console.log(this.length)
}
var obj = {
    
    
  length:5,
  method:function(fn){
    
    
    fn()
    arguments[0]()
    console.log(arguments,'arguments')
  }
}

obj.method(fn) 
obj.method(fn, 123)

答案:
10
1
args
10
2
args

猜你喜欢

转载自blog.csdn.net/zSY_snake/article/details/142356574