After looking around a bit, I couldn't find an answer to this question, though I suspect it's been asked before. The closest I could find is this Function pointers in objects though it doesn't get quite what I'm after.
Suppose we have a piece of code like this:
var foo = function () { /* some code */ };
now, I'm assuming that during evaluation time the name foo is bound in it's environment to an internal representation of the function, that is then looked up during application time.
Now suppose we have , a little later in the program, an object:
var obj = {};
obj.func = foo;
At this point, there should be two copies of the same function object in the environment, one bound to foo, the other bound to obj.func. But let's say I don't want two copies of that function, but rather have obj.func point back towards foo--is there a way to do this?
This is what I've come up with:
var obj = {};
obj.func = function () { foo(); };
Would this work? Is there a better way?
Many thanks
EDIT FOR CLARIFICATION
Apologies--I don't think I was being clear enough. I hope this helps.
I'm not sure how the Javascript evaluation process works, but let's say it keeps track of some internally represented environment, which we'll represent abstractly here as a set of key value pairs.
Now, when the evaluator sees some code such as
var foo = function () { /* some code */ };
it constructs this in it's environment: ['foo' : [function object]]. And then, later on, when it sees something like this:
var bar = foo;
it looks up foo in the environment to retrieve it's value, a function object, and then augments the environment like so. ['foo' : [function object], 'bar' : [function object]].
Now the same function really is there twice in the environment. Is this how javascript sets up its environment? If not, then how does it do so?
My motivation for asking is as follows. Let's say we define some functions, and then later an object that we export that functions as an interface to those functions, and which we know we're going to instantiate many times. It would be more efficient if the object contained pointers to functions, rather than the functions themselves.
JS variables, object properties, etc do not hold objects directly; they hold references to objects. When you say var foo = function() { };, foo is assigned a reference to that function you just defined. (Not a pointer, by the way. The difference can be subtle, but important. JS has no user-visible pointers, so it's not as much of an issue. But the languages that do, use them differently. Don't make yourself have to unlearn stuff later.)
And later in the program, when you say obj.func = foo;, you're copying the reference into obj.func. Not the function -- there's still only one function object, with two references to it.
So obj.func = foo; already does what you were saying. When you call obj.func(), it's actually calling the exact same function that's referenced by foo. There's one huge difference, though, and this may be what's causing you trouble: obj.func is a "method call", and JS sets this to obj inside the function. If foo was using this for anything, assuming it was some other object, it's going to be disappointed.
If that's a problem, you might do something like
var that = this;
var foo = function() { /* use `that` instead of `this` here */ };
Then, whether you call the function as foo or obj.func, it's not affected by the changed this.
If this doesn't help, you'll need to clarify the question.
Have you tried running your example?
Yes, that does work, however be aware that if you change the foo variable it will also change the functionality of objc.func().
I don't know any other way to do this.
This isn't true:
At this point, there should be two copies of the same function object in the environment, one bound to foo, the other bound to obj.func. But let's say I don't want two copies of that function, but rather have obj.func point back towards foo
If you assign things that way then obj.func and foo point to the same thing. I don't even think it's possible to copy a function.
Just to elaborate a bit:
functions are first class citizens or objects in javascript. They are used just like any other objects.
var foo = func() {
//some code
};
is the analogous to
var foo = {
//some code
};
In Javascript, all objects are passed by reference. As far as I know there is no concept of a pointer or pass by value for javascript objects.
So when you assign two references to the same function, the function object is not copied. However, the internal state of the function remains the same for both the references. In your case foo and obj.func()
At this point, there should be two copies of the same function object in the environment, one bound to foo, the other bound to obj.func.
You think so? Just out of curiosity, if the code said:
var obj = {};
obj.func = 5;
How many copies of 5 are floating around?
No. All code is translated to functions, which are essentially constants. You can assign several variables to the same constant without any trouble.
As for "binding", binding occurs when the function is called. That is, the this parameter is set to obj and whooosh...
Related
I had a random, rather rudimentary question pop into my head as I was writing some JS about scopes and closures. (Please bear with me with the rather convoluted example.)
Let's say I have two functions, one that's more or less a decorator called "makeMagicFn". This thing takes in an object, looks up the randomFn method on it, and does something cool to it, attaching it as a property to a new object as someSpecialFn, returning the object.
The second function is where that magic happens. It has a few local variables inside of it, and then defines the "random" function for use in the makeMagicFn described above.
Here's the fun part. The randomFn, defined here as innerFn, looks up the variables defined on outerFn's scope (foo and baz), and does some stuff with them. At the end, the decorated innerFn is returned from outerFn to be used by its caller.
function makeMagicFn({ randomFn }) {
const someSpecialFn = makeSomethingAwesomeWithRandomFn(fn);
return {someSpecialFn};
}
function outerFn() {
const foo = "bar";
const baz = "qux";
const insideFn = () => {
console.log(foo, baz);
}
const {someSpecialFn} = makeMagicFn({ randomFn: insideFn });
return someSpecialFn;
}
Now for my question.
Does JS allow me to define innerFn outside of outerFn, in such a way that allows access to outerFn's scope, so it can look up the variables without throwing a ___ is not defined error? (E.g. if I wanted to import it from a separate file instead.) Like using .bind, except setting the context not on outerFn's this, but its place in memory instead.
No, this is not possible. Local variables are local, and scope is lexical. To create a closure over them, you must define the function where they are in scope.
You can do lots of trickery if you don't make foo and baz local variables but properties of an object, which you then can pass around (in the easiest case, as an argument to makeMagicFn).
I want to be able to take a string and use that to retrieve the value of a constant that has that string's name. In particular, the constant will equal an arrow function.
const foo = (bar) => { return bar }
I expected that it would show up in the window object, but it doesn't:
let fn = window['foo'] // undefined
Right now, the only way I can figure out how to do this is to use the older function syntax:
function foo(bar) { return bar }
let fn = window['foo'] // function foo(bar) { return bar }
Is there a way I can get the function from the string of its name, when the function is stored within a constant?
Edit:
I feel the need to clarify why I would want to start defining functions like this, as most responses have seemed to find the distinction important. It essentially comes down to scope and mutability.
The way arrow functions handle the this keyword is a little easier to grok with arrow functions and I believe should be the standard behavior unless the old behavior is explicitly required.
Second, the way mutability works with JavaScript, I think that defining functions as constants is a bit safer. Example:
function foo(bar) { return bar }
// Elsewhere
let foo = 4;
// Back at the ranch
foo("return this string please") // foo is not a function.
Ultimately, I think this just reduces mutability, and also causes fewer surprises when using this.
Only global variables get assigned a matching property on the global object. Nothing else, including constants, does.
The value of a constant won't automatically appear anywhere except in the constant itself.
If you want to access it via a string, then store it as a property of an object (preferably not the global object though, that's a disorganised mess with a significant risk of clashing with other code).
[Edited] Important! Function is treated as object, not value. So this question is invalid because it is based on a wrong assumption. This edit serves as a note to avoid confusing anyone who read this question.
Let's say I have a function expression of foo
var foo = function() {
return this.member;
}
and I have the following class and instantiate many objects of it with "foo" as the callback function.
var simpleClass = function(callback) {
this.member = "I am an instance variable";
this.callback = callback;
}
var a = new simpleClass(foo);
var b = new simpleClass(foo);
var c = new simpleClass(foo);
.
.
.
Since in JavaScript arguments are passed by value, we are copying the value([Edited]actually it should be object) of foo to a, b, c and other variables' callback. If my understanding is correct, then foo will be copied n times, each occupying certain memory space for each object.
Base on this understanding, I have some performance questions regarding this situation:
Does copying functions to multiple variables harm the performance?
Since each copies of "foo" as simpleClass object's "callback" occupies space, if there are really many simpleClass object(e.g. in a DOM library I have thousands of DOM objects which has the same function css()), will it harm the performance significantly? Or most JavaScript engine has mechanism to tackle this situation and it generally won't harm at all?
In situation where potentially hundreds or thousands of object will be created. Is it always a good practice to put those shared functions to the prototype of an object?
Since all the object instance share the same class prototype, if we put the "foo" function to the prototype of simpleClass, then there should have only one copy of the "foo" and every object instance will just execute the prototype copy of "foo" when needed. Is this a good practice we should follow?
I try to search for similar keywords but couldn't find the right wordings to find the solution to this problem. Please correct my wordings if I make anything unclear. And of course if I have any misunderstandings please correct me too. I appreciate everyone's help.
I don't understand this well enough to give you an authoritative answer but I can say this:
then foo will be copied n times, each occupying certain memory space for each object.
This is incorrect. foo is a variable pointing to a function. foo is not the function, if you did var bar = foo, bar now also points to the function, the same function. So the function is not copied. A reference to the function is assigned to this.callback.
In situation where potentially hundreds or thousands of object will be created. Is it always a good practice to put those shared functions to the prototype of an object?
What is and isn't good practise in JavaScript is up for debate. Some people like to use class/prototype, other people use object literals. It's definitly true though that prototype can help reduce the memory footprint of your application. See it like this: if you're using prototype you're giving the JavaScript engine more information about the object, ie. that your object is similar to all these other objects. The JavaScript engine should be able to make optimizations based on that. I can't say too much about the exact numbers, it might vary wildly per vendor.
Your code sample is equivalent to this:
function foo() {}
function myClass() {
this.foo = foo;
}
var instance = new myClass();
If you used prototypes you'd write:
function myClass() {}
myClass.prototype.foo = function () {};
var instance = new myClass();
If you used object literals you'd have:
function foo() {};
function create_myClass() {
return {
foo: foo
};
}
var instance = create_myClass();
In all the cases above the function foo is never copied. In these cases below you do create a new copy of foo every time:
function myClass() {
this.foo = function () {}; // new copy every time
}
var instance = new myClass();
function create_myClass() {
return {
foo: function () {}; // new copy every time
};
}
As for performance. This is the tip I always give: don't start optimizing until you run into a measurable problem. Always measure with real data. Additionally, if you think your way of doing things is good then it's likely that JavaScript engine vendors will optimize for that method.
In javascript reference is copied not the object itself so you can't assign the value to callback to change the function from inside constructor. You your code all those object will share the function, look at this snipet:
var foo = function() {
return this.member;
}
var simpleClass = function(callback) {
this.member = "I am an instance variable";
this.callback = callback;
}
var a = new simpleClass(foo);
var b = new simpleClass(foo);
alert(a.callback === b.callback ? 'shared' : 'not shared');
I thought I had a reasonable understanding of the this object in JavaScript. When dealing with objects, callbacks, and both events and handlers, I haven't had a problem with it since time immemorial. Now, however, all has changed.
I've fallen head over heels in love with JavaScript. Pure JS, that is, not jQuery, prototype.js, dojo... So naturally, I've taken to using closures. In some cases, though, this is catching me off guard here. Take this snippet for one:
function anyFunc(par)
{
//console.log(par);
console.log(this);
}
function makeClosure(func)
{
return function(par)
{
return func(par);
}
}
var close = makeClosure(anyFunc);
close('Foo');
var objWithClosure = {cls:makeClosure(anyFunc),prop:'foobar'};
objWithClosure.cls(objWithClosure.prop);
var scndObj = {prop:'Foobar2'};
scndObj.cls = makeClosure;
scndObj.cls = scndObj.cls(anyFunc);
scndObj.cls(scndObj.prop);
In all three cases, this logs as the window object. It's an easy fix, of course:
function makeClosure(func)
{
return function(par)
{
return func.call(this,par);
}
}
This fix works, I put it here to avoid people answering this, without explaining what I need to know: why is this behaving the way it does here?
ensures the caller is effectively the object that the closure belongs to. What I fail to understand is this:
Sure enough, this points to the window object in the first case, but in other cases, it shouldn't. I tried logging this in the makeClosure function just before returning, and it did log the object itself, not the window object. But when the actual closure is used, this is back to pointing to the window object. Why?
The only thing I can think of is that, by passing the anyFunc function as an argument, I'm actually passing window.anyFunc. So I tried this quick fix:
function makeClosure(func)
{
var theFunc = func;
return function(par)
{
theFunc(par);
}
}
With the expected results, this now points to the objects, but again: Why? I have a few idea's (theFunc is a reference to the function in the local scope [this > private: theFunc]?), but I'm sure there are people here with a lot more know-how when it comes to JS, so I was hoping to get some more explanation or links to articles worth reading from them...
Thanks
Update
Here's a fiddle, may be I left something out, but here this logs all sorts of things ;)
Edit/Update 2
The case that confuses me is here.
Final Edit
Ok, This is getting a rather messy post. So to clarify: What I was expecting was a behaviour similar to this:
function makeClosure()
{
function fromThisFunc()
{
console.log(this);
}
return fromThisFunc;
}
var windowContext = makeClosure();
windowContext();
var objectContext = {cls:makeClosure()};
objectContext.cls();
What caught me, was that the function anyFunc wasn't declared within the correct scope, and therefore, this pointed to the window object. I found this out by reading an ancient scroll I found somewhere on the web.
But something a little more complicated has happened because the function object now referred to by globalVar was created with a [[scope]] property referring to a scope chain containing the Activation/Variable object belonging to the execution context in which it was created (and the global object). Now the Activation/Variable object cannot be garbage collected either as the execution of the function object referred to by globalVar will need to add the whole scope chain from its [[scope]] property to the scope of the execution context created for each call to it.
So what I needed to do, was simplify rather then complicate things:
function fromThisFunc()
{
console.log(this);
}
function makeClosure(funcRef)
{
//some code here
return funcRef;
}
That should work, right?
PS: I'll except Alnitak's answer, but special thanks goes to Felix Kling for all the patience and info.
As soon as you call:
return func(par);
You're creating a new scope (with its own this) and in this case because you haven't specified an object, this === window usually or undefined in strict mode. The called function does not inherit whatever this was in the calling scope.
Ways to set a value for this are:
myobj.func(par); // this === myobj
or
func.call(myobj, ...) // this === myobj
There are also:
apply
bind
arrow functions, where this is set to the same value as the outer execution context (also see MDN:Arrow functions )
The value of this depends only on whether you call the function as a method or as a function.
If you call it as a method, this will be the object that the method belongs to:
obj.myFunction();
If you call it as a function, this will be the window object:
myFunction();
Note that even if you are in a method that belongs to an object, you still have to call other methods in the object using the method syntax, otherwise they will be called as functions:
this.myOtherFunction();
If you put a method reference in a variable, you will detach it from the object, and it will be called as a function:
var f = obj.myFunction;
f();
The call and apply methods are used to call a function as a method even if it's not a method in the object (or if it's a method in a different object):
myFunction.call(obj);
I have run into this jquery plugin and i quite understand how this works:
$.functionone = function(){
function setOptions(newOptions){
...
}
this.setOptions = setOptions;
}
What i dont understand is what does this actually do? this.setOptions = setOptions can you call a function without parenthesis? What is the relationship between this.setOptions and setOptions by itself?
Functions in JavaScript are objects like (nearly) everything else. When you do this:
this.setOptions = setOptions;
you're not calling the setOptions function, you're just assigning a reference to the function to a property, exactly like setting a property to any other object, like this:
var dt;
dt = new Date();
this.today = dt;
With functions, you'd do this so you can later call the function via the property (which sets up the this value to be the object the property's on, which is handy). It's a bit clearer what's going on if you use a different name for the property than for the function:
function functionName() { ... } // Declares the function
this.propertyName = functionName; // Sets the property
functionName(); // Calls the function (with `this` = the global object ["window", on browsers])
this.propertyName(); // Also calls the function (but with `this` = the object the property's on)
The pattern you identified, declaring a function and then separately setting a reference to it on an object, is frequently used to make sure the resulting function has a name. You can create a function and bind it to a property like this:
this.setOptions = function() {
...
};
...but then the function doesn't have a name (the property does, but not the function), which can be an issue when you're trying to debug because debuggers show you the names of functions in various contexts (call stacks, for instance). If a lot of your functions don't have names, even though the properties referring to them do, it makes debugging difficult. More about anonymous vs. named functions here. (There's also a difference in terms of when the function is instantiated, but going into it here would just complicate things.)
You'd think you could combine things, like this:
this.setOptions = function setOptions() { // <=== DON'T DO THIS
...
};
...but although that mostly works, it triggers a bug in Internet Explorer / JScript (it creates two different functions for that code, which is at best a memory waste and at worst a very subtle and time-wasting problem, as it was in this question).
The function setOptions is only called if you add parenthesis: setOptions(). If you do not add parenthesis, you have a reference to a function. This is just like a normal variable, only it contains a function reference instead of some other value.
If you set this.setOptions = setOptions, you make a function setOptions on the this object, which points to the same function as setOptions. That is, if you call it using this.setOptions(), the referenced function will be called.