I would like to access variables created inside a private context. I'm creating a private context like this:
(new Function("var a = 'hello'; console.log('this', this);")).call({});
// outputs -> this Object {}
I'm call'ing the function with an empty context. But this doesn't holds the a variable. And anyway how is it possible that console.log works with an empty context?
jsFiddle Demo
Inside of the scope for the function which creates the object var a is present. However, once that scope is lost, so is the variable. If you would like a to persist, you would need to attach it to the object that is created using the this keyword:
(new Function("this.a = 'hello'; console.log(this);")).call({});
However, this is an obfuscated way of doing it. There are elements which are not required here. Mainly that the new keyword is not needed (Function implies a function object). Function also comes with methods, such as call.
Function("this.a = 'hello'; console.log(this);").call({});
This will also work. Moreover, if you would like to retain what is in the variable a, you could always do this (demo):
var obj = {};
Function("this.a = 'hello'").call(obj);
obj.a;//hello
As for why it works with an empty context. You have actually given it a freshly constructed object with {}. So that is the scope that is used inside of the function when the reference this is encountered. In fact, call() does not need arguments if you are not intending to use scope. Something like this:
Function("console.log(5);").call();
will log 5 to the console without error.
The approach used in your question is to build a function from a magic string. That approach is pretty cool I must say, very similar to eval. But what you are looking for boils down to this difference I think:
function ball(){
var color = "red";
return color;
}
function Ball(){
this.color = "red";
}
console.log(ball());//logs red
console.log(new Ball().color);//logs red
Related
What's the best way for a method to call another method and pass the arguments in not-by-reference fashion?
i.e.
function main() {
let context = {};
// Pass context to someOtherFunction
// Such that console.log(context) in this function does not show `{whatever: true}`
}
function someOtherFunc(context) {
context.whatever = true;
}
I realize I can clone the context and pass that. But I was wondering if there was another way to do this, maybe using anonymous function wrap?
Okay, let's break this down a bit
const context = {x: true};
Above, you create an object (named context) in the global scope.
function(x) {
"use strict";
x.y = true;
}
You create an anonymous function that takes a reference to an object, and adds a new property y to that object
(/*...*/)(context);
You wrapped the above function into an IIFE so it immediately executes. For the parameter, you supplied a reference to the global context object, which is referenced by x inside the IIFE.
Objects are passed around by reference. Passing context in to the function doesn't create a new object x that is a copy of the context, it creates a new reference x that references the same object that context references.
If you need to actually copy the provided object into a new object, you need to do that yourself. As mentioned above, one mechanism is to stringify the object into JSON and then parse the JSON back to a new object. There are others depending on what you need to accomplish.
This isn't even a scope or context question at all - it's passing a reference to an object in to a function. Even if your IIFE had no way whatsoever of directly accessing the context variable, once you pass a reference to that object as an input to the function, the function has the reference and can do what it likes to it.
You also seem to misunderstand about how IIFEs hide data. You hide things inside the IIFE from things outside, not vice versa. Even then, it won't prevent you from passing a reference outside of the IIFE. Here's an example:
function changeName(animal) {
"use strict"
//myDog.name = "Rex"; // Error - myDog isn't a valid reference in this scope
//myCat.name = "Rex"; // Error - myCat isn't a valid reference in this scope either
animal.name = "Rex"; // Perfectly legal
}
(function () {
var myDog = {name: "Rover"};
var myCat = {name: "Kitty"};
console.log(myDog);
console.log(myCat);
changeName(myDog); // Even though changeName couldn't directly access myDog, if we give it a reference, it can do what it likes with it.
console.log(myDog);
})()
In this case, changeName has no access to myDog or myCat which are purely contained within the closure formed by the IIFE. However, the code that exists within that IIFE is able to pass a reference to myDog to changeName and allow it to change the name of the dog, even though changeName still couldn't access the object using the myDog variable.
This is because you are not technically redefining x, but adding properties to it.
I didn't really understood where your doubts came from so this is (to the best of my knowledge) an explanation of what your code is doing.
I'll try to translate the code to human-english.
Define the variable context in the "global scope". (It can be read from anywhere)
It cannot be redefined because its a constant.
Afterwards, define an anonymous self-invoking function (which "starts" a new "local scope" above the global scope so it has access to everything the global scope had access to)
This self invoking function grabs parameter x and adds the property y with a value of true to x and calls itself with the variable context
Read the value of context.
Please read:
JavaScript Scope
JavaScript Function Definitions (Self-Invoking Functions)
I've been learning Javascript with Khan Academy. I'm looking at : http://www.khanacademy.org/cs/speed-circles/964929070
there is a line that reads "var draw = function() {...}" is he defining a function called draw? Or is the variable draw calling some function (which I don't see defined)?
Thanks!
Yes, a function expression is being assigned to the variable named draw. You can even call it:
var draw = function() {
console.log('xyz');
};
draw(); // 'xyz'
In JavaScript, functions are objects, just like arrays and -logically- objects are. As you may have found out already these objects can be assigned to a multitude of variables, but as soon as you change one of these variables, they all change. That's because JS always assigns by value, but a variable is never assigned an object directly: it's assigned a reference to an object:
var obj = {iam: 'an object'};
var reassign = obj;
console.log(obj);//shows object
console.log(reassign);//surprize, shows the same thing
reassign.bar = 'foobar';
console.log(obj.bar);//logs foobar, the variable obj has gained the same property, because it is the same object.
The same applies to functions, being objects, the can be assigned to variables/properties all over the place, but it'll still be the same object/function:
var foo = function()
{
console.log('I am an object');
};
var second = foo;
second();//logs I am an object
console.log(second === foo);//logs true, because they both reference the same thing
Why, then, you might ask is an anonymous function being assigned to a variable, instead of just declaring a function as you'd expect? Well:
function foo(){}
is hoisted, prior to running any code, JS moves all function declarations and variable declarations to the very top of the scope, but in your case, you're not simply defining a function, or declaring a variable: JS has to do something, too: assign a reference to a variable. The function won't be hoisted:
var foo = function()
{
console.log('foo');
};
foo();//logs foo
foo = function()
{
console.log('bar');
};
foo();//logs bar now
If foo were undefined prior to the assignment, you'd get an error. If any code preceded the code above, JS would hoist the variable declaration of foo, but it's value would still be undefined.
What's the point? This will prove useful when you start playing with closures, or if you need the function to differ, depending on a branch (if (x){ foo = functionX} else { foo = functionY;}). These are just 2 reasons why you'd want to avoid scope hoisting... but the most important reason of all ATM has to be redefining a function on the fly
Note that in processing.js (as used by this Khan academy demo), the function draw is automatically called every frame reference doc.
This bit of code overrides the default (empty) implementation of draw so that the given code is called every frame.
Khan academy has a tutorial about this use of the draw function here.
function draw(){ return "Sample"; };
var draw = function(){ return "Sample"; };
are same meaning.
function () { ... } creates a function value. That is, something that can be passed around just as easily as a number, or any other object in javascript.
He then binds it to the name draw for future reference.
He could as well have written
function draw() {
...
}
For these purposes they are equivalent.
My question is dead simple.
I just casually discovered that once you have defined a property with this. into an object, you don't need to prepend this. anymore when you want to call them.
So this. is really meant to be used ad definition time, like var?
I found it my self shortly after, i was referencing the window object with this. since i called my object without using new, so like it was a function.
One extra question, maybe for comments. Inside the main object, if i create a new object, and use this during the object definition, this this what will be referring to?
No, unless the context of this is a global object, such as window. Take the following example:
function Foo(bar) {
this.data = bar;
console.log(this.data); // OK
console.log(data); // ReferenceError
}
In this example, you'll get a ReferenceError: data is not defined on the first console.log(data), unless, data is a global variable. To access the instance's public member, you have to use this.data.
References:
Understanding JavaScript’s this keyword
The this keyword
There are all sorts of circumstances where you MUST use this in order to reference the right data.
These two implementations do very different things:
Array.prototype.truncate(newLen) {
// sets the length property on the current Array object
this.length = newLen;
}
Array.prototype.truncate(newLen) {
// sets a global variable named length
length = newLen;
}
var arr = [1,2,3,4,5,6,7];
arr.truncate(2);
You MUST use this in order to control what happens if you want to modify the current object. Your assumption that you can leave it off and it will still modify the current object's properties is not correct. If you leave it off, you are modifying global variables, not member properties.
So this. is really meant to be used ad definition time, like var?
No, the point of this is to be the current scope of execution. You can (and will) run into weird errors if you don't use this. For example, imagine you are an object with a property val and then on the prototype of that object you have
App.obj = function(){
this.val = 'initial';
}
obj.prototype.myMethod = function(val) {
// how would you assign argument val to object val?
}
also note that your reasoning breaks down with methods.
obj.prototype.meth2 = function(){
myMethod(); // fails where this.myMethod() would work.
}
See http://jsfiddle.net/BRsqH/:
function f(){
this.public='hello!';
var hidden='TOP SECRET!';
}
var instance=new f();
alert('Public data: '+instance.public+ /* gives "hello!" */
'\nHidden data: '+instance.hidden /* gives undefined */
);
Variables created with var are hidden and cannot be viewed nor modified outside the function which created them.
But variables created with this are public, so you can access them outside the function.
I think I got it.
I defined my object as function My_Object(){...} and then called it with MyObject(). This way the My_Object was treated as a function, not an object and therefore this == window.
So in the end I was attaching properties and methods to window instead of My_Object! That's way there were available without prepending .this.
The right way to initialize My_Object as an object is to call it like this new My_Object, isn't right?
I recently started programming JavaScript and thought everything would be good...
Well today I faced a problem I can't solve on my own.
My tutorial/ learning project has a class called model. In this class there are several private and one public variable. This variable is of type CustomEvent:
function Model(){
/**
* Array in which the questions are stored
*/
var questions=new Array();
var db;
var valuesSplit="*";
var tableName="quests";
this.myEvent=new CustomEvent("my event");
So as you can see "myEvent" is public and can be called from outside. In this case it is an event which can be subscribed (this is done outside this class by other objects that want to listen) and it can be fired (this is done in the same class). And this is my problem.
How can I access myEvent within the model class?
I tried:
this.myEvent.fire()
and:
myEvent.fire()
But I always get "myEvent is not defined".
Probably the first thing to say is: JavaScript doesn't have classes. The sooner you stop thinking of "JavaScript classes," the better off you'll be. :-) JavaScript has OOP, but not the kind with classes. Your Model function is called a constructor function.
You can access myEvent from any code that has a reference to the object created by new Model, which includes code in your constructor (via this — e.g., the way you're setting it up) and any function called with this referring to that object (or, of course, "externally" via someObjReference.myEvent).
So probably this.myEvent.fire() is what you want, but the code you're calling it from doesn't have the right this value. That's because in JavaScript, this is controlled entirely by how a function is called, not where the function is defined as it is in some other languages. See my blog articles Mythical methods and You must remember this for more details, but I've done a somewhat truncated discussion below.
Here's an example of a fairly standard way to set up a constructor function with useful methods that all instances share:
function Foo() {
this.myEvent = new CustomEvent("my event");
}
Foo.prototype.bar = function() {
this.myEvent.fire();
};
// Usage:
var f = new Foo();
f.bar(); // Fires the event indirectly, via the code in `bar`
f.myEvent.fire(); // Fires it directly
Note that that only works if bar is called with this referring to an object with a myEvent property. It's easy to call bar with this set to something else entirely:
document.getElementById("someID").onclick = f.bar;
When the click occurs, the bar function gets called, but this does not refer to an object created via Model. (It will refer to the element with the id "someID" instead.) And so this line in bar
this.myEvent.fire();
...will fail.
If you're used to class-based languages, you can see how this is totally different from, say, Java, C#, or C++. In those langauges, this inside bar will always refer to an object created via new Model. Not so JavaScript, which is both awkward and powerful.
This flexibility of functions (not being bound to any particular object) is one of the biggest things to get used to, and take advantage of, in JavaScript. The other is how functions are closures, which is powerful but not complicated.
So if this is set by how a function is called, how do you do that? There are two ways:
Call the function by referencing it from an object property in the same expression as the call. That's an awkward way of saying do this:
var f = new Foo();
f.bar(); // <== The key bit
f["bar"](); // <== Also works
The expression f.bar() does two things, which interact: The first thing it does is retrieve the property bar of the object referenced by f, and get that property's value (which is a function reference). Then it calls that function (because of the ()). The way JavaScript works, because you did those two things in the same overall expression, the interpreter sets this to f during the call to bar for you. But note this key distinction:
var f = new Foo();
var b = f.bar;
b(); // <== Different!
Now when the bar function gets called, this will not be set to f (it'll be set to the global object, which is window on browsers), because we've separated the property retrieval from the function call.
Alternately, you can use the built-in features of JavaScript function objects, their call and apply functions. call and apply do exactly the same thing, the only difference between them is how you supply the arguments for the function. Example:
var f = new Foo();
f.bar(1, 2): // <== Calls `bar` with `this` === `f` and passing in
// the arguments 1 and 2
var b = f.bar;
b.call(f, 1, 2); // <== Does the same thing as f.bar(1, 2)
var args = [1, 2];
b.apply(f, args); // <== Does the same thing as f.bar(1, 2)
E.g., call and apply allow you to set what this should be explicitly when you call the function. The only difference between them is that call accepts the arguments to give the function as further arguments to call, and apply accepts them as an array.
If you want to use myEvent in a non public function in your Model than you have to create another reference to the myEvent which isn't using the this reference of your Model. Because the this in another function is something else than in your Model function. The easiest way to bypass this problem is if you define a new variable in your Model:
var that = this;
Then you can call your myEvent like:
that.myEvent
The myEvent member should be visible both in the inner & outer scope of the object :
function Model(){
this.myEvent = 'some value';
this.canAccessEvent = function(){
return 'myEvent' in this;
}
}
var m = new Model();
// access from outside :
alert(m.myEvent);
// access from inside :
alert('Model can access the even? ' + m.canAccessEvent());
However, it is very possible that your new CustomEvent function doesn't exist or does not return a valid object making your myEvent variable to be undefined. I suggest you attribute some other value to the myEvent property and see if it is defined. If it is defined, then the problem lies in your CustomEvent function.
I definitely need some light on this.
What's the diference between:
var MY_APP = function(){
this.firstMethod = function(){
//something
};
this.secondMethod = function(){
//something
};
};
and
var MY_APP = {
firstKey: function(){
//something
},
secondKey: function(){
//something
}
};
besides the obvious fact that one is a Function and the other an Object, what are the differences in code flow, prototypes, patterns... whatever, and when should we use the first or the second?
I'm so spaced out in this area that i'm not sure if i'm correctly explaining the doubt, but further info can be given if you ask.
The key difference between the two is in how they are intended to be used. A constructor, as its name suggests, is designed to create and set up multiple instances of an object. An object literal on the other hand is one-off, like string and number literals, and used more often as configuration objects or global singletons (e.g. for namespacing).
There are a few subtleties about the first example to note:
When the code is executed, an anonymous function is created and assigned to MY_APP, but nothing else happens. firstMethod and secondMethod don't exist until MY_APP is explicitly called.
Depending on how MY_APP is called, the methods firstMethod and secondMethod will end up in different places:
MY_APP(): Since no context is supplied, the this defaults to window and the methods will become global.
var app1 = new MY_APP(): Due to the new keyword, a new object is created and becomes the default context. this refers to the new object, and the methods will get assigned to the new object, which subsequently gets assigned to app1. However, MY_APP.firstMethod remains undefined.
MY_APP.call(YOUR_APP): This calls my MY_APP but sets the context to be another object, YOUR_APP. The methods will get assigned to YOUR_APP, overriding any properties of YOUR_APP with the same names. This is a really flexible method that allows multiple inheritance or mixins in Javascript.
Constructors also allow another level of flexibility since functions provide closures, while object literals do not. If for example firstMethod and secondMethod rely on a common variable password that is private to the object (cannot be accessed outside the constructor), this can be achieved very simply by doing:
var MY_APP = function(){
var password = "GFHSFG";
this.firstMethod = function(){
// Do something with password
alert(password); // Woops!
};
this.secondMethod = function(){
// Do something else with password
};
};
MY_APP();
alert(password); // undefined
alert(MY_APP.password); // undefined
The first is a function, the second is an object literal. Since Functions in JS are first class objects, a function can have properties on it, just like any other object can.
Typically, if you want to create a "class" that you might be familiar with from classical inheritance languages, you would do something like
function MyClass() {...}
as is documented here http://www.crockford.com/javascript/inheritance.html
To answer the question posed in your edits, you would use them both in different situations. Object literals are used to pass configurations around. A typical usage pattern would be a method that accepts an object literal like so
something.init({
length: 10,
height: 10,
text: 'some text'
});
and so on.
You could use something similar to your first example when creating a namespace. Javascript has some interesting language features in that you can have so-called "self-invoking functions" that are of the form:
var myApp = (function(){
var firstMethod = function() {...}
...
})();
the motivations behind doing something like this are detailed here
http://sparecycles.wordpress.com/2008/06/29/advanced-javascript/
You can also investigate the differences via your favorite javascript debugging console. In firebug and chrome, I did the following:
var ol = {}; ol.prototype;
var fn = function(){}; fn.prototype;
the first line prints undefined, the second returns a prototype with a constructor of 'function'
The constructor can be reused as is, the object literal would need to be repeated or wrapped in a function to be reused.
Example of wrapping the object literal in a function:
function MY_APP() {
return {
firstKey: function(){
//something
},
secondKey: function(){
//something
}
};
}
The object created using the constructor will have it's constructor property set to the constructor function. However, as you used an anonymous function assigned to a variable instead of a named function, the constructor will still be nameless.
Other than that, there isn't really any differences. Both create anonymous functions that are assigned to the properties of the object, so the resulting objects are the same. You can compare this to assigning named functions to the properties, or using prototype functions, both having the difference that each function only exists once instead of being created over and over for each object.
There is some confusion in JavaScript regarding the difference between a function and an object.
In the first case,
var MY_APP = function() { this.v = 7; ... }
or
function MY_APP(x) { this.v = x; ... }
a function is declared, not an object. In MY_APP, this refers to the global object.
Meaning that calling the function MY_APP(7) will assign v globally to the value of 7. (and in your case the function firstMethod would be declared globally).
MY_APP(3); // The global variable v is set to 3
MY_APP(4); // The global variable v is overwritten and set to 4
To use MY_APP as an object, it needs to be instantiated, for instance
var obj1 = new MY_APP(3);
var obj2 = new MY_APP(4);
will have obj1.v to be 3, and obj2.v to be 4.
Note you can also add methods using the prototype keyword (instead of this.firstMethod...)
MY_APP.prototype.firstMethod = function () { ... }
In the second case
var MY_APP = { ... };
an object, one object, is created and its name is MY_APP. The this keywords refers to that object, MY_APP.