Scope of JavaScript Objects - javascript

Quick question about JSON in general, say I had:
var foo = {
a: null,
init: function() {
this.a = document.getElementById(...);
}
}
This will give have a with null. Is there anyway to go outside this scope and get the document element other than doing it externally via foo.a = document.getElementById(...)?
EDIT: Changed title more appropriately.
I am calling foo.init(), but when I do this, say I have:
and then I call init.foo() which contains this.a = document.getElementById('test') it seems to return NULL, perhaps I am doing something wrong.

This works fine:
var foo = {
a: null,
init: function() {
this.a = document.getElementById('test');
}
}
foo.init();
console.log(foo.a);
http://jsfiddle.net/dwhxN/

This is not JSON. JSON is a lightweight data exchange format which is similar to JavaScript (hence the name JavaScript Object Notation). This is just regular JavaScript.
Nonetheless, I'm not 100% sure what you're asking. In your example, if you ran foo.init(), then foo.a would be reassigned to document.getElementById(...). If you're wanting to get the global object, then there's this old trick:
var foo = {
a: null,
init: function () {
(function () {
this.test = 1;
})();
}
};
In that example, running foo.init() will create the global variable test with a value of 1. If you mean getting the document element, as you said, then it is just as easy as referencing document (just as you did). If you mean changing the value of foo.a inside of foo.init, then there are only the two methods of using foo.a and this.a that I'm aware of.
However, I could be completely missing the mark...

It matters how the function is invoked. The following usage will behave as expected:
foo.init();
In the above example the value of this inside init will be foo, so foo.a will be modified. However, be careful. This:
var fn = foo.init;
fn();
...will not behave as expected. The object receiving the message to execute foo in this case is the window object, so the value of this inside init will be window, and foo.a will not be modified (window.a will be).
You have complete control over the value of this inside your functions. In other words, you control the context in which your functions execute. This is done using JavaScript's call/apply: For example, what if we did this:
var someObj = {};
foo.init.apply(someObj);
In this example, init will be executed in the context of someObj, which means that someObj.a will be modified.
Further reading:
https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special/this
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/function/apply

Related

Wrong bind techniques?

Did you ever think about what exactly bind does and if bind can be overused?
This is model of the object that is considered as a bad practise (example A):
var A = function() {
this.foo = "foo";
this.bar = function () {
console.log("bar");
};
};
This is same object written better:
var A = function() {
this.foo = "foo";
};
A.prototype.bar = function () {
console.log("bar");
};
Function bar is not declared over and over for each instance of A. Now look at the following snippet:
function origin() {
console.log(this.toString() + " is who I am");
};
var listOfBindedF = [];
var dummyObject = {};
for(var i = 0; i<100;i++) {
listOfBindedF.push(origin.bind(dummyObject));
}
With each bind usage, I declared new function didnt I? A lot of libs, frameworks and engines uses bind in its core. Not just for async calls, where it is really hard to go without bind, but literally everywhere, custom inheritance is good example.
I did short test to check it on my own.
Array with 100k length and full of references to origin eats
~465kB.
Array with 200k length, 100k references to origin and 100k
references to dummyObject eats ~1.1MB.
Array with 100k length full
of origin.bind(dummyObject) eats ~9.5MB.
So is there any bind performance impact on javascript apps we are doing with these frameworks/libs? Is the impact noticable? Isnt it similar to example A?
First off, this is a function declaration
function foo() {
}
and this is a function expression
var foo = function() {};
Your two As are different. Imagine the following code:
function A(foo) {
this.bar = function() {
console.log(foo);
};
}
This keeps foo private and still allows bar to access it, something not possible with the prototype version of A.
As for the memory issue: Each function object takes up some memory, obviously. A function expression always creates a new object. Creating 100 instances of A would create 100 function objects assigned to bar using your first example.
A function declaration creates an instance when its surrounding scope is entered. So 100 instances of A would still create 100 instances of bar in this case:
function A(foo) {
function bar() {
console.log(foo);
}
this.bar = bar;
}
bind also creates a new function object that needs even more memory (it has to store a reference to the original function, the value for this etc.)
Using bind has an impact, but I doubt that that will ever lead to performance problems in your app. FWIW: Calling bar in your first example for A is faster then calling it in your second one, because it's not necessary to go up the prototype chain.
Please note that bind can be used for currying as well, making it a versatile tool:
function log(message) {
console.log(message);
}
var logHello = log.bind(null, 'Hello');
logHello(); // prints 'Hello' to the console
Conclusion: Use the tool that's best suited for a task.

Where does property when added to function object

