对This对象的理解

42 阅读3分钟

一、This的核心绑定机制(高频考点)

1. 全局作用域

  • 指向:全局对象(浏览器中为window,严格模式下为undefined)。
  • 示例
    console.log(this); // 浏览器中输出Window对象
    
    function test() {
      console.log(this); // 非严格模式:Window;严格模式:undefined
    }
    

2. 函数调用

  • 指向:调用该函数的对象,或全局对象(严格模式下为undefined)。
  • 示例
    const obj = {
      name: 'Alice',
      sayHi() {
        console.log(this.name); // 指向obj,输出"Alice"
      }
    };
    
    obj.sayHi(); // 隐式绑定:this指向obj
    

3. 构造函数

  • 指向:新创建的实例对象。
  • 示例
    function Person(name) {
      this.name = name; // this指向新创建的Person实例
    }
    
    const p = new Person('Bob');
    console.log(p.name); // 输出"Bob"
    

4. 显式绑定

  • 方法call()apply()bind()强制指定this。
  • 示例
    function greet() {
      console.log(`Hello, ${this.name}`);
    }
    
    const user = { name: 'Charlie' };
    greet.call(user); // 输出"Hello, Charlie"
    

二、应用场景(结合项目经验)

  1. 对象方法:访问对象自身属性。

    const calculator = {
      value: 0,
      add(num) {
        this.value += num; // this指向calculator
        return this; // 支持链式调用
      }
    };
    calculator.add(5).add(3); // value变为8
    
  2. 事件处理:获取触发事件的DOM元素。

    <button onclick="this.style.color='red'">点击变红</button>
    
  3. 构造函数:初始化实例属性。

    class Car {
      constructor(model) {
        this.model = model; // this指向新Car实例
      }
    }
    

三、常见易错点(高频陷阱)

1. 回调函数中的this丢失

  • 问题:回调函数的this默认指向全局对象(非严格模式)。
  • 示例
    const timer = {
      seconds: 10,
      start() {
        setTimeout(function() {
          console.log(this.seconds); // 错误:this指向window,而非timer
        }, 1000);
      }
    };
    
  • 解决方案
    // 1. 使用箭头函数(不绑定this,继承外层this)
    setTimeout(() => {
      console.log(this.seconds); // 正确:this指向timer
    }, 1000);
    
    // 2. 保存this引用(var that = this)
    const that = this;
    setTimeout(function() {
      console.log(that.seconds); // 正确
    }, 1000);
    

2. DOM事件中的this

  • 问题:事件处理函数的this指向触发事件的元素,而非定义该函数的对象。
  • 示例
    const button = document.querySelector('button');
    const obj = {
      handleClick() {
        console.log(this); // 指向button元素,而非obj
      }
    };
    button.addEventListener('click', obj.handleClick);
    
  • 解决方案
    // 1. 使用箭头函数
    button.addEventListener('click', () => obj.handleClick());
    
    // 2. bind方法
    button.addEventListener('click', obj.handleClick.bind(obj));
    

四、ES6箭头函数的this(高频考点)

1. 核心区别

  • 箭头函数:不绑定this,继承外层(函数或全局)作用域的this值。
  • 普通函数:根据调用方式动态绑定this。

2. 示例对比

const obj = {
  name: 'Alice',
  normal() {
    console.log(this.name); // 指向obj
  },
  arrow: () => {
    console.log(this.name); // 指向window(全局作用域)
  }
};

obj.normal(); // 输出"Alice"
obj.arrow();  // 输出undefined(window.name为空)

3. 适用场景

  • 回调函数:避免this丢失(如定时器、数组方法)。
    const numbers = [1, 2, 3];
    numbers.forEach((num) => {
      console.log(this); // 继承自外层作用域
    });
    
  • 不适合场景
    • 对象方法(需动态this);
    • 构造函数(无法使用new调用)。

五、总结

“This对象在JavaScript中是动态绑定的,其指向取决于函数的调用方式:

  1. 全局作用域:指向全局对象(严格模式下为undefined);
  2. 函数调用:指向调用者对象(或全局对象);
  3. 构造函数:指向新创建的实例;
  4. 显式绑定:通过call/apply/bind强制指定this;
  5. 箭头函数:继承外层作用域的this,不动态绑定。

在实际项目中,注意箭头函数和普通函数的适用场景,通过显式绑定或箭头函数解决this丢失问题,并在严格模式下编写代码以避免全局对象污染。”,