JavaScript 开发人员应该理解的 this

简介: 初次接触 this 是在 c# 中,再后来的 JavaScript ,两者在 this 处理上非常相似。但是 JavaScript 是一种基于原型的编程语言,没有类的概念。意味着 this 将指向调用函数的对象,通常称为上下文。当然 this 不止于此,在函数内部的引用可以绑定到不同的对象,这得取决于函数是从哪里被调用。this 问题和变量函数提升是前端面试常见的问题,关于变量提升可以参阅《加深Javascript变量函数声明提升理解》

初次接触 this 是在 c# 中,再后来的 JavaScript ,两者在 this 处理上非常相似。但是 JavaScript 是一种基于原型的编程语言,没有类的概念。意味着 this 将指向调用函数的对象,通常称为上下文。当然 this 不止于此,在函数内部的引用可以绑定到不同的对象,这得取决于函数是从哪里被调用。this 问题和变量函数提升是前端面试常见的问题,关于变量提升可以参阅《加深Javascript变量函数声明提升理解

绑定

在 JavaScript 中,词法环境(Lexical Environments)是一种规范类型,用于根据ECMAScript代码的词法嵌套结构定义标识符与特定变量和函数的关联。一个词法环境由一个环境记录(Environment Record)和一个可能为空的外部词法环境的引用组成。通常,词法环境与ECMAScript代码的特定句法结构有关。例如函数申明、块语句、try语句中的catch等代码每次运算后会产生新的词法环境。

执行上下文(Execution Contexts)是一种规范设备,通过ECMAScript编译器来跟踪代码的运行时评估。在任何时候,每个代理(agent)最多只有一个正在执行代码的执行上下文。

每个执行上下文包含一个环境记录(Environment Record),当 JavaScript 引擎执行代码时,变量和函数名会被添加到环境记录(Environment Record)中,这就是绑定的基本概念,有助于将标识符(变量、函数名)与执行上下文的 this 关键字关联起来。

函数调用

这个很简单,this 是指调用的来源,在函数中的 this 指的是全局对象。

function callAuthor() {
    console.log(this.author);
}
callAuthor(); // undefined
var author = "DevPoint";
callAuthor(); // DevPoint

在严格模式下,this.author 的值为 undefined

let & const

如果在全局级使用 letconst 声明变量,则它们不会存储在全局对象中。相反,在不可访问的声明性环境记录中,因此前面的示例在使用 const 时输出不一样的结果。

function callAuthor() {
    console.log(this.author);
}
const author = "DevPoint";
callAuthor(); // undefined
window.author = "DevPoint";
callAuthor(); // DevPoint

隐式绑定

当函数引用有上下文对象时,隐式绑定规则会把函数中的this绑定到这个上下文对象。对象属性引用链中只有上一层或者说最后一层在调用中起作用。

const thisArticle = {
    title: "JavaScript",
    printTitle: function () {
        console.log(this.title);
    },
};
thisArticle.printTitle(); // JavaScript

如果对象只包含对 printTitle 调用函数的引用,可以获得相同的结果:

function printTitle() {
    console.log(this.title);
}
const thisArticle = {
    title: "JavaScript",
    printTitle: printTitle,
};
thisArticle.printTitle(); // JavaScript

显式绑定

通过callapplybind 方法把对象绑定到this上,叫做显式绑定。

function article() {
    console.log(this.title);
}
const thisArticle = {
    title: "JavaScript",
};
article.call(thisArticle); // JavaScript

callapply 都执行相同的操作,两者的第一个论点应该是这指向什么。如果需要将额外的参数传递给被调用的函数,则会出现差异。

  • 使用 call 时参数作以普通逗号分隔的参数列表传递
  • 使用 apply 时参数以数组方式传递
  • 使用 bind 将创建一个新函数并将其永久绑定到 this

下面创建一个将 this 永久绑定到 thisArticle 的新函数,并将 article 重新分配给该新的永久绑定函数:

function article() {
    console.log(this.title);
}
const thisArticle = {
    title: "JavaScript",
};
const newArticle = article.bind(thisArticle);
newArticle(); // JavaScript

new绑定

new 关键字构造一个新对象, this 指向它。当使用 new 关键字将函数作为构造函数调用时, this 指向创建的新对象。

function Article(title) {
    this.title = title;
}
const thisArticle = new Article("JavaScript");
console.log(thisArticle.title); // JavaScript

箭头函数

使用箭头函数,this 保持与其父作用域相同的值。例如,箭头函数中的 this 值与外面 Article 函数中的 this 值保持一致:

function Article(title) {
    this.title = title;
    this.toUpper = () => {
        return this.title.toUpperCase();
    };
}
const thisArticle = new Article("JavaScript");
console.log(thisArticle.title); // JavaScript
console.log(thisArticle.toUpper()); // JAVASCRIPT

结论

JavaScript 中的 this 是一个容器带来 Bug 的关键字,为了减少类似问题就需要加深对其 this 的理解。从上面的介绍来看,最佳的实践是尽量使用箭头函数。


相关文章
|
6月前
|
JavaScript
JS中改变this指向的六种方法
JS中改变this指向的六种方法
|
8天前
|
JavaScript 前端开发 安全
十个只有专业开发人员才知道的 JavaScript 秘密技巧
十个只有专业开发人员才知道的 JavaScript 秘密技巧
|
5月前
|
自然语言处理 JavaScript 前端开发
在JavaScript中,this关键字的行为可能会因函数的调用方式而异
【6月更文挑战第15天】JavaScript的`this`根据调用方式变化:非严格模式下直接调用时指向全局对象(浏览器为window),严格模式下为undefined。作为对象方法时,`this`指对象本身。用`new`调用构造函数时,`this`指新实例。`call`,`apply`,`bind`可显式设定`this`值。箭头函数和绑定方法有助于管理复杂场景中的`this`行为。
59 3
|
4月前
|
JavaScript
js 【详解】函数中的 this 指向
js 【详解】函数中的 this 指向
38 0
|
4月前
|
JavaScript 前端开发
|
6月前
|
JavaScript 前端开发
js中改变this指向、动态指定函数 this 值的方法
js中改变this指向、动态指定函数 this 值的方法
|
5月前
|
JavaScript
js -- 函数总结篇,函数提升、动态参数、剩余参数、箭头函数、this指向......
js -- 函数总结篇,函数提升、动态参数、剩余参数、箭头函数、this指向......
|
5月前
|
JavaScript 前端开发
JS中如何使用this方法
JS中如何使用this方法
18 0
|
6月前
|
自然语言处理 JavaScript 前端开发
在JavaScript中,this关键字的行为可能会因函数的调用方式而异
【5月更文挑战第9天】JavaScript中的`this`关键字行为取决于函数调用方式。在非严格模式下,直接调用函数时`this`指全局对象,严格模式下为`undefined`。作为对象方法调用时,`this`指向该对象。用`new`调用构造函数时,`this`指向新实例。通过`call`、`apply`、`bind`可手动设置`this`值。在回调和事件处理中,`this`可能不直观,箭头函数和绑定方法可帮助管理`this`的行为。
43 1
|
6月前
|
JavaScript 前端开发
深入探索JavaScript:如何改变this的指向
深入探索JavaScript:如何改变this的指向
47 2