this opreator for nested functions - javascript

Sorry if my question is silly one,I searched on google but I could't find anything useful.
Here I have module with 2 functions inside it and here is the code
var sample = (function(){
var _return = [];
_return.bar = function(){
alert("hello world");
};
_return.foo = function(){
function test(){
this.bar();
};
};
return _return;
})();
sample.foo();
And my questions:
How can I access to the bar function inside test function? I tried this.this.bar() or parent.this.bar() but none of them worked.
And how can I access it with this operator?

Usually (unless one has used bind to change the context of a function), the this context is bound to the object on which the function is being called, i.e., if you call foo.bar(), then inside bar, this === foo. In your case, since you are returning _return, you want to access the function bar which is defined on the same object, i.e. this.bar. However, since you will call test directly, this will be bound to the window object.
There are three main ways of working around this issue:
Save the context while you can
_return.foo = function(){
var self = this;
function test(){
self.bar();
};
};
Working demo: http://jsfiddle.net/jcovmspr/
Use bind
The other approach is using bind (ES5):
_return.foo = function(){
function test_(){
this.bar();
};
var test = test_.bind(this);
};
Use arrow syntax
The third approach is using arrow syntax for defining test but this is ES6 only and you will need a transpiler to support more common browsers:
_return.foo = function(){
var test = () => {
this.bar();
};
};

You can use a closure like below,
Note: I prefer using 'that' or 'me' rather than 'self' because self is a special keyword in JS.
_return.foo = function() {
var that = this;
function test(){
that.bar();
}
};
or you can use bind:
_return.foo = function() {
var test = (function () {
this.bar();
}).bind(this);
};

