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

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();

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 create an object in which the object itself is a function?

I have a javascript object from which I created from a constructor.
var obj = new Obj();
It has several functions but I wish to also use it as follows;
obj();
Obj is defined as:
function obj() {
this.blah = function () {
};
}
How can I do this?
It would be easier to have a function you call which returns an arbitrary function that is treated as both an object and a function. Each one would be unique, and you would not need to use new.
function Obj() {
var ret = function(){
console.log('Hello');
};
ret.blah = function () {
console.log('World');
};
return ret;
}
var obj = Obj();
obj();//Hello
obj.blah();//World
You can create properties on function objects. For instance, if you have the function
function foo() {
return "bar";
}
You can set a property on foo.
foo.baz = 42;
So now you can call foo and get the result "bar", and you can access its baz property.
I think you are looking for 'closure' here.
Try:
function MyObject(/* constructor params */) {
//assign properties to 'this'
return function() {
return this; //<== placeholder implementation
}.bind(this);
}
var obj1 = new MyObject();
Now if you do console.log(obj1) you will see function() { [...] } and you will be able to do obj1() to execute your function.
As a bonus in the code above, I also added this binding in the 'closure' as you will need it in most cases that you are doing anything interesting.

this opreator for nested functions

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)

'this' keyword doesn’t always refer to the object on which a method is defined, but instead can change based on specific contexts. How?

I was going through this article http://dev.opera.com/articles/view/objects-in-javascript/
where I read "'this' keyword doesn’t always refer to the object on which a method is defined, but instead can change based on specific contexts."
I couldn't find any example in which 'this' does not refer to the object on a method is defined....please gimme an example if possible
One example that you could realistically run into and not expect this result:
var obj = {
testFunc : function(){
alert("testFunc: " + this);
}
}
obj.testFunc(); // this is the object
setTimeout(obj.testFunc, 1000); // this is window
http://jsfiddle.net/t7ycd/
There are many way to change context. jsfiddle
using bind: (not supported by older IE browsers (IE < 9))
var obj = {};
function fun1(){};
obj2 = {};
obj2.fun1 = fun1.bind(obj);
obj2.fun1(); // context inside fun1 would be obj.
Using apply or call.
var obj = {};
function fun1(){};
obj2 = {};
obj2.fun1 = function(){
fun1.apply(obj, arguments);
//or fun1.call(obj, ar1, arg2,...);
};
obj2.fun1(); // context inside fun1 would be obj.
Here is one way
var a = {};
a.foo = function(){ console.log(this); }
a.foo(); // object a
a.foo.call(window); // window object
If you call a method in class B from class A, the 'this' will refer to the class that is calling the method - A, not the class that it is in.
Here is an example taken directly from the Mozilla documentation
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this
var o = {prop: 37};
function independent() {
return this.prop;
}
o.f = independent;
console.log(o.f()); // logs 37
So the function independent is defined in the global context, but is then attached to an object. When it is invoked on that object the context becomes the object on which the function is invoked rather than the object on which the function is defined.
You can achieve similar results using the javascript call and bind methods, and using anonymous functions.
like this
var MyObject = function()
{
this.initialize();
}
MyObject.prototype.SomeMethod = function()
{
//common fix is to use
//var self = this;
(function(){
//this has lost scope
//self will retain the this scope that was desired
})();
}

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.

Categories