I've mocked up some code here
var common = common || {};
(function(NAMESPACE) {
NAMESPACE = {
isIE: function() {
return true;
}
};
main();
})(common);
function main() {
console.log(common.isIE());
return 'Hello, World!';
}
I would like to understand a couple of things,
1) Why isn't this working, I guess it has something to do with how scoping is "decided" and IIFE, but not entirely sure.
2) How to make this code work?
common which passed as argument named NAMESPACE needs to be extended instead of assigning new value.
So Object.assign can help here.
var common = common|| {};
(function(NAMESPACE) {
Object.assign(NAMESPACE,{
isIE: function() {
return true;
}
});
main();
})(common);
function main() {
console.log(common.isIE());
return 'Hello, World!';
}
When you are passing an object as an argument in JS, you should remember that you are passing "by-value" the reference of it.
Creating a new object in literal notation and assigning it to the argument like this,
NAMESPACE = {
isIE: function() {
return true;
}
};
can only point the argument to the new object - not to the object of the reference you passed the argument by.
If you had said,
NAMESPACE.isIE = function() {}
it would work.
Related
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 want to be able to assign a property to a function inside the function itself. I do not want to assign it to the object of invocation. So I want the equivalent of doing this:
var test = function() {
return true;
};
test.a = 'property on a function';
alert(test.a);
Instead of this, where the property is assigned to a global object:
var testAgain = function() {
this.a = "this property won't be assigned to the function";
return true;
};
testAgain();
alert(window.a);
Edit: To clarify, I'm wondering if there's something like this:
var test = function() {
function.a = 'property on a function';
};
alert(test.a); // returns 'property on a function'
Without knowing that the function is called test or having to execute it.
I know of course this isn't valid syntax
[is there a way to set a property on a function] without knowing that the function is called test or having to execute it.
Emphasis mine.
You can set a property on a function without knowing what its global variable name is necessarily going to be, however you do have to have a reference to the function in one way or another.
The module pattern is as close of a fit as I can think of:
window.test = (function () {
//the function could be named anything...
function testFn() {
...code here...
}
//...so long as the same name is used here
testFn.foo = 'bar';
return testFn;
}());
window.test.foo; //'bar'
The outer closure prevents testFn from being accessed anywhere globally, so all other references will have to use window.test.
This part of the answer is associated with the prior version of the question.
The simplest way of doing this is to use a named function:
var test = function testFn() {
testFn.foo = 'bar';
return true;
};
test.foo; //undefined
test();
test.foo; //'bar'
A better way of doing this is to use the module pattern so that you don't accidentally create issues with global leakage:
var test = (function () {
function ret() {
ret.foo = 'bar';
return true;
}
return ret;
}());
test.foo; //undefined
test();
test.foo; //'bar'
var testAgain = function() {
arguments.callee.a = "this property won't be assigned to the function";
return true;
};
testAgain();
alert(testAgain.a);
You can do this by simple using the name to assign the property like this:
var test = function () {
test.a = 'a';
return true;
};
When test is invoked, the property will be set.
Demo
You could use arguments.callee, as su- said, but that's considered really bad practice. Also, it won't work in strict mode.
var test = function() {
test.a = 'a';
};
Or you can use prototypes, read more here.
Consider this piece of code
var crazy = function() {
console.log(this);
console.log(this.isCrazy); // wrong.
}
crazy.isCrazy = 'totally';
crazy();
// ouput =>
// DOMWindow
// undefined
From inside crazy() 'this' refers to the window, which I guess makes sense because normally you'd want this to refer to the object the function is attached to, but how can I get the function to refer to itself, and access a property set on itself?
Answer:
Don't use arguments.callee, just use a named function.
"Note: You should avoid using arguments.callee() and just give every function (expression) a name." via MDN article on arguments.callee
I think you are asking for arguments.callee, but it's deprecated now.
https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments/callee
var crazy = function() {
console.log(this);
console.log(arguments.callee.isCrazy); // right.
}
crazy.isCrazy = 'totally';
crazy();
// ouput =>
// DOMWindow
// totally
As rfw said, this is the most straight forward way to go if the function has one single name:
var crazy = function() {
console.log(crazy);
console.log(crazy.isCrazy);
};
crazy.isCrazy = 'totally';
crazy();
In case it may have different names, or you wanted to pass it around, it must be wrapped in a closure:
var crazy = (function(){
var that = function() {
console.log(that);
console.log(that.isCrazy);
};
return that;
})();
crazy.isCrazy = 'totally';
crazy();
Bind the function to itself (taking a hint from answers by #ArunPJohny and #BudgieInWA):
crazy = crazy.bind(crazy);
This will give you access from the function to its properties via this.
> crazy()
function () {
console.log(this);
console.log(this.isCrazy); // works now
}
This seems like a better solution than the accepted answer, which uses the callee feature which is deprecated and doesn't work in strict mode.
You could also now have the function call itself recursively with this() were you so inclined.
We will call this self-thisifying. Write a little utility function:
function selfthisify(fn) { return fn.bind(fn); }
crazy = selfthisify(crazy);
crazy();
Or, if you prefer more "semantic" names, you could call it accessOwnProps.
If you're a syntactic sugar type of person, you could add a selfthisify property to the Function prototype:
Object.defineProperty(Function.prototype, 'selfthisify', {
get: function() { return this.bind(this); }
});
Now you can say
crazy.selfthisify();
You have to give it its own name, so:
var crazy = function() {
console.log(crazy);
console.log(crazy.isCrazy);
}
crazy.isCrazy = 'totally';
crazy();
The variable this is only applicable in the scope of an object, for instance, if you invoked your version of the crazy function with crazy.call(crazy), it will call the function in the context of the function crazy and all would be well.
This has to deal with the scope of the function crazy. If can pass any scope to a function using the function call().
Instead of
crazy();
Use
crazy.call(crazy);
For details refer
http://odetocode.com/blogs/scott/archive/2007/07/05/function-apply-and-function-call-in-javascript.aspxhttps://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/Callhttp://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx
You can use the call method
var crazy = function() {
console.log(this);
console.log(this.isCrazy);
}
crazy.isCrazy = 'totally';
crazy.call(crazy);
// calls crazy using crazy as the target, instead of window:
// functionToCall.call(objectToUseForThis);
Though if your function only ever has one name, you can do this:
var crazy = function() {
console.log(crazy);
console.log(crazy.isCrazy);
}
crazy.isCrazy = 'totally';
crazy();
Easiest way to make the function itself available in its body is to do
var crazy = function crazy2() { crazy2(); }, it's okay for crazy and crazy2 to have the same name since the first occurrence is the name in the outer scope and the second is the name in the function body.
Or simply do function crazy() { crazy(); } which will define crazy in both scopes.
how can I get the function to refer to
itself?
The idea of 'itself' does not exist with functions. What you need is an object and not just a function. An object has knowledge of itself available through the keyword 'this'. Within a function, 'this' points to the global object - in this case the window object. But if you use your function as a constructor function to create an object (using the new operator) then the object's 'this' pointer will point to the object itself.
i.e this points to the object if you write:
var anObject = new crazy();
So you can re-write your code as follows:
var crazy = function() {
this.printMe = function(){
console.log(this);
console.log(this.isCrazy);
}
}
var anObject = new crazy(); //create an object
anObject.isCrazy = 'totally'; //add a new property to the object
anObject.printMe(); //now print
In case you wish to add the property before the object is created, then you have to add the property to the function's prototype as follows:
var crazy = function() {
console.log(this);
console.log(this.isCrazy);
}
crazy.prototype.isCrazy = 'totally'; //add the property to the function's prototype
var anObject = new crazy(); //invoke the constructor
See more on my blog for a detailed explanation of these concepts with code-samples.
Are you actually trying to create an object 'class'?
function crazy(crazyState) {
this.isCrazy = crazyState;
console.log(this);
console.log(this.isCrazy);
}
crazy.prototype.alertMe = function() { alert('I am '+ this.isCrazy +' crazy.'); }
var crazyObj = new crazy('totally');
crazyObj.alertMe();
crazyObj.isCrazy = 'not';
crazyObj.alertMe();
Funny that you should ask, mate. I just went through this same issue for a different purpose. The quick version of the final code is:
$a = function() {};
$ = function() {
if (!(this instanceof $)) {
return new $();
}
this.name = "levi";
return this;
};
//helper function
var log = function(message) {
document.write((message ? message : '') + "<br/>");
};
log("$().name == window.name: " + ($().name == window.name)); //false
log("$().name: " + $().name); //levi
log("window.name: " + window.name); //result
log();
log("$a instanceof $: " + ($a instanceof $)); //false
log("typeof $a: " + (typeof $a)); //function
log("typeof $: " + (typeof $)); //function
The critical piece:
if (!(this instanceof $)) {
return new $();
}
If this isn't pointing to an object of the right type, then it makes a new one, which will properly scope this. The rest of the code is just there for verification that it does indeed work as intended.
In order to make you code to work follow below
function crazy_object (crazy) {
this.isCrazy = crazy
}
var create_crazy = new crazy_object('hello') //creating object
console.log(create_crazy); //=> { isCrazy = 'hello' }
var crazy = function() {
console.log(this); //=> { isCrazy = 'totally' }
console.log(this.isCrazy); //=> 'totally'
}
create_crazy.isCrazy = 'totally'; //=> isCrazy = 'totally'
//below we pass the created object in function crazy.
//And doing that we can use the keywork `this` and refer to the object
crazy.call(create_crazy, null);
Using the call and apply method we can pass to a function a
property,and in that function we can use the property with the keyword this
For example:
function speak (message) {
console.log(`A person with name ${this.name} say ${message}`);
}
speak.call({ name: 'Roland' }, 'Javascript is awesome');
To use it with property:
function speak (message) {
console.log(`A person with name ${this.name} say ${message}`);
}
var name = 'Roland'
speak.call({ name }, 'Javascript is awesome');
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
I basically have an object, extended with a function through its prototype. Inside that function, another function exists, however when using this in this nested function, it does not seem to refer to the object, but the function.
For example,
var sampleObject = function() {
this.foo = 123;
}
sampleObject.prototype.getFoo = function() {
var nested = function() {
return this.foo;
}
return nested();
}
var test = new sampleObject();
window.alert(test.getFoo()); // undefined
The this.foo does not refer to the 123 value, but is undefined as this refers to the nested function, in which no foo exists. How can I access the 123 value from the nested function?
sampleObject.prototype.getFoo = function() {
var me = this;
var nested = function() {
return me.foo;
}
return nested;
}
By saving the value of this in a local variable, you make it explicitly part of the lexical context for that function and for all nested function scopes. Thus, on the call to "nested", that inner function will have its own scope (it's own this value), but it can still refer to the variable "me" in the enclosing scope.
In your example "this" refers to the window object because you didn't specify another context when you call the nested function and you get undefind because window.foo is undefined.
You can fix this in 3 ways.
1 - Use a variable to store the outside this - most used method
sampleObject.prototype.getFoo = function() {
var _this = this;
var nested = function() {
return _this.foo;
}
return nested();
}
2 - Use the bind method which bind the outer "this" to the inner one
sampleObject.prototype.getFoo = function() {
var nested = function() {
return this.foo;
}.bind(this);
return nested();
}
3 - Use the call method which can pass the context to the function
SampleObject.prototype.getFoo = function() {
var nested = function() {
return this.foo;
};
return nested.call(this);
}
The common work around for that is to use closure
sampleObject.prototype.getFoo = function() {
var _this = this;
var nested = function() {
return _this.foo;
}
return nested();
}
Some libraries add methods to automate this
Prototype adds Function.bind (http://prototypejs.org/doc/latest/language/Function/prototype/bind/)
Ext adds function.createDelegate (http://www.sencha.com/learn/Manual:Utilities:Function#createDelegate)
Javascript 1.8.5 adds function.bind (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind)
tl;dr
Use arrow functions. They are available since ECMAScript 6:
var sampleObject = function() {
this.foo = 123;
}
sampleObject.prototype.getFoo = function() {
var nested = () => { // Changed this line.
return this.foo;
}
return nested();
}
var test = new sampleObject();
window.alert(test.getFoo());
Explanation
This is one of the main advantages of arrow functions. Your case is described in the section: No binding of this. The refference states:
Until arrow functions, every new function defined its own this value [...]
An arrow function does not create its own this context, so this has the original meaning from the enclosing context.
Apart from declaring it to var _this = this, I also see codes doing var that = this or var self = this.
Knowing your variable's scope is important as it might raises unexpected result.
This is an old question, but I give another solution for the sake of completeness. Another approach involves function binding.
sampleObject.prototype.getFoo = function() {
var nested = function() {
return this.foo;
}
return nested.bind(this)();
}
An ES6 way of doing this would be to use an Arrow Function. Basically, when you use an arrow function, it does not create it's own "this" context. So, using "this" would then refer to the parent function's context. Here's how the code would look:
sampleObject.prototype.getFoo = function() {
const nested = () => {
return this.foo; //"this" refers to parent function's context
}
return nested;
}
This is a known wart on JavaScript. The usual pattern is to assign this to another variable (often self) in the outer function, then access self from the inner funtction. This works.
I'm wondering if any of yall have any insight as to how one could execute a function by reference in javascript.
http://mootools.net/shell/yL93N/1/
Any discussion would be cool.
-Chase
looking at your mooshell, the way i'd handle it in mootools is this:
http://mootools.net/shell/yL93N/10/
var proxyFunction = new Class({
message: "hello",
Binds: ['passByReference','sayit'],
passByReference: function(func) {
// console.log(this, this[func]);
if (this[func] && $type(this[func]) === "function")
this[func]();
},
sayit: function() {
alert(this.message);
},
killit: function() {
document.write('we\'re dead');
}
});
$('tryit').addEvent('change',function(e){
new proxyFunction().passByReference(this.get('value'));
});
// or have a permanent proxy instance if you call methods of the class often and need it to change things.
var proxy = new proxyFunction();
$('tryit').addEvent('change',function(e){
proxy.passByReference(this.get('value'));
});
the advantage of doing so is that all your proxied functions are behind a common object, don't pollute your window namespace as global variables and can share data that relates to the event.
Not exactly sure what you mean, but you can do this:
var func = window.alert;
var args = ["hello world"]
func.apply(window, args)
Globally-defined functions (and variables) are visible as members of the global window object.
Members of an object can be fetched by name using the square bracket notation: o['k'] is the same as o.k. So, for your example:
var function_name= $(this).val();
window[function_name]();
Like this?
function blah() {
...do stuff
}
myref = blah
myref()
The best way is to do:
func.call();
Function variables in JavaScript already are references. If you have a function:
var explode = function() { alert('boom!'); };
You can pass explode around as an argument, and it's only passing a handle to that function, not the entire function body.
For proof of this, try:
explode.id = 5;
var detonate = explode;
alert(detonate.id); // => 5
explode.id = 6;
alert(detonate.id); // => 6
functions are first class objects in Java Script. Effectively this means that you can treat it very much as if it were a variable, and pass it anywhere that you would expect a variable.
e.g.
var myFn = function() { alert('inside anonymous fn'); }
function callMyFn(paramFn)
{
paramFn();
}
callMyFn(myFn); //inside anonymous fn
function MyFnHolders(argFn)
{
this.argFn = argFn;
this.fieldFn = function() {
alert('inside fn field');
}
}
var myFnHolders = new MyFnHolders(myFn);
myFnHolders.argFn(); //'inside anonymous fn'
myFnHolders.fieldFn(); //'inside fn field'
//etc
so passing a function by ref can be done simply by assigning it to a variable and passing it around.
Here's one with a closure for your arguments...
function Runner(func, args) {
return function() { return func.apply(window, args); };
}
var ref = new Runner(window.alert, ["hello world"]);
ref();