I'm trying to understand exactly how this Once function by David Walsh works:
`
function once(fn, context) {
var result;
return function() {
if(fn) {
result = fn.apply(context || this, arguments);
fn = null;
}
return result;
};
}
// Usage
var canOnlyFireOnce = once(function() {
console.log('Fired!');
});
canOnlyFireOnce(); // "Fired!"
canOnlyFireOnce(); // nada
`
I understand it takes a function as a argument, and returns a function that calls the passed function only once.
But I'm trying to understand what each part is doing. Can anyone help explain? especially this part:
result = fn.apply(context || this, arguments);
Why the OR sign? what is "this" and how is it getting the arguments from fn? What purpose does 'context' serve?
I wrote a similar once() function for school that returns the result of the passed function, and stores the result to return it again if the function attempts to get called again. It took a lot of trial and error, and I'm just trying to get a firm grasp on all the component parts of how this works.
`
function add(x, y) {
return x y;
}
function once(fn) {
let timesRan = 0;
let result;
function doOnce() {
if (timesRan === 0) {
timesRan = 1;
result = fn.apply(this, arguments); //I don't understand how this gets the arguments from AddOnce
console.log(`did it once: ${result}`)
return result;
} else {
return result;
}
}
return doOnce;
}
var addOnce = once(add);
console.log(addOnce(1, 2)); // test first call, expected value: 3
console.log(addOnce(2, 5)); // test second call, expected value: 3
console.log(addOnce(8, 22)); // test third call, expected value: 3
`
CodePudding user response:
The concept behind this
in JavaScript is confusing, because when I write a function such as:
function getPersonName() {
return this.name
}
I expect that this
be defined as a some object with a name
attribute. Depending on the scope, I may have this be defined and no problems! But in order for a function such as the above to properly reference this
, we need to tell it what it should reference when we use that keyword.
For example, it allows us to do the following:
var canOnlyFireOnce = once(function() {
console.log(this.name)
}, {name: "John"});
canOnlyFireOnce() // prints John
canOnlyFireOnce() // nada
It may be helpful to understand the bind function's use cases in JavaScript to understand why having this (no pun intended) is useful.
CodePudding user response:
The meaning of the this
context in function.apply
is already explained in rb612
's answer.
For the question about arguments
, you need to know that
the
arguments
object is a local variable available within all non-arrow functions. You can refer to a function's arguments inside that function by using itsarguments
object.