A, call ()
Call () makes an indirect call to a function by specifying a pointer to this, and can pass in arguments to the function call
Here’s an example:
var foo = {
value: 1
};
function bar() { console.log(this.value) } bar.call(foo); / / 1Copy the code
First we need to know what call() does here:
- Specify that this points to foo
- Execute bar function
We can simulate these two effects:
var foo = {
value: 1,
bar: function() { console.log(this.value) } }; foo.bar(); / / 1Copy the code
You can see that setting bar to foo implements pointing this to foo. But doing so adds an attribute to foo for no reason, so we also need to delete it by delete. Therefore, the main implementation ideas are as follows:
// 1. Set the function to the object property foo.fn = bar // 2. Execute the function foo.fn() // 3. Delete the function from the object: delete foo.fnCopy the code
According to this idea to implement a simple version of:
Function.prototype.call2 = function(context) {// First get the function that called the call. This can get context.fn = this; context.fn(); delete context.fn; }Copy the code
Call (); call (); call (); call (); call ();
Function.prototype.call2 = function(context) { context.fn = this; var args = []; // Take the second starting argument and put it in the arrayfor(var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + '] '); Arguments [1], arguments[2], arguments[3]] // Args automatically calls array.toString ()eval('context.fn(' + args +') ');
delete context.fn;
}
Copy the code
Now that the core of the call() method has been implemented, we need to improve the call() function:
- The first argument can be passed null to indicate pointing to
window
- Functions can have return values
Complete implementation
Function.prototype.call2 = function(context) {
var context = context || window;
context.fn = this;
var args = [];
for(var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + '] ');
}
var result = eval('context.fn(' + args + ') ');
delete context.fn
return result;
}
Copy the code
Var value = 2; var obj = { value: 1 }function bar(name, age) {
console.log(this.value);
return {
value: this.value,
name: name,
age: age
}
}
bar.call2(null); // 2
console.log(bar.call2(obj, 'kevin', 18));
// 1
// Object {
// value: 1,
// name: 'kevin',
// age: 18
// }
Copy the code
Second, the apply ()
The implementation of Apply is similar to that of Call, except that the second argument to apply is passed in an array of parameters
Function.prototype.apply = function (context, arr) {
var context = Object(context) || window;
context.fn = this;
var result;
if(! arr) { result = context.fn(); }else {
var args = [];
for (var i = 0, len = arr.length; i < len; i++) {
args.push('arr[' + i + '] ');
}
result = eval('context.fn(' + args + ') ')
}
delete context.fn
return result;
}
Copy the code
At the end
Series of articles:
- JavaScript is new from the past — prototypes and prototype chains
- JavaScript is old and new — execution environment and scope
- JavaScript is old and new — scoped chains and closures
- JavaScript: 4 ways to call a function
- JavaScript revisits the past — the implementation of call() and apply()