Just refer to _return instead of this:
var sample = (function(){
var _return = {
bar: function(){
alert("hello world");
},
foo: function(){
return function test(){
_return.bar();
};
}
};
return _return;
})();
sample.foo()();
(Also, I've used a proper object literal instead of creating properties on an array)

Related

JavaScript Function Hoisting in my Object

I have created an object and am attaching a bunch of functions to the object. I am concerned about how the ordering of the functions effects when I can call my functions. In my example below, I must define my functions first before I can use them. My problem with this is that I cannot call init() immediately until I have defined it. Init() will contain a bunch of other functions that it will need to call, which will have to be placed above init(). So in the end, init() will have to be the very last function defined in my object. I believe this is related to Hoisting.
My question is if there is a way for me to call a function before defining it? Is there some sort of way to create a 'placeholder' function like in C?
https://jsfiddle.net/13hdbysh/1/
(function() {
foo = window.foo || {};
//this will not error
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.helloWorld();
//this will error
foo.init();
foo.init = function() {
console.log('init()');
};
})();
What you're asking deals with how objects store member data. This can be seen in a weird light because of prototypal inheritance. Javascript by default will parse naked functions before they execute.
Example:
(function() {
init();
function init()
{
console.log("Init");
}
)};
This gets muddied when storing behavior as a member to an object. Because prototypal inheritances dynamic functionality you need to declare your members before accessing them. This is Javascript's main difference from traditional OOP languages.
You mentioned, "is there a way to create a 'placeholder' function like in C." You can, but not in the same way. You can assign it to a naked function and assign that to your object. Look in my example, the hello function.
Alternatively you can store the behavior on the prototype of your object and override it when necessary.
Example:
function hello()
{
console.log("Hello my name is "+this.name);
}
(function() {
var something = function(name) {
this.name = name;
};
something.prototype.initTwo = function() {
console.log("My Name is: "+this.name);
};
var thingOne = new something("Thing One");
thingOne.init = "SomeThing";
var thingTwo = new something("Thing Two");
thingTwo.init = function() {
console.log(this.name);
};
thingTwo.initTwo = function() {
console.log("SomethingTwo is Named: "+this.name);
};
thingTwo.hello = hello;
console.log(thingOne.init);
thingTwo.init();
thingOne.initTwo();
thingTwo.initTwo();
thingTwo.hello();
}) ();
Demo: Fiddle
Documentation on objects in javascript.
Try using similar IIFE pattern
(function() {
foo = window.foo || {};
//this will not error
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.helloWorld();
//this will error
// foo.init();
foo.init = (function _foo() {
console.log('init()');
this.init = _foo;
return this.init
}).call(foo);
foo.init()
})();
jsfiddle https://jsfiddle.net/13hdbysh/2/
I am not sure why would you wanna call it before it is defined but here is how to do it:
foo = window.foo || { init: function() { } };
How about declaring it as a local variable first.
(function() {
foo = window.foo || {};
//this will not error
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.helloWorld();
var initFunction = function() {
console.log('init()');
};
//this will no longer error
initFunction();
foo.init = initFunction;
})();
Init() will contain a bunch of other functions that it will need to call, which will have to be placed above init().
You are operating under a misapprehension.
A function must be defined before you call it, not before you define another function which will call it later.
Just define all your functions and then start calling them.
(function() {
foo = window.foo || {};
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.init = function() {
console.log('init()');
};
foo.init();
foo.helloWorld();
})();
As far as hoisting is concerned, function declarations (you only have function expressions) are hoisted, but they create locally scoped variables, not object properties. You would have to assign them to object properties before you could call them as such, and that assignment wouldn't be hoisted.
It's throwing an error because you're calling the method init() before it's declared.
This way will works
foo.init = function() {
console.log('init()');
};
foo.init();
Since foo is an object, you can put those functions into an object so that will be assigned to foo once window.foo is null
(function() {
foo = window.foo || {
helloWorld: function() {
console.log('helloWorld()');
},
init: function() {
console.log('init()');
}
};
//this will not error
foo.helloWorld();
foo.init()
})();

How to set var self = this; from outside the function?

I have a class-like function
var myapp = function() {
this.method = function() {
//Do something...
}
}
To reference myapp from within methods, the first line in the myapp function is
var self = this;
So a method in myapp can reference the "class" safely
this.anothermethod = function() {
self.method();
}
The full code:
var myapp = function() {
var self = this;
this.dosomething = function(Callback) {
Callback();
}
this.anothermethod = function() {
//Pass a callback ("self" is required here)...
this.dosomething(function() {
self.complete();
)};
}
this.complete = function() {
console.log('All done!');
}
}
My question is: can I assign var self = this; from outside the declaration of myapp? I don't want to set self every single time I write a "class".
Kind of like this:
var library = function() {
this.loadclass = function(Name) {
var tempclass = window[Name];
library[Name] = new tempclass();
library[Name].self = library[Name];
}
}
var myapp = new library();
myapp.loadclass('myapp');
myapp.myapp.dosomething();
It doesn't work as expected. self equals window for some reason.
I know it's a little abnormal programming, but can it be done?
Note about using self: I remember why I started using it. I wanted to reference the base class (this) from within callbacks inside methods. As soon as you try to use this within a function within a method, it then references the method, not the base class.
Unless you are detaching the methods from the object and calling them as plain functions, you don't need a self variable at all. The method can reach its object using the this keyword:
var myapp = function() {
this.method = function() {
//Do something...
}
this.anothermethod = function() {
this.method();
}
}
No, you can't really; not the way you're creating objects at least.
You can sort of do this, by enumerating all the functions on the object and binding them to the object itself. Something like this:
Object.keys(obj)
.filter(function(n) { return typeof obj[n] == "function" })
.forEach(function(n) { obj[n] = obj[n].bind(obj) })
This function will go over the public, enumerable properties of obj and make sure that any functions on it are bound to obj; i.e. this is now bound to obj.
A primer on this
When you call new, this within the constructor gets bound to the newly created object. If you do need a reference to this as it was bound at constructor time, you do need to keep away a reference to it.
Functions in JavaScript are bound to wherever it is called. Here's an example:
var foo = new function() {
this.bar = function() {
return 'bar'
}
this.baz = function() {
return this.bar()
}
}
console.log(foo.bar()) // bar
console.log(foo.baz()) // bar
var bar = function() {
return "window"
}
var baz = foo.baz
console.log(baz()) // window
When we call foo.baz() it'll look to foo for the implementation of bar, but when calling foo.baz through a "detached" reference, it'll look to whatever the global object is (in this case the browser window object) and call bar from there. Because we defined bar in the global context, it then returns window.
The practice of assign a variable called self is so that it doesn't matter how you call your methods, because you always reference the this at the time of creation through the self variable. You don't have to write things this way, but then you should understand that references to this may change under your feet.

Function in object and access to 'this' property - failed

Look at this sample code:
var functions = {
testFunction: function(){
console.log('testFunction()', this, this.someProperty);
}
};
functions.testFunction.someProperty = 'someValue';
functions.testFunction();
Why this.someProperty in 2nd line is undefined?
Because as you could see by a second argument console.log outputs - this refers to the functions object, not to the testFunction anonymous function.
This assignment would do what you want:
functions.someProperty = 'someValue';
obj.method() is syntactic sugar for obj.method.call(obj).
Hence when you do functions.testFunction() the this reference inside of this function call points to functions.
To access it this way you would do:
var functions = {
testFunction: function(){
console.log(this.testFunction.someProperty); //"someValue"
}
};
functions.testFunction.someProperty = 'someValue';
functions.testFunction();
The this keyword is well explained in this article.
Try like this:-
var functions = {
testFunction: function(){
console.log('testFunction()', functions, functions.someProperty);
}
};
functions.someProperty = 'someValue';
functions.testFunction();
var functions = {
testFunction: function(){
console.log('testFunction()', functions, functions.someProperty);
}
};
functions.someProperty = 'someValue'; // <------ you should set value to functions's property
functions.testFunction();

Access a function's property inside the function

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.

'this' in function inside prototype function [duplicate]

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.

Categories