javascript步骤_通过4个简单的步骤了解JavaScript中的“ this”并确定其值

javascript步骤

Every frontend developer at some point of his career has stumbled into thisin JavaScript and my bet is the first experience wasn’t very clear.

每个前端开发人员在其职业生涯的某个阶段都已经在JavaScript中碰到了this ,我敢打赌,第一次体验并不是很清楚。

It turns out that in fact this in JavaScript can be understood and that we can even follow a simple 4 step procedure to determine it’s value. Let’s solve this riddle.

事实证明,其实this在JavaScript中可以理解的,我们甚至可以遵循一个简单的4步程序,以确定它的价值。 让我们解决这个难题。

介绍 (Introduction)

If you are looking into thisit probably means one of the three things:

如果您正在研究this则可能意味着以下三件事之一:

  • you stumbled upon some bug, lost hours and have thought to yourself that it’s finally time to understand this. Or maybe you have to support some legacy project

    您偶然发现了一些错误,浪费了很多时间,并自以为是this了解this 。 也许您必须支持一些旧项目

  • you are preparing for a job interview or some sort of an exam (yes, thiswill be asked :) )

    您正在准备面试或某种形式的考试(是的, this将被要求:))

  • you are just curious about JavaScript

    您只是对JavaScript感到好奇

As a disclaimer, I know a lot of developers who (without fully understanding this) still manage to write production quality code.

作为免责声明,我知道许多开发人员(在没有完全理解this )仍然设法编写生产质量代码。

For instance, if you work in React for not a long time, chances are that you operate on functional components and hooks only and haven’t seen this for a long time.

例如,如果您在React中工作了很长时间,那么您很可能只在功能组件和钩子上操作,而且很长一段时间都没有看到this

I personally believe that it’s worth to have an understanding of the basics as this is really not that difficult and at some point of your career it will definitely pay off.

我个人认为,对基础知识有所了解是值得的,因为this并不是那么困难,并且在您的职业生涯的某个阶段肯定会有所收获。

TL; DR (TL;DR)

To determine value of this we just have to follow simple 4 step procedure. It comes down to inspecting where and how it’s called.

要确定this值,我们只需遵循简单的4步过程。 它取决于检查它的调用位置和调用方式。

The first condition that we meet determines this value.

我们满足的第一个条件决定了this值。

  1. Did we use new keyword i.e. new MyFunction()?

    我们是否使用过new关键字,即new MyFunction()

  2. Did we use call, bind, apply i.e. myObject.myFunction.call(myObject2) ?

    我们是否使用过call, bind, apply myObject.myFunction.call(myObject2)

  3. Did we use the dot notation i.e. myObject.myFunction()?

    我们是否使用了表示法即myObject.myFunction()

  4. Did we use free function invocation i.e. window.myFunction() or just myFunction() ?

    我们是否使用自由函数调用,window.myFunction()或仅myFunction()

Above does not apply for arrow functions. For arrow functions we have to inspect thisvalue of the surrounding context.

以上不适用于箭头功能。 对于箭头函数,我们必须检查周围上下文的this值。

Have a read below for more detailed explanation.

请在下面阅读以获取更详细的说明。

遵守规则 (Rules to follow)

There are four rules that we need to inspect in order to determine this.Disclaimer — none of these values apply to arrow functions — more on that later on.

为了确定this规则,我们需要检查四个规则。免责声明-这些值均不适用于箭头功能-稍后会详细介绍。

1. The newkeyword.

1. new关键字。

JavaScript has the keyword new. If we use it when we call the function, this inside the function is new object.

JavaScript具有关键字new 。 如果在调用函数时使用它,则函数内部的this对象为新对象。

function Example() {
console.log(this); // {}
this.value = 'puma';
console.log(this); // { value: 'puma' }
}new Example()

As an important side note — if we are to call the Example() without the new keyword, in the browser enviroment we would create ourselves a Window.valuevariable, which can easily lead to bugs (look into point 4 for more details).

作为重要的Window.value说明—如果不使用new关键字调用Example() ,则在浏览器环境中,我们将为自己创建一个Window.value变量,该变量很容易导致错误(更多信息请参见第4点)。

Example();// function invoked without the new keyword refers this to Window
// Window { parent: Window, opener: null, top: Window ... }

If we are in strict (‘use-strict’) mode (on production level we must be), things change a bit:

如果我们处于严格(“ 使用严格”)模式(必须处于生产级别),那么情况会有所变化:

Example(); // undefinedwindow.Example() 
// Window { parent: Window, opener: null, top: Window ... }

