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

How to deal with this binding method call apply bind

2025-02-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

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

Editor to share with you how to deal with the this binding method call apply bind, I believe that most people do not know much about it, so share this article for your reference, I hope you can learn a lot after reading this article, let's learn about it!

Let's take a look at an example.

Var obj = {}; / / create an object obj.name = "James"; / / add a property to the object obj.say = function () {/ / add a method console.log ('My name is' + this.name) to the object;}; obj.say (); / / this points to obj, so output "My name is James" var fn = obj.say;fn () / / this points to window. There is no name variable in the global, so you can only output "My name is" without name.

Because the this in fn points to window instead of obj, name has no output. If you also want fn to output James, it means that you have to make the this in fn point to obj. At this point, you need to forcibly change the direction of this.

The call method, you can specify the direction of the this inside the function (that is, the scope in which the function is executed), and then call the function in the specified scope.

Var obj = {}; / / create an object obj.name = "James"; / / add a property to the object obj.say = function () {/ / add a method console.log ('My name is' + this.name) to the object;}; obj.say (); / / this points to obj, so output "My name is James" var fn = obj.say;fn.call (obj); / / output "My name is James"

In the above code, the this of the fn function points to the window,call method, which changes the direction of the this so that the this object points to the obj, and then runs the function fn in the scope of the object obj

The argument to the call method is an object, and if the parameters are empty, null and undefined, the global object is passed in by default. Let's modify the above example:

Var name = 'Kobe'; / / define the global variable var obj = {}; / / create an object obj.name = "James"; / / add a property obj.say = function () {/ / add a method console.log (' My name is' + this.name) to the object;}; var fn = obj.say;fn.call (); / / output "My name is Kobe" fn.call (null) / output "My name is Kobe" fn.call (undefined); / output "My name is Kobe" fn.call (window); / / output "My name is Kobe" fn.call (obj); / / output "My name is James"

The call method can also accept multiple parameters func.call (the object to which this points, parameter 1, parameter 2...) The first parameter of the call method is the object to which this points, and the following argument is the required parameter when calling the function

Var uname = 'Kobe';var team =' Lakers';var num = 24 My name is'+ this.uname+', obj = {}; obj.uname = 'Westbook';obj.team =' Thunder';obj.num = 0poliobj.introduce = function () {console.log ('My name is'+ this.uname+', I am from'+this.team+',My number is'+this.num);}; var fn = obj.introduce;fn (); / / My name is Kobe, I am from Lakers,My number is 24fn.call (obj,uname,team,num) / / My name is Westbook, I am from Thunder,My number is 0

In this code, the this of the fn function points to window, and the global variable is output when fn is executed. Point the this to the obj object through the call method, and then run the function fn in the scope of obj, so the output is Westbook instead of Kobe

The function of the apply method is similar to that of the call method, changing the direction of the this and then calling the function. The only difference is that it takes an array as a parameter when the function is executed, using the following format:

Func.apply (the object to which this points, [parameter 1, parameter 2...])

So in the above example, in addition to using the call method, we can also use the apply method

Fn.apply (obj, [uname,team,num]); / / My name is Westbook, I am from Thunder,My number is 0

Practical application of apply method:

1. Find the largest element in the array

The Math object provides the API to obtain the maximum and minimum values

