Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

The misunderstanding and binding rules of this in JavaScript and what are the common problems?

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

JavaScript this misunderstanding and binding rules and common problems, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain in detail for you, people with this need can come to learn, I hope you can gain something.

I believe that this in Javascript will make many students confused in their work and study, the author is also, after reading a variety of materials and practical work applications, did the following comb, the main content, including the long-term misunderstanding of this and this binding rules, arrow functions, the actual work scene problems encountered, I hope you can help with this confusion.

First, two kinds of misunderstandings

1. Point to yourself.

The first misunderstanding of this is that it is easy to understand this as pointing to the function itself. In fact, the direction of this cannot be determined in the function definition stage, and only when the function is executed can it be determined who the this points to. The actual this ultimately points to the object from which it is called.

In the following example, the function foo () is declared, and when foo.count=0 is executed, an attribute count is added like the function object foo. But the this in the internal code this.count of the function foo does not point to that function object. The object that foo (I) in the for loop uses is window, which is equivalent to window.foo (I), so the this in the function foo points to window.

Function foo (num) {this.count++; / / record the number of times foo is called} foo.count = 0; window.count = 0; for (let item0; I 5) {foo (I);}} console.log (foo.count, window.count); / / 0 4

two。 Point to the scope of the function

The second misunderstanding of this is that this points to the scope of a function.

The following code, which attempts to call the bar function in foo, depends on the environment.

Browser: there is no problem in the browser environment. The globally declared function is placed under the window object. The this in the foo function refers to the window object, and the variable an is not declared in the global environment, so the this.an in the bar function is naturally not defined and outputs undefined.

Node.js: in the Node.js environment, the declared function is not placed under the global global object, so calling the this.bar function in the foo function will report a TypeError: this.bar is not a function error. To run without reporting errors, omit the previous this when calling the bar function.

Function foo () {var a = 2; this.bar ();} function bar () {console.log (this.a);} foo ()

II. Four binding rules of This

1. Default binding

When a function call is a stand-alone call (a call without a function reference) and cannot call other binding rules, we give it a name "default binding", which binds to the global object in non-strict mode and to undefined in strict mode (use strict).

Call in strict mode:

'use strict' function demo () {/ / TypeError: Cannot read property 'a'of undefined console.log (this.a);} const a = 1; demo ()

Called in non-strict mode:

In the browser environment, an is bound to window.a, and the following code uses the variable a declared by var to output 1.

Function demo () {console.log (this.a); / / 1} var a = 1; demo ()

The following code declares the variable a using let or const and the result outputs undefined

Function demo () {console.log (this.a); / / undefined} let a = 1; demo ()

When giving an example, you actually want to focus on the default binding relationship of this, but you will find that the results of the above two kinds of code are also different because they are declared using var and let respectively. The reason is related to the concept of top-level objects.

Children's shoes mention this question in Issue: Nodejs-Roadmap/issues/11, which is also an oversight before. Let's briefly talk about the concept of top-level object. The attributes of top-level objects (browser environment refers to window, Node.js environment refers to Global) are equivalent to global variable attributes. Properties of top-level objects are declared using var and function, and let belongs to the ES6 specification, but the global variables declared by let, const and class in ES6 specification Properties that no longer belong to the top-level object.

two。 Implicit binding

It is contained by an object at the calling location of the function and has the context. See the following example:

Function child () {console.log (this.name);} let parent = {name: 'zhangsan', child,} parent.child (); / / zhangsan

The function uses the parent object context to refer to the function child when the function is called, which can be understood to mean that the parent object owns or contains the child function when it is called.

Hidden dangers of implicit binding:

The function that is implicitly bound, because some careless operations will lose the bound object, the default binding in the binding rule mentioned at the beginning will be applied, see the following code:

Function child () {console.log (this.name);} let parent = {name: 'zhangsan', child,} let parentparent2 = parent.child; var name =' lisi'; parent2 ()

Assigning the parent.child function itself to parent2, calling parent2 () is actually a function call without any modification, so the default binding is applied.

3. Show bindings

