js三座大山之函数-运行时this的四种指向

119 阅读3分钟

js三座大山

一:函数式编程
js三座大山之函数1 
js三座大山之函数-静态词法作用域
js三座大山之函数-运行时this的四种指向

二:面向对象编程
js三座大山之对象,继承,类,原型链

三:异步编程:
js三座大山之异步一单线程,event loope,宏任务&微任务
js三座大山之异步二异步方案
js三座大山之异步三promise本质
js三座大山之异步四-Promise的同步调用消除异步的传染性
js三座大山之异步五基于异步的js性能优化
js三座大山之异步六实现微任务的N种方式
js三座大山之异步七实现宏任务的N种方式

静态词法作用域作用域与运行时this

完整的描述应该为:变量的静态词法作用域与函数的运行时动态this。
有很多同学会将变量的作用域和函数的运行时this指向搞混淆其实这可以说是两个东西。作用域是修饰变量的。 例如function fn fn即为指向函数的变量,作用域是指能够访问到这个fn的范围,这与代码的编写位置和声明方式有关,而this是指谁调用的fn例如obj.fn(),this就是函数的调用者。

运行时this:

在JavaScript中,函数的this关键字是在函数被调用时确定的,而不是在函数被定义时确定的。这就是所谓的“运行时绑定”。this的值取决于函数的调用方式。

函数的调用方式有多种方式 但是this指向本质只有四种情况 指向全局,指向上层, 显示设置this指向实例对象

1. 指向全局

function greet() {
  console.log(this); // 指向全局window 浏览器调用了green
}
greet()

2. 箭头函数指向上层:

没有自己的thisargumentssupernew.target.

这些值由距离最近的外层作用域的非箭头函数决定

注意: 只有函数才能生成新的作用域

const obj = {
    name: 'hahha',
    run(){
        const say = (name) => {
          console.log(this); // this指向obj 因为run是一个函数 有自己的作用域
        }; 
      say();
    }
}
obj.run()

再通过下面的例子深刻的理解下 只有函数才能生成新的作用域

const obj = {
    name: 'hahha',
    run:()=>{
        console.log('run this', this) 
        // this指向全局window 
        // 因为run的上层是obj但是obj是一个对象没有自己的作用域 
        // 只有函数才能生成新的作用域 所以在向外层找 到全局环境。
    },
}
obj.run() 

3.显示设置this

当函数使用callapplybind方法调用时,

this被显式设置为传递给这些方法的第一个参数。

function myFunction() {
  console.log(this);
}
myFunction.call({custom: 'object'}); // 输出:{custom: "object"}

4. 指向实例对象

  1. 对象方法:
var obj = {
  greet: function() {
    console.log(this);
  }
};
obj.greet() // 指向obj
  1. 构造函数:
function Person(name) {
  this.name = name;
  console.log(this) // 指向新创建的对象 具体可以了解下new操作符的实现原理
}
var john = new Person('John');

小例子

哪个对象实际调用函数 this就指向哪个对象。注意不要被引用传递干扰了视线。

let obj = {
    name: 'obj',
    p1:{
        name: 'p1',
        p2:{
            name: 'p2',
            action(){
                console.log(this.name)
            }
            
        }
    }
}
obj.p1.p2.action() // 指向p2

const fn = obj.p1.p2.action;
fn() // 指向window

截屏2023-12-12 下午5.06.29.png

第一种方式,本质上是obj引用p1,p1引用p2 p2调用了action方法 所以this是指向p2的,因为p2是实际调用者。
第二种方式,类似于全局直接调用方法 所以this指向全局。

参考:

  1. github.com/mqyqingfeng…
  2. developer.mozilla.org/en-US/docs/…
  3. zhuanlan.zhihu.com/p/42145138