Math.max (a _ c.

Math.min (a _ c.

Problem: max and min do not support getting the maximum value in the array, because Javascript does not provide an API to obtain the maximum value of the array. The solution is: Math.max.apply (null, [a ~ ~ b.])

2. Change the empty elements of the array to undefined

The difference between empty elements and undefined is that the array's forEach method skips empty elements, but not undefined. So, you get different results when you traverse the internal elements

Var arr= ['console.log,' b']; function show (I) {console.log (I);}; arr.forEach (show); / / a bArray.apply (null,arr) .forEach (show); / / a undefined b

3. Convert the class array object to a real array (both call and apply are OK)

Array.prototype.slice.call (obj)-- > obj is a class array, which allows you to convert the class array into a real array (the argument position is the class array).

The parameters in the above apply/call method are all objects, and the results are all arrays, which serves the purpose of converting objects into arrays. At the same time, it can be seen that the premise that this method works is that the object being processed must have a length attribute and the corresponding numeric key.

Object.prototype.toString.call (arg)-- > arg can be any type of value, and this function determines the type of parameter most accurately.

4. Bind the object of the callback function

Buttonvar obj = new Object (); obj.fun = function () {console.log (this===obj); / / this object points to obj}; var fun = function () {/ / Global function fun,this points to window obj.fun.apply (obj); / / forcibly points this to obj (call can also be used here)}; var button = document.getElementById ('button'); button.onclick=function () {fun ();}

After clicking the button, the console will display true. Because the apply method (or call method) not only binds the object in which the function is executed, but also executes the function immediately, the binding statement has to be written in the body of a function. A more concise way of writing is to use the bind method described below.

The bind method is used to bind the this in the body of a function to an object and return a new function.

Var obj = {}; obj.name = "Kobe"; obj.say = function () {/ / this points to obj console.log ("My name is" + this.name);}; var fn = obj.say.bind (obj); / / the global function fn,this points to windowfn (); / / My name is Kobe

After the say method of obj assigns a global variable fn, the this of fn points to window, so it is not possible to output name. Now force the this to point to the obj object through the bind method.

The bind method goes further than the call/apply method by binding the parameters of the original function in addition to binding this

Var add = function (x, y) {console.log (x * this.m + y * this.n);}; var obj = {m: 2, n: 3}; var newAdd = add.bind (obj, 5); newAdd (6); / / 28 5*2+6*3newAdd (8); / / 34 5*2+8*3newAdd (10); / 40 5 / 2 / 10

In the above code, bind not only binds the this object, but also binds the first parameter x of the add function to 5, and then returns a new function newAdd, which can run as long as it takes one more argument y

For further verification, we can change the above code a little bit

Var add = function (x, y) {console.log (x * this.m + y * this.n);}; var obj = {m: 2, n: 3}; var newAdd = add.bind (obj, 5,6); newAdd (6); / / 28newAdd (8); / / 28newAdd (10); / / 28newAdd (11pm 12); / / 28

Now the parameter x is 5 and the value is 6. No matter how the value is passed to the newAdd function, the output cannot be changed.

If the first parameter of the bind method is null or undefined, then this is bound to the global object window

Function add (x, y) {console.log (x + y);} var plus = add.bind (null, 5); / / this points to window,x and binds to 5plus (10); / / 15 yong 10 5+10plus (10Ling 10); / / 15 x has been bound to 5 and cannot be changed to 10

In the above code, there is no this inside the function add. The main purpose of using the bind method is to bind the parameter x. Each time you run the new function plus, you only need to provide another parameter y. And because there is no this inside add, the first parameter of bind is null, but if it is any other object here, it doesn't matter.

For older browsers that do not support the bind method, you can define the bind method yourself.

If (! ('bind' in Function.prototype)) {Function.prototype.bind = function () {var fn = this; var context = arguments [0]; var args = Array.prototype.slice.call (arguments, 1); return function () {return fn.apply (context, args);}

Note when using the bind method:

1. Return a new function at a time

Every time the bind method is run, it returns a new function, which creates some problems. For example, when monitoring an event, it cannot be written as follows

Element.addEventListener ('click', o.m.bind (o)); element.removeEventListener (' click', o.m.bind (o))

In the above code, the click event binds an anonymous function generated by the bind method. This makes it impossible to unbind, so the above code is invalid. The correct way to write:

Var listener = o.m.bind (o); element.addEventListener ('click', listener); / /... element.removeEventListener (' click', listener)

2. Use in combination with callback function

The callback function is one of the most commonly used patterns in Javascript, but a common mistake is to treat the method containing this as the callback function directly.

Var counter = {count: 0, inc: function () {'use strict'; / / Note: in strict mode, the this object is undefined this.count++; / / this object, not counter alert (this);}}; function callIt (callback) {/ / global function callIt's this object is not window callback () in strict mode either;} callIt (counter.inc); / / Uncaught TypeError: Cannot read property' count' of undefined

In the above code, the counter.inc method is treated as a callback function and callIt is passed in. When called, the internal this points to the object in which the callIt runs, that is, the top-level object window, so the expected result is not obtained. Note that the counter.inc method above uses strict mode internally, where the this will report an error when it points to the top-level object, but the normal mode will not.

The solution is to use the bind method to bind counter.inc to counter.

Var counter = {count: 0, inc: function () {'use strict'; / / Note: in strict mode, the this object is undefined console.log (this.count++); / / this object is not counter}}; function callIt (callback) {/ / global function callIt's this object is not window callback () in strict mode either;} callIt (counter.inc.bind (counter)) / / 0 pay attention to the difference between the first + + and the latter + +. The former + + returns the new value, and the latter + + returns the old value callIt (counter.inc.bind (counter)); / / 1

Another hidden situation is that some array methods can accept a function as an argument. The this points inside these functions are likely to go wrong as well.

Var obj = {name: 'Zhang San', times: [1,2,3], print: function () {/ / this points to obj this.times.forEach (function (n) {/ / this points to window console.log (this.name);});}}; obj.print ()

You just need to divide the direction of the this, and you can easily tell that there will be no output, because there is no name globally. The solution to this problem is to bind this through bind.

Var obj = {name: 'Zhang San', times: [1, 2, 3], print: function () {/ / this points to obj this.times.forEach (function (n) {console.log (this.name);} .bind (this) / / bind to this while traversing the array);}}; obj.print (); / / Zhang San * 3

In addition, we can also use the method of retaining this. You can refer to the article "complicated and confusing this keywords".

Var obj = {name: 'Zhang San', times: [1,2,3], print: function () {var me=this; / / keep this this.times.forEach (function (n) {console.log (me.name);});}}; obj.print (); Zhang San * 3

3. Use the call method.

Using the bind method, you can rewrite the use of some JavaScript native methods, taking the slice method of an array as an example

[1,2,3] .slice (0,1); / / starting from bit 0, intercept 1 bit and return an array / / [1] / / equivalent to Array.prototype.slice.call ([1,2,3], 0,1); / / [1]

In the above code, the slice method of the array splits another array according to the specified position and length from [1, 2, 3]. The essence of doing this is to call the Array.prototype.slice method on [1, 2, 3], so you can express the process with the call method and get the same result.

The call method is essentially a call to the Function.prototype.call method, so the above expression can be overwritten with the bind method.

Var slice = Function.prototype.call.bind (Array.prototype.slice); slice ([1,2,3], 0,1) / / [1]

As you can see, using the bind method, [1,2,3] .slice (0,1) is changed into the form of slice ([1,2,3], 0,1). This form of change can also be used in other array methods.

Var push = Function.prototype.call.bind (Array.prototype.push); var pop = Function.prototype.call.bind (Array.prototype.pop); var a = [1,2,3]; push (a, 4) / add an element 4a / / [1,2,3,4] pop (a) / delete the last element of the array a / / [1,2,3] at the end of the array

If you go a step further, binding the Function.prototype.call method to the Function.prototype.bind object means that the calling form of bind can also be rewritten.

Function f () {console.log (this.v);} var o = {v: 123}; var bind = Function.prototype.call.bind (Function.prototype.bind); bind (f, o) () / / 123

The above code indicates that after binding the Function.prototype.call method to Function.prototype.bind, the use of the bind method has changed from f.bind (o) to bind (f, o).

The above is all the content of the article "how to fix the this binding method call apply bind". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow 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.

Share To

Development

Wechat

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

12
Report