Show binding and implicit binding are understood literally, there is an opposite contrast, one is more direct, the other is more euphemistic, let's take a look at the respective meanings of the two rules:

Implicit binding: the this is implicitly bound to the function that the object's internal property points to (for example, the child property reference function function child () {} of the object parent in the above example) by indirectly referencing the function inside an object.

Show binding: mandatory binding calls are made when an object needs to be referenced. Js provides call () and apply () methods, and ES5 also provides a built-in method Function.prototype.bind.

The first argument to both the call () and apply () functions is to set the this object. The difference is that apply passes parameters as an array, while call passes them one by one.

Function fruit (... args) {console.log (this.name, args);} var apple = {name: 'Apple'} var banana = {name: 'banana'} fruit.call (banana, 'asides,' b') / / ['axiao,' b'] fruit.apply (apple, ['ajar,' b']) / / ['aqu,' b']

The following is an example of bind binding, which simply binds a value to the this of the function and returns the bound function. The information is output only when the fruit function is executed, for example:

Function fruit () {console.log (this.name);} var apple = {name: 'Apple'} fruitfruit = fruit.bind (apple); fruit (); / / Apple

In addition to the above call, apply, bind, you can also use context context, for example:

Function fruit (name) {console.log (`${this.name}: ${name}`);} const obj = {name: 'this is fruit',} const arr = ['apple', 'banana']; arr.forEach (fruit, banana); / / this is fruit: Apple / / this is fruit: banana

4. New binding

The new binding can also affect the this call, which is a constructor, and each new binding creates a new object.

Function Fruit (name) {this.name = name;} const F1 = new Fruit ('apple'); const f2 = new Fruit (' banana'); console.log (f1.name, f2.name); / / apple banana

III. Priority

If multiple binding rules are applied to the calling location of this, it has priority: new binding-> Show binding-> implicit binding-> default binding.

IV. Arrow function

The arrow function is not defined using the function keyword, nor does it use the four this standard specifications described above. The arrow function inherits from the this binding of the outer function call.

When fruit.call (apple) is executed, the arrow function this is bound and cannot be modified again.

Function fruit () {return () = > {console.log (this.name);}} var apple = {name: 'Apple'} var banana = {name: 'banana'} var fruitfruitCall = fruit.call (apple); fruitCall.call (banana); / / Apple

5. Several common problems in the use of This

1. Simulate classes through functions and prototype chains

The following example defines the function Fruit, then defines the info method on the prototype chain, and instantiates object F1 and defines object f2 to call the info method, respectively.

Function Fruit (name) {this.name = name;} Fruit.prototype.info = function () {console.log (this.name);} const F1 = new Fruit ('Apple'); f1.info (); const f2 = {name:' Banana'}; f2.info = f1.info; f2.info ()

After the output, the two results are different, because the this in the info method does not correspond to the context in which it is defined, but the context in which it is called. According to the binding rules mentioned above, it corresponds to the implicit binding rules.

Apple Banana

two。 Use the arrow function on the prototype chain

If you use constructors and prototype chains to simulate classes, you cannot define the arrow function on the prototype chain, because the this in the arrow function inherits the this binding of the outer function call.

Function Fruit (name) {this.name = name;} Fruit.prototype.info = () = > {console.log (this.name);} var name = 'Banana' const F1 = new Fruit (' Apple'); f1.info ()

3. Use in events

Take an example of Node.js. When used in an event, when our listener is called, if a normal function is declared, this will be pointed to the EventEmitter instance bound by the listener. If the arrow function is used, this will not point to the EventEmitter instance.

Const EventEmitter = require ('events'); class MyEmitter extends EventEmitter {constructor () {super (); this.name =' myEmitter';}} const func1 = () = > console.log (this.name); const func2 = function () {console.log (this.name);}; const myEmitter = new MyEmitter (); myEmitter.on ('event', func1); / / undefined myEmitter.on (' event', func2); / / myEmitter myEmitter.emit ('event') Is it helpful for you to read the above content? If you want to know more about the relevant knowledge or read more related articles, please follow the industry information channel, thank you for your support.

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.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report