current position:Home>[hot answer] - what is the principle of this in JavaScript?

[hot answer] - what is the principle of this in JavaScript?

2021-08-23 07:53:57 Tong ouba

Know almost the 「JavaScript Of this What is the principle ?」 Under this question : There is a sentence to explain JavaScript Of this Point to the , It's smart “ Cheat praise ” Of ; Some people say JavaScript Of this To some extent, it reflects JavaScript Deficiencies in the initial design , There is no need to study these dross too much ; Some turn out the specifications ,“ scripted ”, Maybe it will make you more “ The fog ”.

Actually , No matter JavaScript Of this It's good or not , Not bad , I think it is very important to understand its direction , At least it can make you less detours , Write less bug, It can also let you know this “ strange ” Language , To harness it , Conquer it .

I “ Poison ” Responsive Education ,“ Sincere belief “ Some concepts “ Only remember to die , To live ”. If you have time , have interest in , Let's learn from the example , Memorize it by rote , I'm sure you'll fully understand .

Last but not least : If you are JavaScript These difficult problems are not easy to torture , Please don't lose heart , If you don't believe it, turn to the answer and finally look at my point of view ?

scene 1: In the global environment this

This situation is relatively simple and direct , Functions are simply called in the browser global environment , Non strict mode this Point to window; stay use strict In the case of a strict pattern, it is undefined:

function f1 () {
    console.log(this)
}
function f2 () {
    'use strict'
    console.log(this)
}
f1() // window
f2() // undefined

Such a topic is more basic , But if you're interviewing , So candidates need to pay special attention to its variants ( Why are there always such abnormal boring interview questions ), Please look again :

const foo = {
    bar: 10,
    fn: function() {
       console.log(this)
       console.log(this.bar)
    }
}
var fn1 = foo.fn
fn1()

here this Still pointing to window. although fn Function in foo Object is referenced as a method , But when assigned to fn1 after ,fn1 The implementation of is still in window In the global environment . So output window and undefined, Or the above question , If the call changes to :

const foo = {
    bar: 10,
    fn: function() {
       console.log(this)
       console.log(this.bar)
    }
}
foo.fn()

Will be output :

{bar: 10, fn: ƒ}
10

This is actually the second case , Because at this time this It refers to the last object that calls it , stay foo.fn() In the sentence this Point to foo object . please remember : When executing a function , If in a function this It is called by the object of the upper level , that this It points to the object at the next level ; Otherwise, it points to the global environment .

scene 2: Context object call this

Let's go straight to “ difficult ” A little bit : When there are more complex call relationships ,

const person = {
    name: 'Lucas',
    brother: {
        name: 'Mike',
        fn: function() {
            return this.name
        }
    }
}
console.log(person.brother.fn())

In this nested relationship ,this Point to the object that finally calls it. , So the output will be :Mike

Let's look at a more complex topic , Please do it with me “ Examination ” To prepare :

const o1 = {
    text: 'o1',
    fn: function() {
        return this.text
    }
}
const o2 = {
    text: 'o2',
    fn: function() {
        return o1.fn()
    }
}
const o3 = {
    text: 'o3',
    fn: function() {
        var fn = o1.fn
        return fn()
    }
}

console.log(o1.fn())
console.log(o2.fn())
console.log(o3.fn())

The answer is :o1o1undefined, Are you right ?

Let's analyze one by one .

  • first console The most simple ,o1 No problem . The difficulty lies in the second and third , The key is to call this The function of .
  • the second console Of o2.fn(), Finally, call o1.fn(), So the answer is still o1.
  • the last one , It's going on var fn = o1.fn After the assignment , yes “ streaking ” call , So here's this Point to window, The answer, of course, is undefined.

If it's in an interview , I'm an interviewer , Will ask : If we need to :

console.log(o2.fn())

Output o2, What to do ?

The average developer might want to use bind/call/apply Come on this Intervene in the direction of , This is really an idea . But I went on to ask , If you can't use bind/call/apply, Is there any other way ?

const o1 = {
    text: 'o1',
    fn: function() {
        return this.text
    }
}
const o2 = {
    text: 'o2',
    fn: o1.fn
}

console.log(o2.fn())

Or apply that important conclusion :this Point to the object that finally calls it. , stay fn Execution time , Hang up o2 Object , We performed a similar assignment in advance .

scene 3:bind/call/apply change this Point to

Mentioned above bind/call/apply:

const foo = {
    name: 'lucas',
    logName: function() {
        console.log(this.name)
    }
}
const bar = {
    name: 'mike'
}
console.log(foo.logName.call(bar))

Will be output mike, It's not hard to understand . But yes. call/apply/bind High level reviews often combine constructors and combinatorial implementation inheritance . The topic of implementing inheritance , We'll talk about... Alone . Use cases of constructors , Let's analyze it in combination with the following scenarios .

scene 4: Constructors and this

The most direct example of this is :

function Foo() {
    this.bar = "Lucas"
}
const instance = new Foo()
console.log(instance.bar)

The answer will be output Lucas. But such a scenario is often accompanied by the next problem :new Operators call constructors , What exactly did you do ? The following is for reference :

  • Create a new object ;
  • Will construct the this Point to this new object ;
  • Add properties for this object 、 Such method ;
  • Finally, the new object is returned .

The above process , It can also be expressed in code :

var obj  = {}
obj.__proto__ = Foo.prototype
Foo.call(obj)

Of course , Here to new The simulation is a simple basic version , I won't go into more complicated situations .

