I am reading Secrets of the JavaScript Ninja by John Resig and Bear Bibeault, currently up to Chapter 5 on closures. I think have the general gist of closures and how JavaScript operates with function scoping rather than the block scoping of C++/Java of which I am familiar. One thing I am having trouble understanding fully though is sometimes in the code there seem to be more function declarations than I can figure out purposes for. For instance, in Section 5.5.1 He covers self-memoizing functions, which is basically a function that remembers computed values and stores them in a cache for subsequent calls with the same input. He gives the following code:
Function.prototype.memoized = function (key) { // #1
this._values = this._values || {};
xyz = this._values;
return this._values[key] !== undefined ?
this._values[key] :
this._values[key] = this.apply(this, arguments);
};
Function.prototype.memoize = function () { // #2
var fn = this;
return function() { // #2.1
return fn.memoized.apply(fn, arguments);
};
};
var isPrime = (function (num) {
var prime = num !== 1;
for (var i = 2; i < num; i++) {
if (num % i === 0) {
prime = false;
break;
}
}
return prime;
}).memoize();
I understand most of this code. However what I am having trouble understanding is why at the second memoization function couldn't simply be:
Function.prototype.memoize = function () {
return this.memoized.apply(fn, arguments);
};
Can anyone give me a good explanation of what is happening in his code above and how it is different than what I have written here?
There is quite a big difference:
return function() {
return fn.memoized.apply(fn, arguments);
};
returns a function that you can call later. memoized is only called when the function is called.
return this.memoized.apply(fn, arguments);
calls the function memoized and returns its return value.
Related
I came across David Walsh's once function here:
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
My question is what is the tracker variable here? Doesn't result become null each time canOnlyFireOnce() is fired? What is the purpose of setting the fn to null?
The fn is the tracker variable here. The fn variable holds the anonymous function. After calling the canOnlyFireOnce function once, the fn variable gets a new value "null". Now the fn(the anonymous function) is no longer available for execution, that's why you won't see the "Fired!" message again.
fn is the variable which tracks whether it's been called. You could write it this way with a more explicit extra variable:
function once(fn, context) {
var result;
var called = false;
return function() {
if (!called) {
result = fn.apply(context || this, arguments);
called = true;
}
return result;
};
}
I guess that setting fn = null can free some memory, so he wants to do that after the call too. So why not also use that to remember the call.
In Javascript, there is a point that "arguments leaking" can affect optimization. For example:
function leakingArguments() {
var a = arguments;
return function() {
return a;
};
}
Arguments leaking which is a function arguments be used outside that function. In this case, compiler may not optimize that code.
So I built a jsperf, their performance is equalit. It seems passing the arguments out of function wouldn't affect the results execution time.
let MAX_LENGTH = 1000
let arr = Array.from({length: MAX_LENGTH}, (v, i) => i)
let withoutArguments = function() {
let cloneArgs = Array.apply(null, arguments)
return function() {
cloneArgs[0] = 1
return
}
}
let argumentsFn = function() {
let args = arguments
let cloneArgs = Array.apply(null, arguments)
return function() {
args[0] = 1
return
}
}
withoutArguments(...arr)
argumentsFn(...arr)
Is there a real existing about "arguments leaking"?
I'd like to question your performance testcase because:
(1) You only call these functions once, it is unlikely that the engine JIT compiles them, and that's the place were optimizations really matter.
(2) You never call the function returned, so you never actually modify arguments.
(3) The main problem with arguments is that the values have to be reflected live into the closured variables, so this testcase would be much better:
function urgh(a) {
const leak = arguments;
return function() {
leak.a = 1;
console.log(a);
};
}
I have this spec from Jasmine.js which tests a once function. I'm not sure how to implement such a function though.
/* Functions that decorate other functions. These functions return a version of the function
with some changed behavior. */
// Given a function, return a new function will only run once, no matter how many times it's called
describe("once", function() {
it("should only increment num one time", function() {
var num = 0;
var increment = once(function() {
num++;
});
increment();
increment();
expect(num).toEqual(1);
});
});
I don't quite understand what should I do here. I know I should make a function once(myFunction) {} but other than that, I am stuck. I figure out this has something to do with closures, still can't my head around it.
If you prefer not to use UnderscoreJS, you can implement a simpler "once" function yourself like this:
var once = function (func) {
var result;
return function () {
if (func) {
result = func.apply(this, arguments);
func = null;
}
return result;
}
};
When you pass your function as the argument to this once function (as the parameter as 'func'), it returns a function that can only be called once.
It accomplishes this feat, in short, by creating a results variable and assigning that variable the results of calling your function with its supplied arguments--but only the first time it is run. Otherwise, when the function is invoked subsequent times, it will never enter your if statement (because the func variable was set to null in the first invocation) and the value referenced by the results variable (set during the first invocation and accessed via closure) will be returned.
Copied from the UnderscoreJS source:
_.once = function(func) {
var ran = false, memo;
return function() {
if (ran) return memo;
ran = true;
memo = func.apply(this, arguments);
func = null;
return memo;
};
};
http://underscorejs.org/docs/underscore.html
Very, very minimal
const once = fn => (...args) => {
if (!fn) return;
fn(...args);
fn = null;
};
(Old school version)
function once(fn) {
return function() {
if (!fn) return;
fn.apply(null, arguments);
fn = null;
}
}
I want to build a javascript function that maintains state. Here's a pattern that I've come up with, but something in the back of my mind tells me this is an anti-pattern.
function f() {
var state = 1;
f = function() {
return state++;
};
return f();
};
Is there anything wrong with this? If so, what's a better approach?
Well it's a matter of opinion what the best way is, but (although I know it works) I'm a little uncomfortable with having the function overwrite itself. A similar pattern that doesn't do that but still uses practically the same closure idea is this:
var f = function() {
var state = 1;
return function() {
return state++;
};
}();
Or here is another way:
function f() {
return f.state++;
}
f.state = 1;
Of course with the f.state method the advantage and disadvantage (depending on your needs) is that the .state property can be read and modified by other code.
Normally, you set a closure scope and return a function that has access to that scope. Every time that function is now called, the state will remain as long as that function exists. Example:
var statefulFunction = function() {
// set up closure scope
var state = 1;
// return function with access to the closure scope
return function() {
return state++;
};
}(); // immediately execute to return function with access to closure scope
var first = statefulFunction(); // first === 1
var second = statefulFunction(); // second === 2
Another pattern is to create a closure scope and return an object with methods that have access to that closure scope. Example:
var myStatefulObj = function() {
// set up closure scope
var state = 1;
// return object with methods to manipulate closure scope
return {
incr: function() {
state++;
},
decr: function() {
state--;
},
get: function() {
return state;
}
};
}();
myStatefulObj.incr();
var currState = myStatefulObj.get(); // currState === 2
myStatefulObj.decr();
currState = myStatefulObj.get(); // currState === 1
A better way to achieve this might be to use an Immediately-Invoked Function Expression (IIFE) to encapsulate your state.
var f = (function () {
var state = 1;
return function() {
return state++;
};
}());
console.log(f()); // 1
console.log(f()); // 2
What is the best way to deal with the following situation in JavaScript.
I have three methods (m1, m2, m3) and the last one (m3) depends from the results of the others two (m1, m2).
In this way it works, but I am curious to know if there is a better way to write the code in this situation, especially for future developers that will read the code.
var O = function () {
this.p = 0;
}
O.prototype.makesomething = function () {
var that = this;
that.m1();
that.m2();
that.m3();
}
O.prototype.m1 = function () {O.p++}; // it changes the value O.p
O.prototype.m2 = function () {O.p++}; // it changes the value O.p
O.prototype.m3 = function () {return O.p}; // m3 depends by m1, m2 because it needs to get the update value of O.p
First, I don't know for sure, but putting this.p = 0 inside O does not make sense in combination with O.p. You probably mean this.p inside m3, when referring to the instance.
Anyway, if you are looking for readability, you could make some simple but idiomatic functions like this: http://jsfiddle.net/ZvprZ/1/.
var O = function () {
this.p = 0;
}
O.prototype.makesomething = function () {
var that = this;
var result = when( that.m1(), that.m2() )
.then( that.m3() );
return result;
}
O.prototype.m1 = function () {this.p++};
O.prototype.m2 = function () {this.p++};
O.prototype.m3 = function () {return this.p};
The when/then can be rather straight-forward since it does not do anything than making it more readable:
(function(window) {
var when, then, o;
when = function() {
return o; // just return the object so that you can chain with .then,
// the functions have been executed already before executing
// .when
};
then = function(a) {
return a; // return the result of the first function, which has been
// executed already (the result is passed)
};
o = { when: when,
then: then };
window.when = when; // expose
window.then = then;
})(window);