2. The trio call, bind, apply. If either of them is used, this inside the function is the object in the argument.

2.三重call, bind, apply 。 如果使用它们中的, this功能是内部参数中的对象。

function exampleFunction() {  console.log(this);}const obj = {  value: 'puma'};const boundedFunction = exampleFunction.bind(obj);boundedFunction();     // { value: 'puma' }exampleFunction.call(obj);  // { value: 'puma' }exampleFunction.apply(obj); // { value: 'puma' }exampleFunction(obj) // Window 
// undefined in strict mode

3. Calling function as object or class method.

3.调用函数作为对象或类方法。

This is actually quite intuitive.

这实际上是非常直观的。

Whenever we have an object that has a method and we use a dot notation to invoke the function, this is the object to the left of the dot i.e.

每当我们有一个具有方法的对象并且我们使用点符号来调用该函数时, this就是点左侧的对象,即

const myObject = {
value: 'puma',
myFunction: function() {
console.log(this);
}
};myObject.myFunction(); // this is the object to left of the dot// -> { value: 'puma', myFunction: ƒ }

4. Free function invocation

4. 自由函数调用

This is very similar to point 3. If we create a function not as a method, it automatically becomes a property of global object, window.

这与第3点非常相似。如果我们创建的函数不是方法 ,则它会自动成为全局对象window的属性。

function myFunction() {
console.log(this);
}myFunction();window.myFunction();// if not in strict mode
// this is doing exactly the same thing
// output if called in browser// Window {stop: ƒ, open: ƒ, alert: ƒ, ...}

In this scenario, this is a global object — window. Remember how in point 3 we said myObject.myFunction? We have said that this is an object that is on the left hand side of the dot i.e. myObject. Same rule applies when we say window.myFunction. Should we say myFunction what we implicitly say is window.myFunction.

在这种情况下, this是一个全局对象window 。 还记得我们在第3点中所说的myObject.myFunction吗? 我们已经说过, this是一个位于点左侧的对象,即myObject 。 当我们说window.myFunction时,同样的规则适用。 我们应该说myFunction ,我们隐式说的是window.myFunction

console.log(myFunction === window.myFunction); // true

This looks slightly different in the strict mode:

strict模式下,这看起来略有不同:

'use strict';function myFunction() {
console.log(this);
}myFunction(); // undefined
window.myFunction(); // Window { ... }

5. If multiple rules apply, the one on the top takes precedence. For instance, rule 2 (call) takes precedence over rule 3 (the dot notation).

5.如果有多个规则,则顶部的规则优先。 例如,规则2( call )优先于规则3( 表示法)。

new keyword 
call, bind, apply
myObject.myFunction
window.myFunction

箭头功能 (Arrow functions)

Arrow functions are a special case. One of the key reasons they were created, was to simplify this.

箭头功能是一种特殊情况。 创建它们的关键原因之一就是简化了this

Rules introduced earlier are ignored, and this value receives the value of the surrounding scope.

前面介绍的规则将被忽略,并且this值接收周围范围的value

In simple terms, we can go level above the arrow function and inspect this value in that level. The arrow function has the same this value i.e.

简而言之,我们可以在箭头功能之上进行检查,并在该级别中检查this值。 箭头功能具有相同的this值,即

const myObject = {  value: "puma",  createArrowFunction: function () {    return () => console.log(this);  },};const arrowFunction = myObject.createArrowFunction();arrowFunction();// { value: "puma", createArrowFunction: ƒ }

We often meet with arrow functions in React be it class or functional components.

我们经常在React中遇到箭头函数,无论是类还是功能组件。

As a side note, you cannot use new with arrow functions — they cannot be used as a constructor.

附带说明,您不能使用带箭头的new函数-它们不能用作构造函数。

const myArrowFunction = () => console.log(this)new myArrowFunction();// Uncaught TypeError: myArrowFunction is not a constructor

练习题 (Exercises)

Let’s put the theory into practice and try to determine this value.

让我们将理论付诸实践,并尝试确定this值。

第一次练习 (First exercise)

const myObject = {  value: "puma",  myFunction: function () {    console.log(this);  },};const printThis = myObject.myFunction;myObject.myFunction(); // { value: "puma", printThis: ƒ }printThis(); // in non strict mode: Window {stop: ƒ, open: ƒ, alert: ƒ, ...}

ok, so what is going on here?

好的,这是怎么回事?

myObject.myFunction()

myObject.myFunction()