function foo()
{
var a=5;
}
Since above function is JavaScript object so we can add properties to it like foo.p=6.But while doing console.log(foo) i am not able to see the p property of object but is accessible through foo.p and foo['p'].
Also i am not able to access foo.a if we consider foo as JavaScript object.
Try console.dir(foo); instead, which lists the properties of the object. concole.log simply outputs some representation of the value, the browser thinks would be useful.
foo.a can't work. a is a local variable, not a property, and only exist while foo is executed.
When logging an object, the browser will choose how to render it in the console. This may be as primitive as calling .toString() on it, or as complex as giving you the ability to navigate its properties.
Furthermore, the console is not a standard. Browsers may implement it however they like, although for convenience they will keep to a common style. Ultimately, however, this means they will be different.
Internet Explorer:
Google Chrome:
Notice how I had to use console.dir() to force Chrome to give me a navigable view of the object, rather than its simple .toString() representation.
"a" is a local variable, this not accessible from outside the function.
you'd like something like this:
var myClass = function(){
this.foo = 'bar';
}
var myInstance = myClass();
myInstance.foo // 'bar'
or as a plain object:
var myObj = {
foo: 'bar'
}
myObj.foo // 'bar'
myObj.foo = 123;
myObj.foo // 123
There are few ways of achieving that. One is using objects in Javascript and another one with the called "Module Pattern".
For using objects, you can do:
function MyObject() {
this.foo = "myObj";
}
var mo = new MyObject();
console.log(mo.foo); //Will print "myObj".
Module pattern works as below:
var MP = (function(){}(
var foo = "MP";
return {
foo : foo
}
));
console.log(MP.foo); // Will print "MP"

fn.call(this) versus fn() when defining a CommonJS module

It's common to see CommonJS modules defined using the following idiom:
(function() {
var logThis = function() { console.log(this); }
module.exports = logThis;
}).call(this);
Underscore.js, for example, does this.
I just spend half an hour discussing with a colleague why they invoke the closure with call(this). This will cause the value of this inside the closure to be inherited from the caller, rather than being set to the global object. However, when I tested this in Node.js, the value of this inside the module was always the global object, even when I loaded and ran it like this:
var bar = {};
bar.foo = function() { var foo = require("./foo"); foo(); }
I was really expecting to see the bar object in the console, but actually I see the global object. It then occurred to me that this might be because modules like Underscore.js are also used in a web context. But in that case it would be loaded with a <script> tag so this will always be equal to the global object anyway.
What gives? I'm sure there is a reason for using this construct but I can't see the practical difference in this particular case whether the module is being used in Node.js or in a webpage.
Update: Just to clarify, I can think of a number of cases where this could make a difference. For example, if I say:
var bar = {}
var foo = require("./foo");
bar.foo = foo;
bar.foo();
(Thanks to #Pointy for correcting my original example.)
I would expect the closure in the module to be evaluated when require() is called, which means that the value of this inside it would be bound to the global object, which would be written to the console even though foo() is then invoked as a member of the "bar" object. However, I am seeing the "bar" object in the console even in this example. I guess that this is not being bound to the closure as I expected?
In a nutshell, I'm looking for one example where a module like Underscore.js will have different behavior due to being wrapped in a closure invoked with fn.call(this) instead of just fn(), either in Node.js or in a web page.
Your call to "foo" inside "bar.foo" is made without any context, so the global context is used. The fact that it's inside a function where this refers to "bar" is not relevant; that's just not how JavaScript works. The only thing that matters is how the function is invoked, not where it's invoked, in other words.
If "bar.foo" looked like this:
bar.foo = function() { require("./foo"); foo.call(this); }
then you'd see "bar" in the console. Or, you could do this:
var bar = {};
require("./foo");
bar.foo = foo;
Then calling bar.foo() would also log the "bar" object. (Does that really work in Node? That is, I thought require() returned an object, and that it didn't just leave things in the global scope. I'm a rank novice at Node however.)
edit — OK thanks for updating. Thus, my example would be corrected as follows. First, I think that your module should look like this:
(function() {
var logThis = function() { console.log(this); }
module.exports.logThis = logThis;
}).call(this);
That is, I think that you want to explort the "logThis" function, so it needs to be bound to the "exports" object as a named property.
Then:
var bar = {};
var foo = require("./foo");
// At this point, foo.logThis is the function
bar.foo = foo.logThis;
// Now the "foo" property of "bar" is a reference to the same function
bar.foo(); // logs the "bar" object
var fee = { fie: foo.logThis };
fee.fie(); // logs the "fee" object

Namespaces in JavaScript: do I need to rewrite all my variable and function references?

I am namespacing some JavaScript code, and I want to know if I have rewritten all my function calls and references to global variables correctly. The current code is this:
var x = 10;
function foo() {
console.log('foo');
bar();
},
function bar() {
console.log('bar', x);
}
foo();
I have rewritten it as follows:
var namespace = {
x : 10,
foo: function() {
console.log('foo');
// Is this the correct way to call bar?
this.bar();
},
bar: function() {
// Is this the correct way to refer to x?
console.log('bar', this.x);
}
};
namespace.foo();
Is this correct, i.e. do I need to rewrite all function calls (EDIT: by which I mean all inside the namespace variable) to this.functionname() and all global variables to this.variablename?
If you like, you can make yourself some "real" private variables and methods by incorporating a closure. I favour the module pattern.
var ns = (function () {
var x = 10;
return {
foo: function () {
console.log('foo');
this.bar();
},
bar: function () {
console.log('bar', x);
},
increment: function () {
x++;
}
}
}());
ns.foo();
ns.increment();
ns.foo();
http://jsfiddle.net/DjYue/
No, in some places (code that calls those functions from outside of your namespace object) you would have to call namespace.foo(), namespace.bar(), namespace.varName
Actually, if you use namespace.bar() from the function in the object itself, you get the added benefit that your functions don't depend on context. That is, the following code doesn't work with what you have
var fun = namespace.foo;
fun(); // This would break, since the this value is going to be the global object
I usually don't like to use this from literal objects because of the problem mentioned above. It's definitely a preference, I just prefer to avoid problems with this
No, you shouldn't rewrite to this.funcname() but rather namespace.funcname(). The this keyword is reserved to refer to the current context object (or whatever it's called), meaning that you'd use it within your "namespaced" code to refer to the namespace object.
And generally, it's good to know that you aren't actually working with namespaces as you'd know it from more classical OOP. JavaScript is a prototype-based language, which means that you don't have namespaces - rather, what you're creating is an object containing several properties and methods. As previously mentioned, when you're working with methods of the object, the this keyword refers to the object itself. You'd need a reference to the object when outside of it's context.
Currently, the approach of using objects to contain all of your code as a sort of namespaces and classes in disguise is diminishing in favor of closures which attaches the methods and properties that should be publicly available to a function (which, in JavaScript, is a first class object), and either returns that function or attaches it to the global object. You may also, alternatively, use a function to contain the properties and methods instead of an object.
I disagree with the people who say No to your question. It really depends on what you want to accomplish here. Based the rewritten code, I don't see anything wrong with it. As long as you call namespace.foo(), the execution context of each function should be namespace. Thus, it is not wrong to use this.
There is a situation that invoking the function foo() will not work:
var foo1 = namespace.foo;
foo1();
Although foo1 is same as the function namespace.foo, foo1's execution context has changed. this will refer to window, not namespace.
Their is no need to rewrite that much because you can have more than one reference to a function - a private and a public one.
var namespace = (function() {
var ns = {}; // the 'namespace'
var x = 10;
var foo = // 'private' reference: bar();
ns.foo = // 'public' reference: ns.bar() -> namespace.bar();
function foo() { // the name is optional because it's a function expression
console.log('foo');
bar();
}; // don't forget the semicolon
var bar =
ns.bar =
function() {
console.log('bar', x);
};
return ns; // return the 'namespace'
})();
namespace.foo();
var foo = namespace.foo;
foo();
delete namespace.bar;
// namespace.bar(); // Error
foo(); // bar is called

