js中this指向哪里

JavaScript 中的 this 指向是一个重要且复杂的概念,每次记了忘忘了记,自己实操下整个文档加深下印象
  • 全局环境中的this
js 复制代码
// 在浏览器中
console.log(this);  // Window 对象

// 在 Node.js中
console.log(this);  // {} 空对象
  • 函数中的this
js 复制代码
// 普通函数调用
function test() {
    console.log(this);  // 严格模式下是 undefined,非严格模式下是 Window
}
test();

// 对象方法调用
const obj = {
    name: 'obj',
    test: function() {
        console.log(this);  // 指向 obj 对象
    }
};
obj.test();

// 箭头函数
const obj = {
    name: 'obj',
    test: () => {
        console.log(this);  // 指向定义时的上下文,这里是 Window
    }
};
obj.test();
  • 构造函数中的this
js 复制代码
function Person(name) {
    this.name = name;  // this 指向新创建的对象
    console.log(this);
}

const p = new Person('John');  // Person { name: 'John' }
  • 事件处理函数中的this
js 复制代码
<body>
<button id="btn">点击</button>
    <script>
      const button = document.getElementById('btn');

      // DOM 事件
      button.addEventListener('click', function () {
        console.log(this); // 指向触发事件的dom元素
      });

      // 箭头函数作为事件处理函数
      button.addEventListener('click', () => {
        console.log(this); // 指向定义时的上下文,这里指向window
      });
    </script>
</body>
  • call、apply、bind改变this
js 复制代码
function test() {
    console.log(this.name);
}

const obj1 = { name: 'obj1' };
const obj2 = { name: 'obj2' };

// call
test.call(obj1);  // 'obj1'

// apply
test.apply(obj2);  // 'obj2'

// bind
const boundTest = test.bind(obj1);
boundTest();  // 'obj1'
  • 类中的this
js 复制代码
class Person {
    constructor(name) {
      this.name = name; // this 指向实例
    }

    sayName() {
      console.log(this.name); // 'john'
    }

    // 箭头函数方法
    sayNameArrow = () => {
      console.log(this.name); // 'john'
    };
}

const p = new Person('John');
p.sayNameArrow(); // 'John'
  • 定时器中的this
js 复制代码
const obj = {
    name: 'obj',
    test: function () {
      setTimeout(function () {
        console.log(this); // Window
      }, 1000);

      setTimeout(() => {
        console.log(this); // obj
      }, 1000);
    },
  };
  obj.test();
js 复制代码
//如果example是箭头函数,下面不论是否严格模式都指向window

function example() {
    console.log(this); // 严格模式下是undefined 非严格模式Window
    setTimeout(() => {
      console.log(this); // 严格模式下是undefined 非严格模式Window
    }, 0);
    setTimeout(function () {
      console.log(this); // Window
    }, 0);
}

example();
  • promise中的this
js 复制代码
new Promise(function (resolve) {
    console.log(this); // 严格模式下是undefined,非严格模式下是Window
    resolve();
});

new Promise((resolve) => {
    console.log(this); // Window
    resolve();
});
js 复制代码
const obj = {
    name: 'obj',
    test: function() {
        new Promise(function(resolve) {
            console.log(this);  // 严格模式下是undefined,非严格模式下是Window
            resolve();
        });

        new Promise((resolve) => {
            console.log(this);  // obj
            resolve();
        });
    }
};
obj.test();
js 复制代码
const example = () => {
    new Promise(function (resolve) {
      console.log(this); // 严格模式下是undefined,非严格模式下是Window
      resolve();
    });

    new Promise((resolve) => {
      console.log(this); // Window
      resolve();
    });
};

example();
  • this的优先级规则
    • 优先级从高到底
      • new 绑定
      • 显式绑定 (call, apply, bind)
      • 隐式绑定 (对象方法调用)
      • 默认绑定 (普通函数调用)
js 复制代码
function test() {
    console.log(this.name);
}

const obj = { name: 'obj' };

// 1. new 绑定
new test();  // test {}

// 2. 显式绑定
test.call(obj);  // 'obj'

// 3. 隐式绑定
obj.test = test;
obj.test();  // 'obj'

// 4. 默认绑定
test();  // undefined (严格模式) 或 Window (非严格模式)
  • 常见this指向问题及解决方案
js 复制代码
const obj = {
data: [1, 2, 3],
    process: function () {
      this.data.forEach(function (item) {
        console.log(this); // 严格模式undefined;非严格模式Window
      });
    },
};
obj.process();

//解决方案1
const obj = {
    data: [1, 2, 3],
    process: function() {
        this.data.forEach(item => {
            console.log(this);  // obj
        });
    }
};

//解决方案2
const obj = {
    data: [1, 2, 3],
    process: function() {
        this.data.forEach(function(item) {
            console.log(this);  // obj
        }.bind(this));
    }
};

//解决方案3
const obj = {
    data: [1, 2, 3],
    process: function() {
        const self = this;
        this.data.forEach(function(item) {
            console.log(self);  // obj
        });
    }
};
  • 特殊情况的this
js 复制代码
// 1. 链式调用
const calculator = {
    value: 0,
    add(num) {
        this.value += num;
        return this;  // 返回 this 实现链式调用
    },
    multiply(num) {
        this.value *= num;
        return this;
    }
};

calculator.add(5).multiply(2).add(3);  // value = 13

// 2. 工厂函数
function createPerson(name) {
    return {
        name,
        sayName() {
            console.log(this.name);
        }
    };
}

// 3. 类继承
class Animal {
    constructor(name) {
        this.name = name;
    }
    speak() {
        console.log(this.name + ' makes a noise.');
    }
}

class Dog extends Animal {
    speak() {
        super.speak();  // 调用父类方法
        console.log(this.name + ' barks.');
    }
}

记住 this 指向的关键点:

  1. 箭头函数没有自己的 this,继承自外层作用域
  1. 普通函数的 this 在调用时确定
  1. 严格模式会影响 this 的默认值
  1. 可以通过 call、apply、bind 改变 this 指向
  1. 对象方法中的 this 指向调用该方法的对象
  1. 构造函数中的 this 指向新创建的对象

上面每个打印都亲自真机打印的,说实话人麻了,太复杂了,这个记住关键点的情况下还得多练,否则碰到实际情况还是一脸懵

相关推荐
再吃一根胡萝卜2 分钟前
🔍 当 `<a-menu>` 遇上 `<template>`:一个容易忽视的菜单渲染陷阱
前端
Asort18 分钟前
JavaScript 从零开始(六):控制流语句详解——让代码拥有决策与重复能力
前端·javascript
无双_Joney37 分钟前
[更新迭代 - 1] Nestjs 在24年底更新了啥?(功能篇)
前端·后端·nestjs
在云端易逍遥39 分钟前
前端必学的 CSS Grid 布局体系
前端·css
ccnocare40 分钟前
选择文件夹路径
前端
艾小码40 分钟前
还在被超长列表卡到崩溃?3招搞定虚拟滚动,性能直接起飞!
前端·javascript·react.js
闰五月41 分钟前
JavaScript作用域与作用域链详解
前端·面试
泉城老铁1 小时前
idea 优化卡顿
前端·后端·敏捷开发
前端康师傅1 小时前
JavaScript 作用域常见问题及解决方案
前端·javascript