一文搞懂 this 指向

在这里插入图片描述



一、前言

JS 中 this 指向问题 - 掘金

在JavaScript中,this关键字表示当前执行代码的上下文对象。它的值取决于函数被调用的方式。this可以引用全局对象(在浏览器中是window对象),也可以引用当前对象(例如,在对象方法中),或者在使用构造函数创建对象时引用新创建的实例。

二、箭头函数

const obj = {
    
    
    fun1: function () {
    
    
        console.log(this);
    },
    fun2: () => {
    
    
        console.log(this);
    }
}

obj.fun1(); // obj
obj.fun2(); // window
  • 箭头函数的 this 指向是在定义函数时确定的,而不是在运行时确定的。
  • 箭头函数内的 this 指向外层的 this
  • 箭头函数的 this 指向是无法改变的,即使使用 call、apply 或 bind 方法也无效。因此,在使用箭头函数时需要注意它的 this 指向。

三、new指向

// class Person {} 和 function Person(name, age) 都可以用来定义一个对象的构造函数,但它们有一些区别。

// 语法:class 是 ES6 中新增的语法,用于定义类和构造函数,而 function 是 JavaScript 中早期就存在的语法,用于定义函数和构造函数。

// 继承:class 支持更加简洁和灵活的继承方式,可以使用 extends 关键字来继承其他类,而 function 只能使用原型链来实现继承。

// 方法定义:在 class 中,方法可以直接定义在类的内部,而在 function 中,方法需要定义在构造函数的原型对象上。

class Person {
    
    
    constructor(name, age) {
    
    
        this.name = name;
        this.age = age;
    }

    print() {
    
    
        console.log(this);
    }
}

const p1 = new Person('张三', 18);
p1.print()

  • 当你使用new关键字调用函数的时候,函数中的this指向一定是实例对象

四、bind

const person = {
    
    
    name: 'Alice',
    age: 20
};

function sayHello() {
    
    
    console.log(`Hello, my name is ${
      
      this.name}, I'm ${
      
      this.age} years old.`);
}

const sayHello2 = sayHello.bind(person);
sayHello2(); // 输出 "Hello, my name is Alice, I'm 20 years old."
  • 使用方法:bind(thisArg, arg1, arg2, /* …, */ argN)
  • bind 方法是 JavaScript 中用于改变函数执行时 this 关键字指向的方法。它会返回一个新的函数,该函数与原函数具有相同的函数体,但是 this 关键字被绑定到指定的对象上。
  • 需要注意的是,bind 方法不会修改原函数的 this 关键字,而是返回一个新的函数,但是不会立刻调用。同时,使用 bind 方法创建的新函数可以被多次调用,每次调用时都会使用相同的绑定对象,this不会被修改。

另外,bind 方法还可以用于实现函数柯里化(Currying),即将一个多参数函数转换为一个单参数函数序列的过程。例如:

function add(x, y) {
    
    
    return x + y;
  }
  
  const add5 = add.bind(null, 5);
  console.log(add5(3)); // 输出 8
  console.log(add5(7)); // 输出 12

五、call和apply

const person = {
    
    
  name: 'Alice',
  age: 20
};

function sayHello() {
    
    
  console.log(`Hello, my name is ${
      
      this.name}, I'm ${
      
      this.age} years old.`);
}

sayHello.apply(person);
sayHello.call(person);
  • call和apply都可以立即立即调用原函数,并且可以指定函数执行时的 this 关键字和参数列表

六、bind call apply区别

const name = '小王', age = 17

const obj = {
    
    
    name: '小张',
    objAge: this.age,
    myFun: function (fm, t) {
    
    
        console.log(this.name + '年龄' + this.age)
        console.log(fm + t)
    }
}

const db = {
    
    
    name: '小李',
    age: 18
}

obj.myFun.bind(db, '北京', '上海')()
obj.myFun.call(db, '北京', '上海')
obj.myFun.apply(db, ['北京', '上海'])
  • 相同点:都会改变函数的this指向
  • 绑定不同:
    • bind不会改变原函数的this关键字,返回一个新的函数,不会立刻调用
    • call、apply都可以立即调用原函数
  • 传参不同:
    • bind、call传入一组参数
    • apply传入数组参数

七、对象(obj.)

function func() {
    
    
  console.log(this.x)
}

obj = {
    
     x: 1 }
obj.func = func
obj.func() // 1
  • 函数赋值给对象,当前this指向obj
  • 如果是箭头函数会报错

八、全局this指向

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

fn1() //window对象

九、不在函数里

不在函数中的场景,可分为浏览器的 script 标签里,或 Node.js 的模块文件里。

  1. 在 script 标签里,this 指向 Window。
  2. 在 Node.js 的模块文件里,this 指向 Module 的默认导出对象,也就是 module.exports。

猜你喜欢

转载自blog.csdn.net/qq_53673551/article/details/133279464