calling inner-function dynamically in javascript

is it possible to call inner function dynamically(by it's name)?
e.g.
function a(){
function b(){..}
var funcName = "b";
//calling the function b somehow using funcName
}
I know it's possible by using eval, but I rather not using eval, if b was global function I could use window[funcName] or global[funcName]...
Sounds like you want to access b through its name ("b") magically, without recording the name b in a separate structure.
You are correct that global variables are properties of the global object, generally accessed through the identifier window in web environments. It's fun how that works actually, as window is a property of the global object pointing to itself, but, that is off topic.
Local variables are properties of an object, too -- the call object. This object exists temporarily during the call. If you could get to the call object directly, then you would be able to say something like theCallObject[funcName], because the nested function is still a local variable, although hoisted. Alas, this object is not directly accessible, so you basically have to revert to the techniques shown in the earlier answers.
Here is an SO question with info: How to output call object in javascript?.
I suppose it is possible to write a JS engine with an extension permitting access to the call object, much like Mozilla gave us the non-standard __proto__.
Well, if you can declare it differently, and it's not so hard:
function a(){
this.b = function() {...};
// dynamic access
var funcName = "b";
this[funcName]();
// still need static access?
var b = this.b;
b();
}
You can mix it up, of course. But Functions are just objects (both a and b), so they can be assigned, moved around, and even have instance members.
A variation on OverZealous's answer that does not muck with this:
function a(){
function b(){..}
var internalFuncs = {"b": b}
var funcName = "b"
internalFuncs[funcName]()
}
Happy coding.
Another approach:
var a = (function() {
return {
b: function() { alert("b"); },
c: function() { alert("c"); },
d: function() { alert("d"); }
}
})();
a["b"]();
Fiddle: http://jsfiddle.net/raSKW/

Categories

Resources