"this指南:掌握JavaScript中的上下文绑定"

this指向"死记硬背"定律

  1. 在函数体中,非显示或隐式地简单调用函数时,在严格模式下,函数内的this会被绑定到undefined上,在非严格模式下则会被绑定到全局对象window/global
  2. 一般使用new方法调用构造函数时,构造函数中的this会被绑定到新创建的对象上
  3. 显示的通过apply/call/bind绑定this指向指定的参数对象上
  4. 一般通过上下文对象调用函数时,函数内部的this绑定到该对象上
  5. 在箭头函数中,this指向外层this的指向位置

全局环境中的this

js 复制代码
function fn1() {
  console.log(this); // window
}
function fn2() {
  "use strict";
  console.log(this); // undefined
}

fn1();
fn2();

函数在浏览器全局环境中被简单调用,在严格模式下this指向为undefined。在非严格模式下this指向window对象

js 复制代码
const obj = {
  bar: 10,
  foo() {
    console.log(this);
  },
};
const fn = obj.foo;
fn(); //window

上述代码运行结果为window对象,因为最终foo函数被简单的在全局环境中被调用,所以this指向window

js 复制代码
const obj = {
  bar: 10,
  foo() {
    console.log(this);
  },
};
obj.foo(); // { bar: 10, foo: [Function: foo] }

在不考虑显示绑定的情况下:上述代码通过对象obj调用foo函数,所以函数内部的this指向obj对象,所以如果函数中的this是被上一级的对象调用的,则this指向的就是上一级对象。否则指向window对象

通过bind,apply,call,改变this指向

它们都是用来改变函数this指向,apply,call是直接进行相关函数的调用;bind不会指向相关函数,而是返回一个新的函数,这个函数的this 指向已经绑定,开发者可以手动调用。

js 复制代码
const obj = {
  bar: 10,
  foo() {
    console.log(this.bar);
  },
};
const obj1 = {
  bar: 20,
};
obj.foo.call(obj1); // 20

上述代码输出值20,通过call改变了foo函数的this指向

构造函数与this

js 复制代码
function Fn() {
  this.bar = 110;
}
const instance = new Fn();
console.log(instance.bar); // 110

上述代码输出值110,表明通过new操作符实例化构造函数,构造函数中的this指向为实例对象。

箭头函数中的this

箭头函数中的this,是由外层函数作用域或者全局作用域决定的。

js 复制代码
const obj = {
  bar: 10,
  foo() {
    setTimeout(function () {
      console.log(this.bar);
    });
  },
};
obj.foo(); // undefined

setTimeout函数传入一个匿名函数其this指向为window,作用上述代码打印undefined,如果希望setTimeout中的回调函数中this指向为obj则可以将匿名函数改为箭头函数,因为箭头函数中的this指向是根据其外层函数的this指向所决定。

js 复制代码
const obj = {
  bar: 10,
  foo() {
    setTimeout(() => {
      console.log(this.bar);
    });
  },
};
obj.foo(); // 10

this的优先级

显示绑定和隐式绑定的优先级

js 复制代码
const obj = {
  bar: 10,
  foo() {
    console.log(this.bar);
  },
};
const obj1 = {
  bar: 20,
};

obj.foo.call(obj1); // 20

上述代码输出为20,可以知道显示绑定优先级高于隐式绑定优先级

new操作符和显示绑定的优先级

js 复制代码
function fun(a) {
  this.a = a;
}
const obj3 = {};

const bar = fun.bind(obj3);
bar(100);
console.log(obj3.a); // 100

const baz = new bar(300);
console.log(baz.a); // 300
console.log(obj3); // { a: 100 }

上述代码可以看出,new 操作符在 fun.bind()之后绑定到obj3上之后,通过new bar()之后改变了barh函数的this指向。所以new操作符的优先级高于显示绑定优先级

注意:如果显示绑定的函数为箭头函数,箭头函数中的this不会被改变,按照其规则进行指向,这里我们将上例进行修改:

js 复制代码
fun = (a) => {
  this.a = a;
};
const obj3 = {};

const bar = fun.bind(obj3);
bar(100);
console.log(obj3.a); // undefined
console.log(window.a); // 100
相关推荐
kyriewen1120 分钟前
Next.js:让你的React应用从“裸奔”到“穿衣服”
开发语言·前端·javascript·react.js·设计模式·ecmascript
MXN_小南学前端20 分钟前
基于 Vue3 + ECharts 的数据大屏实例(提供gitHub仓库地址)
前端·javascript·echarts
宁雨桥28 分钟前
for of,for in以及传统for循环的区别与不同场景下的使用选择
前端·javascript
椰羊~王小美1 小时前
除了前端 JS 配置的国际化,对于 JS 没覆盖到的文本,怎么实现国际化
前端·javascript·状态模式
AC赳赳老秦1 小时前
DBA 专属方案:用 OpenClaw 实现 SQL 语句优化、慢查询分析、数据库备份巡检全自动化
服务器·前端·数据库·ffmpeg·自动化·deepseek·openclaw
燐妤1 小时前
前端HTML编程1:初识html
前端·html5
xiaoye37081 小时前
java接口文档工具 swagger2和swagger3对比
java·服务器·前端
tongyiixiaohuang1 小时前
基于轻易云的数据集成,实现企业系统间灵活对接
java·前端·数据库
哥本哈士奇2 小时前
Power BI学习笔记第17篇:Power BI Dashboard 常用布局方案推荐
前端·powerbi
军军君012 小时前
数字孪生监控大屏实战模板:固体颗粒物监管平台
前端·javascript·vue.js·typescript·前端框架·echarts·less