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

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

相关推荐
群联云防护小杜44 分钟前
构建分布式高防架构实现业务零中断
前端·网络·分布式·tcp/ip·安全·游戏·架构
ohMyGod_1232 小时前
React16,17,18,19新特性更新对比
前端·javascript·react.js
前端小趴菜052 小时前
React-forwardRef-useImperativeHandle
前端·vue.js·react.js
@大迁世界2 小时前
第1章 React组件开发基础
前端·javascript·react.js·前端框架·ecmascript
Hilaku2 小时前
从一个实战项目,看懂 `new DataTransfer()` 的三大妙用
前端·javascript·jquery
爱分享的程序员2 小时前
前端面试专栏-算法篇:20. 贪心算法与动态规划入门
前端·javascript·node.js
我想说一句2 小时前
事件委托与合成事件:前端性能优化的"偷懒"艺术
前端·javascript
爱泡脚的鸡腿2 小时前
Web第二次笔记
前端·javascript
良辰未晚2 小时前
Canvas 绘制模糊?那是你没搞懂 DPR!
前端·canvas
Dream耀2 小时前
React合成事件揭秘:高效事件处理的幕后机制
前端·javascript