It's important to point out that , If an explicit... Occurs in the constructor return The situation of , Well, it should be noted that there are two scenarios :

function Foo(){
    this.user = "Lucas"
    const o = {}
    return o
}
const instance = new Foo()
console.log(instance.user)

Will be output undefined, here instance Is the returned empty object o.

function Foo(){
    this.user = "Lucas"
    return 1
}
const instance = new Foo()
console.log(instance.user)

Will be output Lucas, That is to say, at this time instance Is the returned target object instance this.

Conclusion : If the constructor explicitly returns a value , And it returns an object , that this Just point to the returned object ; If the returned object is not an object , that this Still point to instance .

scene 5: In the arrow function this Point to

Arrow function use this The above standard rules are not applicable , It's based on the outer layer ( Function or global ) Context and scope .

Let's look at the topic :

const foo = {  
    fn: function () {  
        setTimeout(function() {  
            console.log(this)
        })
    }  
}  
console.log(foo.fn())

In this question ,this Appear in the setTimeout() Anonymous functions in , therefore this Point to window object . if necessary this Point to foo This object object , Can skillfully use the arrow function to solve :

const foo = {  
    fn: function () {  
        setTimeout(() => {  
            console.log(this)
        })
    }  
} 
console.log(foo.fn())

// {fn: ƒ}

In a simple arrow function this It's simple , But all things considered , combination this Priority investigation of , Now this It's not easy to be sure . Please read on .

The ultimate scene 6:this Priority related

We often pass callapplybindnew Yes this The case of binding is called explicit binding ; Determined according to the calling relationship this Pointing to is called implicit binding .

So which of explicit binding and implicit binding has higher priority ?

Please look at the example :

function foo (a) {
    console.log(this.a)
}

const obj1 = {
    a: 1,
    foo: foo
}

const obj2 = {
    a: 2,
    foo: foo
}

obj1.foo.call(obj2)
obj2.foo.call(obj1)

The outputs are 2、1, in other words callapply In general, explicit binding takes precedence over implicit binding .

function foo (a) {
    this.a = a
}

const obj1 = {}

var bar = foo.bind(obj1)
bar(2)
console.log(obj1.a)

The above code is passed bind, take bar Function this Bind as obj1 object . perform bar(2) after ,obj1.a The value is 2. That is, through bar(2) After execution ,obj1 The object is :{a: 2}.

When reuse bar As a constructor :

var baz = new bar(3)
console.log(baz.a)

Will be output 3. Let's see bar The function itself is through bind Method , Its internal has been to this Bind as obj1, It acts as a constructor again , adopt new Invocation time , The returned instance has been associated with obj1 Unbundling . in other words :

new Binding modified bind In binding this, therefore new Binding takes precedence over explicit bind Binding higher .

We'll see :

function foo() {
    return a => {
        console.log(this.a)
    };
}

const obj1 = {
    a: 2
}

const obj2 = {
    a: 3
}

const bar = foo.call(obj1)
console.log(bar.call(obj2))

Will be output 2. because foo() Of this Bound to the obj1,bar( Reference arrow function ) Of this It will also be bound to obj1, The binding of arrow function cannot be modified .

If you will foo Written entirely in the form of an arrow function :

var a = 123
const foo = () => a => {
    console.log(this.a)
}

const obj1 = {
    a: 2
}

const obj2 = {
    a: 3
}

var bar = foo.call(obj1)
console.log(bar.call(obj2))

Will be output 123.

Here I'll “ Shake your wits ”, Just the first variable in the above code a The assignment of is changed to :

const a = 123
const foo = () => a => {
    console.log(this.a)
}

const obj1 = {
    a: 2
}

const obj2 = {
    a: 3
}

var bar = foo.call(obj1)
console.log(bar.call(obj2))

The answer will be output as undefined, The reason is because of the use of const Declared variables will not be mounted to window Global objects . therefore this Point to window when , Of course not a The variable . About const perhaps let The method of declaring variables is no longer the topic of this lesson , We will also make a special introduction later .


Come here , Is there a “ Achieve mastery through a comprehensive ” It's the feeling of ? If there's still confusion , Don't lose heart .JavaScript Of this, Need to learn again and again ,“ Rote learning ” Then you can slowly experience . At least as “ Senior Engineer ” Of me , I can't guarantee that all the scenes can be answered correctly , Understanding is not in place , Find out what you're afraid of ?

I comfort myself : Maybe the difference between senior and rookie Engineers , It's not all about the accuracy of answering the test questions , It's more about how you think , Solve the problem . You don't understand this Point to , Then start to observe , Don't understand the principle , Turn it over and have a look , It's no big deal ~

Happy coding!

official account : Front end canteen

You know : Tong ouba

Nuggets : Tong ouba

This is a lifelong learning man , He's sticking to what he loves , Welcome to the front end canteen , Get fat with this man ~

“ If you think you can gain from reading this article, you can click here and let me see . Any questions during reading 、 Thoughts or feelings are also welcome to leave a message below , You can also reply to the communication group of the canteen in the background . Communication creates value , Sharing brings happiness . You are also welcome to share with the students in need , Altruism is the best self-interest . ”

This article is from WeChat official account. - Front end canteen (webcanteen)

The source and reprint of the original text are detailed in the text , If there is any infringement , Please contact the [email protected] Delete .

Original publication time : 2021-08-11

Participation of this paper Tencent cloud media sharing plan , You are welcome to join us , share .

copyright notice
author[Tong ouba],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2021/08/20210823075352618o.html

Random recommended