this指向

普通函数

this指向window

function sayHello() {
    console.log(this);
}
sayHello();
// 在浏览器环境下,会输出window对象,表明函数内部this指向了window(全局对象)

函数作为对象的方法调用

this指向对象

const person = {
    name: 'Alice',
    sayHello: function () {
        console.log(`Hello, my name is ${this.name}`);
    }
};
person.sayHello();
// 这里sayHello函数作为person对象的方法被调用,函数内部的this
就指向person对象,所以会输出 "Hello, my name is Alice"

构造函数

this指向new关键字创建的实例

function Person(name) {
    this.name = name;
    console.log(this);
}
const personInstance = new Person('Bob');
// 这里通过new调用Person函数创建实例,在Person函数内部this指向新创建的personInstance对象,会输出这个实例对象的相关信息

箭头函数中的this指向

取决于其外层(函数或全局)作用域的this,考虑嵌套关系(看最外面)
const person = {
    name: 'David',
    createArrowFn: function () {
        return () => {
            // 这里箭头函数的this继承自外层的createArrowFn函数的this,而createArrowFn函数里this指向person对象,所以箭头函数里this也指向person对象
            console.log(this.name); 
        };
    }
};
const arrowFn = person.createArrowFn();
arrowFn(); // 输出 "David"
这里箭头函数的this继承自外层的createArrowFn函数的this,而createArrowFn函数里this指向person对象,所以箭头函数里this也指向person对象

使用 call、apply、bind 方法改变 this 指向

call

fn.call(this,arg1,arg2…)
  • 使用call方法调用函数时,第一个参数为this指定的值

  • call方法的其余参数会依次自动传入函数作为函数的参数

  • // call方法改变this指向
        function fn(a,b){
          console.log(this,a,b)
        }
        let obj={uname:'牛牛',age:18}
        fn.call(obj,666,999)
        //fn函数调用call方法改变this指向
        //call会让fn函数在执行过程中改变this指向,此时this指向obj,同时将666,999传给a、b
    
let obj={
      uname:'牛牛',
      age:18,
      study:function(){
        console.log(this)
      }
    }
    let o={uname:'萌萌',age:17}
    obj.study.call(o)//此时obj中的study方法的指向变为o这个对象
function add(a, b) {
    return a + b;
}
// 传递两个参数
const result = add.call(null, 1, 2); 
console.log(result); // 输出: 3

apply

fn.apply(this,[arg1,arg2])
  • 第一个参数为this指定的值

  • apply方法的第2个参数,必须是一个数组(或类数组对象)

  • 类数组对象是指具有 length 属性且元素可通过数字索引访问的对象,例如 { 0: 'a', 1: 'b', length: 2 }

  • 不用改变this指向,所以第一参数为null

  • 在使用 apply 方法时,函数只会考虑其参数列表中定义的参数数量,对于超出函数参数数量的数组元素,它们会被忽略,并且 length 属性不会作为参数传递给函数

  • function fn(a,b){
          console.log(this,a,b)
        }
        let obj={uname:'牛牛',age:18}
        fn.apply(obj,[666,999])//第二个参数虽然是数组,但是内容与函数的形参一一对象,数组里有几个值,就看函数有几个形参
    
    
// 求数组最大值方法
    let arr=[1,2,3,4,5,6]
    let re=Math.max.apply(null,arr)
    //不用改变this指向,所以第一参数为null
    //直接Math.max(arr)会报错,因为Marh.max()是个函数,所以可以调用apply方法将数组传过去
    console.log(re)
function add(a, b, c) {
    return a + b + c;
}
// 使用类数组对象作为参数
let arrayLike = { 0: 4, 1: 5, 2: 6, length: 3 };
let result2 = add.apply(null, arrayLike); 
console.log(result2); // 输出 15

bind

  • 主要用于创建一个新的函数,这个新函数的 this 值会被永久绑定到 bind 方法的第一个参数上
  • bind(person)greet 函数的 this 绑定到 person 对象上。这样,无论 greetFn 如何调用,其 this 始终指向 person
  • bind 操作需要作用在函数对象上,而不是普通对象上。
const person = {
    name: 'Alice',
    greet: function() {
        console.log(`Hello, my name is ${this.name}`);
    }
};
const greetFn = person.greet.bind(person);
greetFn(); // 输出 "Hello, my name is Alice"
预定
function add(a, b, c) {
    return a + b + c;
}
const addFive = add.bind(null, 5);
console.log(addFive(2, 3)); // 输出 10

bind(null, 5) 创建了一个新函数 addFive,其中第一个参数 a 已经被预定义为 5。调用 addFive(2, 3) 时,2 作为 b3 作为 c 传递给 add 函数

区别

callapply 是立即调用函数并设置 this 及参数,而 bind 只是创建一个新函数,并不立即调用

你可能感兴趣的:(javascript,前端,开发语言)