To understand the result let’s go through the rules we have learned at the beginning of the article:

为了了解结果,让我们仔细阅读本文开头所学的规则:

First rule — have we used new keyword? No, moving on.Second rule — have we used call, bind, apply? No, moving on.Third rule — have we used dot notation? Yes, we have. This is why this has the value of object from left hand side of the dot.

第一条规则-我们是否使用了new关键字? 不,继续前进。第二条规则-我们使用过call, bind, apply吗? 不,继续。第三条规则-我们是否使用符号? 是的我们有。 这就是为什么this 从点的左侧开始具有object的值。

printThis()

printThis()

This is in fact a common interview question. Let’s inspect the rules one more time:

这实际上是一个常见的面试问题。 让我们再检查一次规则:

First rule — new keyword? No, moving on.Second rule — call, bind, apply? No, moving on.Third rule — dot notation? No, moving on.Fourth rule — free function invocation — yes. This is the rule that we have met. In strict mode, we would get undefined value, in not strict mode we will get globalWindow object.

第一法则- new关键字? 不,继续前进。第二条规则- call, bind, apply ? 不,继续前进。第三条规则- 符号? 不,继续。第四条规则- 自由函数调用 -是的。 这是我们遇到的规则。 在严格模式下,我们将获得undefined值,在非严格模式下,我们将获得全局的Window对象。

第二次练习 (Second exercise)

To start with, I haven’t seen code like that for a long time. Sometimes we do however have to support legacy projects. Or pass a job interview and questions related to this are still very common one.

首先,我已经很长时间没有看到类似的代码了。 但是有时我们确实必须支持旧项目。 或通过求职面试,与this相关的问题仍然很常见。

const myObject = {  value: "puma",  myFunction: function () {    console.log(this);  },};const myObject2 = { value: "Will I overwrite myObject.value?" };myObject.myFunction.call(myObject2);// { value: "Will I overwrite myObject.value?" }

In order to understand what is going on here, let’s go through the rules once again:

为了了解这里发生的情况,让我们再次仔细阅读规则:

  1. Have we used new? No, moving on.

    我们使用过new吗? 不,继续前进。

  2. Have we used call, bind, apply ? Yes, we have. This rule tells us that this value will take the myObject2. This is our answer but for the sake of understanding we will go one level down.

    我们是否使用过call, bind, apply ? 是的我们有。 该规则告诉我们, this值将采用myObject2 。 这是我们的答案,但是为了理解,我们将下一层。

  3. Have we used dot notation? Yes, we have. But Rule 2 is more important hence take precedence.

    我们使用符号了吗? 是的我们有。 但是规则2更重要,因此优先。

关于库的警告 (A word of caution about libraries)

This article applies to Vanilla JavaScript concepts. Some libraries change behaviour of this. For instance, jQuery binds this to the DOM element triggering an event in the callback to that event i.e.

本文适用于Vanilla JavaScript概念。 一些库会更改this行为。 例如,jQuery this绑定到DOM元素,从而在该事件的回调中触发一个事件,即

<button class = "click-me"> jQuery bind this to me </button>$('.click-me').on('click', function() {});

If a library changes this behaviour, always verify it’s documentation. Most likely it’s using bind to bound.

如果图书馆this了更改 行为,请始终验证其文档。 最有可能的是使用bind绑定。

摘要 (Summary)

As we can see, determining this value is not that difficult if we follow a simple procedure.

如我们所见,如果遵循简单的过程,确定this值并不困难。

The first condition that we meet determines this value.

我们满足的第一个条件决定了this值。

  1. Did we use new keyword i.e. new MyFunction()?

    我们是否使用过new关键字,即new MyFunction()

  2. Did we use call, bind, apply i.e. myObject.myFunction.call(myObject2) ?

    我们是否使用过call, bind, apply myObject.myFunction.call(myObject2)

  3. Did we use the dot notation i.e. myObject.myFunction()?

    我们是否使用了表示法即myObject.myFunction()

  4. Did we use free function invocation i.e. window.myFunction() or just myFunction() ?

    我们是否使用自由函数调用,window.myFunction()或仅myFunction()

Above does not apply for arrow functions. In that case, we have to inspect thisvalue of the surrounding context.

以上不适用于箭头功能。 在这种情况下,我们必须检查周围环境的this值。

Happy debugging and enjoy the interview!

调试愉快,享受采访!

翻译自: https://medium.com/@tymekluczko/determining-and-understanding-this-in-javascript-in-4-simple-steps-278d672a0326

javascript步骤

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值