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 指向新创建的对象

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

相关推荐
liliangcsdn6 分钟前
mac mlx大模型框架的安装和使用
java·前端·人工智能·python·macos
CssHero9 分钟前
基于vue3完成领域模型架构建设
前端
PanZonghui12 分钟前
用项目说话:我的React博客构建成果与经验复盘
前端·react.js·typescript
言兴15 分钟前
教你如何理解useContext加上useReducer
前端·javascript·面试
sunbyte18 分钟前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | GoodCheapFast(Good - Cheap - Fast三选二开关)
前端·javascript·css·vue.js·tailwindcss
前端的日常20 分钟前
网页视频录制新技巧,代码实现超简单!
前端
前端的日常21 分钟前
什么是 TypeScript 中的泛型?请给出一个使用泛型的示例。
前端
今禾23 分钟前
一行代码引发的血案:new Array(5) 到底发生了什么?
前端·javascript·算法
ccc101825 分钟前
老师问我localhost和127.0.0.1,有什么区别?
前端
Struggler28132 分钟前
Chrome插件开发
前端