JavaScript 的“this”关键字解释和揭秘
这 这个
关键字是一把双刃剑——它可能是复杂错误的来源——一旦你知道它是如何工作的,它也可以让你作为开发人员的生活更轻松。这些天来,我觉得社区将语言推向了更多功能范式。我们没有使用 这个
关键字这么多。而且我敢打赌,它仍然会使人们感到困惑,因为它的含义因上下文而异。所以,在这篇文章中, 这个
将解释关键字,以便您更好地了解它的实际工作原理。
介绍
本文适用于所有 Javascript 开发人员。您将学习以下内容:
- 什么
这个
关键字在 Javascript 中? - 什么
这个
关键字在节点中表示。 - 如何
这个
关键字在全局和函数执行上下文中确定。 - 调用函数的不同方式及其关联方式
这个
- 如何控制值
这个
使用称呼()
和申请()
方法。 - 如何使用
绑定()
方法。 - 如何
这个
表现在箭头函数中
是什么 这个
关键词
这 这个
关键字是在 Javascript 中调用函数时用于存储对象引用的变量。对象 这个
关键字引用或指向取决于上下文 这个
用于。从概念上讲, 这个
类似于英语中的代词,因为它用于指代对象——就像代词指代名词一样。
例如:“玛丽跑得很快,因为 她 正试图赶上公共汽车。”
在上面的陈述中,代词“she”用于指代先行词(先行词是代词所指的名词)“玛丽”。让我们将这个概念与 这个
关键词。
const person = { 姓名:“玛丽”,
代词:“她”,
Activity: function () { // this = person console.log(`${person.name} 跑得很快,因为 ${this.pronoun} 正试图赶上公共汽车`) } } person.Activity() // Mary 跑得很快,因为她想赶公共汽车
在前面的代码中 这个
被用作的参考值 人
对象,就像代词“she”用来指代“Mary”一样。
价值如何 这个
决定
这 这个
关键字由 执行上下文 简而言之,执行上下文是 Javascript 用于代码执行的抽象环境,它有三种变体:
- 全局执行上下文
- 函数执行上下文
还有 评估()
执行上下文,但由于其恶意性质而很少使用。读这个 文章 了解有关执行上下文的更多信息。
全局执行上下文
在全局执行上下文中, 这个
关键字引用全局对象,即 窗户
Web 浏览器上的对象。
console.log(window === this) // true this.color = 'Green' console.log(window.color) // 绿色
在前面的代码中,将一个属性添加到全局 窗户
对象通过 这个
关键词。
注意: 在全局执行上下文中 这个
无论 Javascript 是处于严格模式还是非严格模式,关键字都将始终引用全局对象。
这个
节点中的关键字
按照 NodeJS 文档
在浏览器中,顶级作用域是全局作用域。这意味着在浏览器中,如果您在全局范围 var 中,某些东西将定义一个全局变量。在 Node.js 中这是不同的。顶级范围不是全局范围; var Node.js 模块中的某些内容将是该模块的本地内容。
上述声明的意思是 这个
关键字不引用 NodeJS 中的全局对象。相反,它指向当前使用它的模块——即通过它导出的对象 模块.exports
.
例如,让我们看一个名为 应用程序.js
┣ app.js
控制台.log(this);
module.exports.color = '绿色';
控制台.log(this);
输出:
┣ $ 节点 app.js
{}
{颜色:'绿色'}
在前面的代码中,首先记录了一个空对象,因为其中没有值 模块.exports
在里面 应用程序.js
模块。然后 颜色
属性被添加到 模块.exports
对象,当 这个
再次记录更新的 模块.exports
对象返回一个 颜色
财产。
Node如何访问全局对象
我们现在知道, 这个
关键字不像在浏览器中那样引用 Node 中的全局对象。在 Node 中,全局对象是使用 全球的
关键字,无论在哪里 全球的
使用关键字。
┣ app.js console.log(global);
输出:
┣ $ node app.js // 记录节点全局对象
全局对象公开了有关 Node 环境的各种有用属性。
函数执行上下文
在函数执行上下文中如何 这个
关键字的确定取决于调用函数的方式。
可以通过四种方式调用 Javascript 函数:
- 作为函数调用
- 作为方法的调用
- 作为构造函数调用
- 使用 apply 和 call 方法调用
当一个函数被作为函数调用时(即当一个函数被使用 ()
操作员), 这个
引用全局 窗户
对象在 非严格的 模式并设置为 不明确的
在 严格的 模式。
例子
function A() { console.log(this === window) // true }
function B() { "use strict" console.log(this === window) // false } function C() { "use strict" console.log(this === undefined) // true}
一个(); // 真的
乙(); // 错误的
C(); // 真的
当函数作为方法调用时(即通过对象属性), 这个
引用该方法的“拥有”对象。
例子
让尼日利亚= {大陆:'非洲',getContinent:函数(){返回this.continent; } }
console.log(Nigeria.getContinent()); // 非洲
要将函数作为构造函数调用,我们在函数调用之前加上 新的
操作员。
例子
函数上下文(){返回这个; }
新上下文();
当函数作为构造函数调用时(通过 新的
操作员)发生了一些特殊的动作:
- 创建了一个新的空对象
- 该对象作为
这个
参考对象——即对象这个
将指向函数何时被调用。 - 新构造的对象作为
新的
运营商的价值。
例子
函数 Person() { this.name = 'Mary', this.age = 20 }
const person1 = new Person();
console.log(person1.age) // 20
前面的代码和图表显示并解释了如何 这个
当函数作为构造函数调用时,将引用一个对象。
如果您尝试在没有 新的
操作员, 这个
将指向 不明确的
,而不是一个对象。
例子
function Person() { this.name = 'Mary', this.age = 20 } const person2 = Person(); console.log(person2.age) // // => TypeError: Cannot read property 'age' of undefined
为了确保 人()
函数总是使用构造函数调用来调用的,你在开头添加一个检查 人()
功能:
function Person() { if (!(this instanceof Person)) { throw Error('必须使用 new 运算符调用函数'); }
this.name = '玛丽',
这个.age = 20 }
const person2 = Person(); console.log(person2.age) // // => 必须使用 new 运算符调用函数
ES6 引入了一个元属性,名为 新目标
这允许您检测函数是作为简单调用还是作为构造函数调用的。
您可以修改 人()
函数使用 新目标
元属性:
函数人(){
if (!new.target) { throw Error('必须使用 new 运算符调用函数'); }
this.name = '玛丽', this.age = 20 }
const person2 = Person();
控制台日志(person2.age)
// // => 必须使用new操作符来调用函数
函数是对象,和所有 Javascript 对象一样,它们也有方法。其中两种方法, 称呼()
和 申请()
,间接调用函数。这两种方法都允许您明确指定 这个
value(object reference) 用于调用,这意味着您可以调用任何函数作为任何对象的方法,即使它实际上不是该对象的方法。 称呼()
和 申请()
还允许您指定调用的参数。这 称呼()
方法使用自己的参数列表作为函数的参数,并且 申请()
方法期望将一组值用作参数。同时 称呼()
和 申请()
第一个论点是 这个
关键字——表示要在其上调用函数的对象。
例子
function getContinent(prefix) { console.log(`${prefix} ${this.continent}`); } 让尼日利亚= {大陆:'非洲'}; 让中国= {大陆:'亚洲'}; getContinent.call(nigeria, "尼日利亚在"); getContinent.call(china, "中国在");
输出:
尼日利亚在非洲 中国在亚洲
在这个例子中,我们称 获取大陆()
间接使用函数 称呼()
的方法 获取大陆()
功能。我们通过了 尼日利亚
和 中国
对象作为第一个参数 称呼()
方法,因此,我们在每次调用中都得到了对应国家的大陆。
这 申请()
方法类似于 称呼()
方法,但正如您已经知道的那样 - 它的第二个参数是一个参数数组。
getContinent.apply(nigeria, ["尼日利亚在"]); getContinent.apply(china, ["中国在"]);
输出:
尼日利亚在非洲 中国在亚洲
在箭头函数中,JavaScript 设置 这个
词汇上 .这意味着 这个
箭头函数内部由最接近的包含“非箭头”函数定义。此外,价值 这个
箭头函数内部无法更改。它在函数的整个生命周期中保持不变。
让我们看一些例子:
让 getThis = () => 这个; console.log(getThis() === 窗口); // 真的
在这个例子中, 这个
值设置为全局对象,即网络浏览器中的窗口对象。让我们借助 堆 和 堆 .
- 这
得到这个
箭头函数的词法范围是全球的()
返回全局的“非箭头”函数窗户
目的。 - 这
这个
中的价值得到这个
箭头函数是全局的窗户
对象自这个
函数的值在词法范围内指向这个对象。
让我们看另一个例子:
function confirmThis () { let getThis = () => this; console.log(getThis() === 窗口); // true } confirmThis();
输出:
由于 这个
“正常”函数的值指向全局 窗户
对象处于“非严格模式”。这 这个
值也将指向 窗户
对象,因为它的词法范围是 确认这个()
功能。但是,在“严格”模式下,情况就不同了。
function confirmThis () { "use strict" let getThis = () => this; console.log(getThis() === 窗口); // true } confirmThis();
输出:
这 这个
的价值 确认这个()
功能将是 不明确的
在严格模式下,同样适用于 得到这个
箭头函数。
该方法创建了一个新函数,在调用该函数时,该函数具有
_这个_
关键字设置为提供的值,在调用新函数时在任何提供的参数之前具有给定的参数序列。
例子
常量模块 = { x: 42, getX: function() { return this.x; } };
常量 unboundGetX = module.getX; console.log(unboundGetX());
// 函数在全局范围内被调用
// 预期输出:未定义 const boundGetX = unboundGetX.bind(module); console.log(boundGetX()); // 预期输出:42
在前面的代码中 模块
对象方法 获取X()
被调用为“函数”(而不是 模块
) 在全局范围内。这会导致它失去它 这个
参考 模块
目的。为了 这个
仍然指向 模块
对象时 得到X
方法作为“函数”而不是“方法”调用,它需要“绑定”到 模块
通过对象 绑定()
方法- const boundGetX = unboundGetX.bind(module);
.
结论
现在你知道怎么做 这个
关键字的作品及其适用的不同上下文。您应该能够在需要时舒适地使用它。
概括
在本文中,您了解了以下内容:
- 什么
这个
关键字在 Javascript 中? - 什么
这个
关键字在节点中表示。 - 如何
这个
关键字在全局和函数执行上下文中确定。 - 调用函数的不同方式及其关联方式
这个
- 如何控制值
这个
使用称呼()
和申请()
方法。 - 如何使用
绑定()
方法。 - 如何
这个
表现在箭头函数中
词汇表
堆栈或调用堆栈:堆栈是遵循后进先出 (LIFO) 原则的数据结构。但是,执行堆栈是一个跟踪代码执行期间创建的所有执行上下文的堆栈。堆栈还将静态数据存储在 Javascript(变量和参考值)中。学到更多 这里
堆:堆是Javascript中用于存储动态数据的数据结构。这是存储所有 Javascript 对象的地方。学到更多 这里 .
词法作用域:读取此堆栈溢出 回答 为了更好地理解。
Javascript 严格模式: MDN
来自编辑的提示:有关 JavaScript 内部细节的更多信息,请不要错过同一作者的其他文章: JavaScript 类型和值,解释 , 和 解释 JavaScript 的执行上下文和堆栈 .
https://newsletter.openreplay.com/
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明
本文链接:https://www.qanswer.top/38552/23172211
标签:这个,函数,对象,JavaScript,关键字,全局,揭秘,log From: https://www.cnblogs.com/amboke/p/16718603.html