In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)05/31 Report--
Today, I would like to share with you the this of JavaScript pointing to the relevant knowledge points of case analysis. The content is detailed and the logic is clear. I believe most people still know too much about this knowledge, so share this article for your reference. I hope you can get something after reading this article. Let's take a look at it.
Default binding, global object
As the saying goes, the global object as a remote object is the existence of a spare tire, which serves as a backdrop for the moat of the language boundary.
In general, this pointing to a global object is the default binding. So what is the default binding?
The default binding of this can be understood as the situation in which no prefix object is called when the function is called. Because there is no prefix object called or the function has no specific binding, this points to the global object in non-strict mode.
In non-strict mode, the global variable objects of different terminals are different:
On the browser side, this points to the Window object
In the Nodejs environment, this points to the global object
In the function environment, this points to the scope where the current function is bound
In strict mode:
In a use strict environment, this points to undefined
? In non-strict mode
{/ * in non-strict mode, this default binding * / console.log ('window global this:', this); / / window function fnOuter () {console.log ('fnOuter:', this); / / window} function windowThis () {console.log ('windowThis:', this); / / window function fnInner () {console.log ('fnInner:', this); / / window fnOuter () } fnInner ();} windowThis ();}
In the above chestnut, no matter where the function declaration is and where it is called, this points to the global object window because no object was specified before when the function was called.
Note, however, that in strict mode, the this bound by default points to undefined.
? In strict mode, look at a few more chestnuts and write down the answer in mind
{/ * this default binding in non-strict mode * / var mode = 'this default binding in non-strict mode'; function windowThis () {console.log ('windowThis:', this); console.log ('windowThis:', this.mode); function fnInner () {console.log ('fnInner:', this); console.log ('fnInner:', this.mode);} fnInner () } function windowStrictThis () {'use strict'; windowThis (); function fnInner () {console.log (' windowStrictThis:', this); console.log ('windowStrictThis:', this.mode);} fnInner ();} windowStrictThis ();}
I suggest you get the answer and take a look at the following article.
Let's count down, "Chipmunk." .
? ️?
All right, let's take a look at the correct output. Are you all right?
/ / windowThis: Window {} / / windowThis: in non-strict mode, this default binding / / fnInner: Window {} / / fnInner: in non-strict mode, this default binding / / windowStrictThis: undefined// windowStrictThis: TypeError: Cannot read property 'mode' of undefined
It can be seen that after the strict mode declaration is used inside the function, the this direction becomes undefined. At the same time, the strict mode declaration within the function is only related to the variables defined in the function and the function, regardless of the external function it calls.
Turn stone into gold, implicitly bind
What is implicit binding?
This implicit binding: if there is an object calling the function in front of the function when the function is called, then this will implicitly bind to the calling object.
So the key point of implicit binding is who the object of the function is called. To put it bluntly, it is to find the point before calling the function. Who is it, who is the object bound by this.
? Take a chestnut:
{var mode = 'window'; var boss1 = {mode:' boss1', fn () {console.log (this.mode);},}; var boss2 = {mode: 'boss2', call: boss1.fn, o: boss1,}; boss2.o.fn (); / / boss1 boss2.call (); / / boss2 var boss1Copy = boss1.fn; boss1Copy (); / / window}
When a function is implicitly bound, if there is more than one object when the function is called, this points to the nearest object, that is. This points to whoever the object in front of you is.
So the question is, what's the difference if you delete mode on boss2?
? Take a chestnut:
{var mode = 'window'; var boss1 = {mode:' boss1', fn () {console.log (this.mode);},}; var boss2 = {call: boss1.fn, o: boss1,}; boss2.call (); / / undefined}
The answer is to output undefined, because at this time, because boss1 is only an attribute of boss2, the prototype chains of boss1 and boss2 are different and do not belong to the parent-child relationship, so they conform to the scope chain search rules, so this must find the mode attribute from boss2, and return undefined when the mode attribute does not exist on the boss2. Be careful not to be confused with the scope chain.
? Be careful with the following example. Can you come up with the answer?
{var mode = 'window'; var boss1:' boss1 mode', fn () {console.log (this.mode);},}; function Fn () {} Fn.prototype.mode ='Fn mode'; Fn.prototype.fnProto = function () {console.log (this.mode);}; var boss2 = {mode: 'boss2 mode', fn: function () {return boss1.fn () }, proto: new Fn (),}; boss2.fn (); / / boss1 mode boss2.proto.fnProto (); / / Fn mode}
The answer is boss1 mode and Fn mode. Oh, that's right.
When it comes to some differences between the prototype chain and the scope chain, basically there is no analysis here, please check and fill the gap.
Implicit binding is lost
I believe careful students have found that in the above example, there is a situation in which a function is assigned to a variable and then called. When the function is assigned and called again, the original this direction will change, and the this of the function will not point to its original object, resulting in the loss of invisible binding.
Common ways to cause invisible loss:
1. Function assignment variable is called again.
? Take a chestnut:
{var mode = 'window'; var boss1 = {mode:' boss1', fn () {console.log (this.mode);},}; var boss2 = {mode: 'boss2', call: boss1.fn, o: boss1,}; boss2.o.fn (); / / boss1 boss2.call (); / / boss2 var boss1Copy = boss1.fn; boss1Copy (); / / window}
In the above case, boss1Copy and boss2.call are the cases where the function assignment variable is called again.
1. Functions are passed by formal parameters
? Take a chestnut:
{var mode = 'window'; var boss1 = {mode:' boss1', fn () {console.log (this.mode);},}; function exce (params) {params & & params ();} exce (boss1.fn); / / window}
In the above example, we pass boss1.fn, that is, a function, into exce for execution. Here, only a function is passed. This is not tied to the function. In this case, this points to the original object and points to window.
It can be seen that the implicit loss is essentially caused by the function assignment. After the function is assigned to the variable or another function parameter Fn, the this will point to the nearest object when Fn is called.
Refers to the belly for marriage, explicit binding
This explicit binding: refers to changing the this direction through Object.prototype.call, Object.prototype.apply, and Object.prototype.bind methods.
Here I subdivide the explicit binding into:
Explicit binding: changing the this direction at run time
Call
Apply
Explicit hard binding: after one binding, the this direction can never be changed
Bind
Let's take a look at an example, which changes the this direction of the function log through call, apply, and bind, respectively.
? Take a chestnut:
{function log () {console.log (this.name);} var boss1 = {name: 'boss1'}; var boss2 = {name:' boss2'}; var boss3 = {name: 'boss3'}; log.call (boss1); / / boss1 log.apply (boss2); / / boss2 log.bind (boss3) (); / / boss3 var logBind = log.bind (boss3); logBind.apply (boss1); / / boss3 logBind.bind (boss2) / / boss3}
In JavaScript, when we call a function, we call it a function call, when the function is in a passive state, while bind, call and apply make the function change from passive to active, and the function can actively choose its own context, so this writing is also called function application.
Note that if you change the this point using methods such as bind, call, and apply, and the point parameter provides null or undefined, the this will point to the global object.
? Take a chestnut:
{var name = 'window'; function log () {console.log (this.name);} var boss1 = {name:' boss1'}; var boss2 = {name: 'boss2'}; var boss3 = {name:' boss3'}; log.call (null); / / window log.apply (undefined); / / window log.bind (undefined) (); / / window}
It is also worth noting that bind returns a new binding function (bound function,BF) after explicitly changing the direction of the this. A binding function is an exotic function object (a term in ECMAScript 2015) that wraps the original function object. Calling a bound function usually results in the execution of the wrapper function.
In addition, briefly add the difference between call, apply and bind:
Bind: the function hard binding this points to and returns a brand new function BF, and the returned BF cannot be pointed to by call, apply, bind change this again, and you need to execute BF to run the function.
Function.bind (thisArg [, arg1 [, arg2 [,...]) ()
Call: changes the direction of the this and executes the function, a parameter in the form of a hash.
Function.bind (thisArg [, arg1 [, arg2 [,...])
Apply: changes the direction of the this and executes a function that accepts a formal parameter in the form of an array.
Function.apply (thisArg, [param1,param2...])
The main difference between call and apply lies in the different forms of passing parameters. In the case of passing parameters, the performance of call is higher than that of apply, because apply has to parse the array one more step.
There is a universe in it, new binding.
Strictly speaking, the constructor in JavaScript is just an ordinary function called with the keyword new, it is not a class, and the object returned is not an instance, just to make it easier to understand.
An easy-to-ignore way to bind this points is to use new. When we new a function, we automatically bind the this to the new object, and then call the function. New overrides the binding of bind so that it does not take effect.
So what exactly does new do to the function? it is roughly divided into three steps:
1. Create an empty simple JavaScript object (that is, {})
two。 Add an attribute _ _ proto__, to the newly created object in step 1 to link it to the prototype object of the constructor
3. Use the newly created object in step 1 as the context of the this
4. If the function does not return an object, it returns this.
This process is called a construction call.
? So what effect does new have on this when constructing the call? Please look at Chestnut:
{function log () {console.log (this);} log (); / / window {} new log (); / / log {} var boss1 = {name: 'boss1'}; log.call (boss1); / / boss1 {} new log.call (boss1); / / Uncaught TypeError: log.call is not a constructor new log.bind (boss1); / / Uncaught TypeError: log.call is not a constructor var logBind = log.bind (boss1); logBind () / / boss1 {} new logBind (); / / log {}}
When you new a function, the this is bound to the function itself, and the keyword new points to the function itself, even if the function bind changes the this direction. And new bindings are incompatible with explicit bindings.
A mountain of military orders, arrow function
The arrow function of ES6 is an alternative, so why say it separately? this is because the this in the arrow function does not apply to the binding rules described above.
To be exact, there is no this in the arrow function, and the this of the arrow function depends on the this in the outer scope, and the this in the arrow function points to whoever the outer scope or function's this points to.
Because the this in the arrow function always points to the current lexical scope (Lexical this), it can be determined when the code is coded. There is no other this binding method to override.
The advantage of this is that it is convenient for the callback function's this to use the current scope without fear of confusion.
So for the arrow function, just look at where it was created.
? A little bit suspected of eating soft food, not tough at all, let's take a look at chestnuts:
{function fn () {return () = > {console.log ('efnArrow:', this);};} function callback (cb) {cb ();} var boss1 = {name: 'boss1', fn () {console.log (' fn:', this);}, fnArrow: () = > {console.log ('fnArrow:', this) }, ret () {return function () {console.log ('ret:', this);};}, retArrow () {return () = > {console.log ('retArrow:', this);};}, cb () {callback (function () {console.log ('cb:', this);}) }, cbArrow () {callback () = > {console.log ('cbArrow:', this);});},}; var boss2 = {name: 'boss2', fn: boss1.retArrow,}; boss1.fn (); / / fn: boss1 {} boss1.fnArrow (); / / fnArrow: window {} boss1.ret () (); / ret: window {} boss1.retArrow () () / retArrow: boss1 {} boss1.cb (); / / cb: window {} boss1.cbArrow (); / / cbArrow: boss1 {} boss1.fn.call (boss2); / / fn: boss2 {} boss1.fnArrow.call (boss2); / / fnArrow: window {} boss1.ret.call (boss2) (); / / ret: window {} boss1.retArrow.call (boss2) (); / / retArrow: boss2 {} boss1.ret (). Call (boss2) / / ret: boss2 {} boss1.retArrow (). Call (boss2); / / retArrow: boss1 {} boss1.cb.call (boss2); / / cb: window {} boss1.cbArrow.call (boss2); / / cbArrow: boss2 {} var bar = boss1.retArrow.call (boss2); bar (); / / returnArrowLog: boss2 {} bar.call (boss1); / / returnArrowLog: boss2 {} bar.bind (boss1) (); / returnArrowLog: boss2 {}}
For boss1.retArrow, why does it not work to change the this direction again after we bind this for the first time and return the arrow function?
As mentioned earlier, the this of the arrow function depends on the this pointing to boss1 when the outer scope this,boss1.retArrow function executes, so the this of the arrow function also points to boss1. In addition, the arrow function this has another feature, that is, once the arrow function's this binding is successful, it cannot be modified again, which means hard binding.
Of course, the this of the arrow function is not really impossible to modify. We know that the this of the arrow function is found from the upper scope just like scope inheritance, so we can modify the outer function this to achieve the purpose of indirectly modifying the arrow function this. For example, boss1.retArrow.call (boss2) () successfully points this to boss2.
This binding priority
I've already introduced several this binding rules, so the question is, if there are multiple binding methods for a function call, who does this end up pointing to? The answer goes straight here.
This binding priority:
Explicit binding > implicit binding > default binding
New binding > implicit binding > default binding
Why isn't explicit binding compared to new binding? Because there is no scenario in which this binding takes effect at the same time, it will be thrown wrong if you write both kinds of code at the same time, so you just need to remember the above rules.
These are all the contents of the article "this of JavaScript points to case Analysis". Thank you for reading! I believe you will gain a lot after reading this article. The editor will update different knowledge for you every day. If you want to learn more knowledge, please pay attention to the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.