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.
Related
I read the piece of code in a book,
Function.prototype.before = function(beforefn){
var _self = this;
return function(){
beforefn.apply(this,arguments);
return _self.apply(this,arguments);
}
}
when execute
beforefn.apply(this,arguments);andreturn _self.apply(this,arguments);,I think even without fix 'this' it will get the same result.
function test(){
return function(){
alert(this.foo);
}
}
var o1 = {
foo:"foo",
test:test(),
}
o1.test(); //alert foo
So what is the purpose to fix this of the author?
P.S This is the first time ask question in StackOverflow,forgive my bad English.Thanks
Thanks for noticing my question! I would rewrite like this:
Function.prototype.before = function(beforefn){
var _self = this;
return function(){
beforefn(arguments);
return arguments.callee;
}
}
.apply(this, …) doesn't fix the thisArg - in contrast, it even makes it dynamic, using the current dynamic this from the returned function. Have a look at how well it works:
function test(){
alert(this.foo);
}
var o1 = {
foo: "bar",
test: test.before(function() { console.log(this); })
};
o1.test(); // logs o1, alerts "bar"
o1.test.call({}); // logs the empty object, alerts undefined
You'd only fix the this argument of _self if you didn't pass the current this, as in
Function.prototype.before = function(beforefn){
var fn = this;
return function() {
beforefn.apply(null, arguments);
return fn.apply(null, arguments);
}
}
where o1.test() would not work any more. Of course, apply is still necessary to pass a variable amount of arguments to the function.
Is it possible, while creating an instance of an object, to check during the instantiation itself the type of the parameter passed to the constructor, and set one of the object's variable accordingly?
This is what I'm trying to do:
function Test(num1) {
this.num1 = num1;
this.isValidNumber = (function() {
console.log(this.num1); // logs "undefined" upon instantiation
if (isNaN(this.num1)) {
return false;
} else {
return true;
}
}());
}
var testObj = new Test(5);
I want isValidNumber's value to be true or false according to the parameter passed to the constructor.
Your IIFE (Immediately-Invoked Function Expression) creates a new context, which means this doesn't point to your constructor anymore but to the Window object (unless you're using strict mode which would make it undefined). One possible solution is to execute this function with the right context:
this.isValidNumber = function() {
if (isNaN(this.num1)) {
return false;
} else {
return true;
}
}.call(this);
The much simpler solution is obviously:
function Test(num1) {
this.num1 = num1;
this.isValidNumber = !isNaN(this.num1);
}
First of all, the code could (and probably should) be rewritten the following way:
function Test(num1) {
this.num1 = num1;
console.log(this.num1);
this.isValidNumber = !isNaN(this.num1);
}
As for the reason why your code is not working as expected – your self invoking function has its own this parameter which is unrelated to the this parameter within your constructor.
In this case the this parameter of your self invoking function references the global object. (In strict mode it would've been undefined)
If you really need to reference the this parameter of a containing function then there are several ways to achieve this, the simplest of which being:
function Test(num1) {
this.num1 = num1;
var self = this;
this.isValidNumber = (function() {
console.log(self.num1);
return !isNaN(self.num1));
}());
}
In your particular case you don't even need to capture it, and this would also achieve the same effect:
function Test(num1) {
this.num1 = num1;
this.isValidNumber = (function() {
console.log(num1);
return !isNaN(num1));
}());
}
But again, the self invoking function is simply not required here.
This in the inner function no longer references the parent object. A common way of storing the object reference is to create a 'self' variable and assign this to it when it's in the correct scope
function Test(num1) {
var self = this;
this.num1 = num1;
this.isValidNumber = (function() {
console.log(self.num1);
if (isNaN(self.num1)) {
return false;
} else {
return true;
}
}());
}
var testObj = new Test(5);
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 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.
I have the following piece of code:
function initValidation()
{
// irrelevant code here
function validate(_block){
// code here
}
}
Is there any way I can call the validate() function outside the initValidation() function? I've tried calling validate() but I think it's only visible inside the parent function.
function initValidation()
{
// irrelevant code here
function validate(_block){
console.log( "test", _block );
}
initValidation.validate = validate;
}
initValidation();
initValidation.validate( "hello" );
//test hello
Hope that you are looking for something like this
function initValidation()
{
// irrelevant code here
this.validate = function(_block){
// code here
}
}
var fCall = new initValidation()
fCall.validate(param);
This will work.
Hope this addresses your problem.
You can call validate from within initValidation. Like this.
function initValidation()
{
// irrelevant code here
function validate(_block){
// code here
}
return validate(someVar);
}
validate is not visible to anything outside of initValidation because of its scope.
Edit: Here's my suggestion of a solution.
(function() {
function validate(_block){
// code here
}
function initValidation()
{
// irrelevant code here
return validate(someVar);
}
function otherFunctions() {
// ...
}
// initValidation = function
}());
// initValidation = undefined
All of your functions will be hidden to anything outside the function wrapper but can all see each other.
This invocation will return function statement, which is function validate.
So you can invoke directly after the first invocation.
function initValidation() {
// irrelevant code here
return function validate(_block) {
// code here
}
}
initValidation()();
I know this is an old post but if you wish to create a set of instances that you wish to work with that reuse the code you could do something like this:
"use strict";
// this is derived from several posts here on SO and ultimately John Resig
function makeClassStrict() {
var isInternal, instance;
var constructor = function(args) {
if (this instanceof constructor) {
if (typeof this.init == "function") {
this.init.apply(this, isInternal ? args : arguments);
}
} else {
isInternal = true;
instance = new constructor(arguments);
isInternal = false;
return instance;
}
};
return constructor;
}
var MyClass = makeClassStrict();// create "class"
MyClass.prototype.init = function(employeeName, isWorking) {
var defaultName = 'notbob';
this.name = employeeName ? employeeName : defaultName;
this.working = !!isWorking;
this.internalValidate = function() {
return {
"check": this.working,
"who": this.name
};
};
};
MyClass.prototype.getName = function() {
return this.name
};
MyClass.prototype.protoValidate = function() {
return {
"check": this.working,
"who": this.name
};
};
var instanceBob = MyClass("Bob", true);// create instance
var instanceFred = MyClass("Fred", false);// create instance
var mything = instanceFred.internalValidate();// call instance function
console.log(mything.check + ":" + mything.who);
var myBobthing = instanceBob.protoValidate();
console.log(myBobthing.check + ":" + myBobthing.who);
I know this thread's been here for quite some time but I thought I'd also leave my 0.02$ on how to call inner functions from outside their scope (might benefit somebody).
Note that in any place, a better design decision should be taken into consideration rather than some hackish workaround which will bite you back later.
How about using function expressions instead of function statements and making use of the global scope.
var innerFn;
function outerFn() {
innerFn = function(number) {
return number ** 2;
}
}
outerFn();
console.log(innerFn(5));
// if there's more complex code around and you could write this defensively
if (typeof innerFn !== 'undefined') {
console.log(`we are squaring the number 5 and the result is: ${innerFn(5)}`);
} else {
console.log('function is undefined');
}
Or, you can make use of closures:
function outer() {
// initialize some parameters, do a bunch of stuff
let x = 5, y = 10;
function inner() {
// keeps references alive to all arguments and parameters in all scopes it references
return `The arithmetic mean of the 2 numbers is: ${(x + y) / 2}`;
}
return inner;
}
innerFn = outer(); // get a reference to the inner function which you can call from outside
console.log(innerFn());
Create a variable outside the parent function, then in the parent function store your required function in the variable.
Var Store;
Function blah() {
Function needed() {
#
}
Store = needed;
}
As a minor variation of Esailija's answer, I did this:
function createTree(somearg) {
function validate(_block) {
console.log( "test", _block );
}
if (somearg==="validate") { return validate; } // for addNodes
// normal invocation code here
validate(somearg);
}
function addNodes() {
const validate = createTree("validate");
//...
validate( "hello" );
}
createTree("create");
addNodes();
//validate("illegal");
so validate() is now perfectly shared between createTree() and addNodes(), and perfectly invisible to the outside world.
Should work.
function initValudation() {
validate();
function validate() {
}
}
Function definition:
function initValidation() {
// code here
function validate(_block){
// code here
console.log(_block);
}
return validate;
}
Call it as below:
initValidation()("hello");
function initValidation()
{
function validate(_block){
console.log(_block)
// code here
}
// you have to call nested function
validate("Its Work")
}
// call initValidation function
initValidation()