Summary of the usage of call and apply in js
- 2020-03-30 01:09:42
- OfStack
The day before yesterday, I went to the interview and a gg asked me some js knowledge. There was a question about the usage of call and apply. Although I used the call method 365 days ago, I still failed to answer it
Call and apply, both of which bind the function to run on another object
Format and parameter definition of both:
Call (thisArg [, arg1, arg2...]); // argument list, arg1, arg2...
Apply (thisArg [, argArray]); // parameter array, argArray
The this pointer inside the above two functions is assigned to thisArg, which enables the function to be run as a method of another object
1. Simple usage of "call"
First, let's look at a simple example (call) :
<!doctype html>
<html>
<head>
<title> call-apply </title>
</head>
<body>
<input type="text" id="idTxt" value="input text">
<script type="text/javascript">
var value = "global var";
function mFunc()
{
this.value = "member var";
}
function gFunc()
{
alert(this.value);
}
window.gFunc(); // show gFunc, global var
gFunc.call(window); // show gFunc, global var
gFunc.call(new mFunc()); // show mFunc, member var
gFunc.call(document.getElementById('idTxt')); // show element, input text
</script>
<script language="javascript">
var func = new function()
{
this.a = "func";
}
var func2 = function(x)
{
var a = "func2";
alert(this.a);
alert(x);
}
func2.call(func, "func2"); // show func and func2
</script>
</body>
</html>
Then, the results are as follows:
Global varGlobal var
Member var
Input text
func
func2
Test environment: Google Chrome 10.0.648.45
Finally, analyze the results
1. The global object window calls the function gFunc, this points to the window object, so the this.value is global var
2. Function gFunc calls the call method, this by default refers to the first parameter window object, so this.value is also global var
3. Function gFunc calls the call method. By default, this refers to the first parameter new mFunc(), which is the object of mFunc
4. Function gFunc calls the call method. By default, this refers to the input text control with the first parameter, that is, the control with id= 'idTxt'
5. Function func2 calls the call method, this by default refers to the first parameter func function object, so this.value is this.a, namely func
6. Function func2 calls the call method, and the second parameter belongs to the function object func2, so alert(x) is the second parameter func2
Ii. Usage and improvement of call inheritance
Js USES call to simulate inheritance
Test code:
<!doctype html>
<html>
<head>
<title> call - apply for inherit </title>
</head>
<body>
<script type="text/javascript">
function baseA() // base Class A
{
this.member = "baseA member";
this.showSelfA = function()
{
window.alert(this.member);
}
}
function baseB() // base Class B
{
this.member = "baseB member";
this.showSelfB = function()
{
window.alert(this.member);
}
}
function extendAB() // Inherit Class from A and B
{
baseA.call(this); // call for A
baseB.call(this); // call for B
}
window.onload = function()
{
var extend = new extendAB();
extend.showSelfA(); // show A
extend.showSelfB(); // show B
}
</script>
</body>
</html>
The operation results are as follows:
BaseB member
BaseB member
Test environment: Google Chrome 10.0.648.45
Result analysis:
The expected result should be output baseA member and baseB member, but the actual output is baseB member and baseB member
(has been tested in IE9, 8, 6, Maxthon, Chrome, FF, Opera, Safari, 360 and other browsers, the results are the latter: baseB member)
At this point, the machine is not wrong, which requires further analysis
It might be easy to think of this as causing this, which both points to baseB objects, but is that true?
To get to the heart of the matter, we used chrome's debugging tools to break down breakpoints and debug.
< img Alt = "" border = 0 SRC =" / / img.jbzj.com/file_images/article/201312/20131228100214.png ">When calling the extend. ShowSelfA (); , this point to extendAB (not pointing to baseB object twice as we speculated)
The real reason is that the member variable of extendAB object is in baseb. call(this); When instantiated, it is overwritten by the member of baseB, that is, the member of extendAB is assigned to baseB member by baseA member
Of course, we can also modify the above baseA code to verify the correctness of our debugging analysis:
function baseA() // base Class A
{
this.memberA = "baseA member"; //Change member to memberA to distinguish members in baseB
this.showSelfA = function()
{
window.alert(this.memberA); //Display memberA
}
}
Run chrome and other browsers again and the results are as follows:
BaseA member
BaseB member
The results were the same as we had expected, and the chrome debugging information also confirmed our correctness:
< img Alt = "" border = 0 SRC =" / / img.jbzj.com/file_images/article/201312/20131228100420.png ">
Inheritance and improvement (prototype)
The above simulation inheritance method, careful analysis is not the best.
Because every time a member method is defined in a function (class), it results in a copy of the instance, you can improve on it with the prototype prototype
Examples of improvements are as follows:
<!doctype html>
<html>
<head>
<title> call - apply for prototype </title>
</head>
<body>
<script type="text/javascript">
var Class = {
create: function() // create Function
{
return function()
{
this.initialize.apply(this, arguments);
}
}
};
var Person = Class.create(); // Create Class Person
Person.prototype = { // prototype initialize
initialize: function(obj1, obj2)
{
this.obj1 = obj1;
this.obj2 = obj2;
},
showSelf: function()
{
alert("obj: " + this.obj1 + " and " + this.obj2);
}
}
// instance Class
var person = new Person("man", "women"); // two params
person.showSelf(); // show person
</script>
</body>
</html>
The operation results are as follows:
Obj: man and women