What is the difference, pros/cons (if any) between these constructs?
new function(obj) {
console.log(obj);
}(extObj);
vs
(function(obj) {
console.log(obj);
})(extObj);
The first one returns a reference to the newly constructed instance of your anonymous constructor function (= this).
The second one returns the return value of the anonymous function. Since your function does not have a return statement, it will implicitly return undefined.
Try the following:
var t1 = new function(obj) { console.log(obj); }(extObj);
var t2 = (function(obj) { console.log(obj); })(extObj);
typeof t1 => "object"
typeof t2 => "undefined"
(Btw, t1.constructor will return the original function you created t1 with.)
The difference becomes much clearer, if you add a return statement:
var t1 = new function(obj){ return(obj); }("foo");
var t2 = (function(obj){ return(obj); })("bar");
console.log(t1) => "object"
console.log(t2) => "bar"
IMO, this makes the (function)() much more useful for the everyday usecase - you assign the returnvalue of the execution of this function to the variable which normally would be what you want if you are working with immediately invoked functions. Especially when having more complex things like (pseudocode):
var myNameSpace = (function(){
/* do some private stuff here*/
...
/* expose parts of your anonymous function by returning them */
return{
functionX,
variable1,
variable2
}
}();
Basically you can use an arbitrary unary operator to turn the function declaration into an expression, that is immediately invoked. So you could also write:
!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();
depending on the return statement of your function, these will give different return results. ! - negate the returnvalue +|- evaluate as Number (apply negative sign) ~ apply bitwise not to the return value.
If you're looking at dealing expressly with an immediately-invoked function, then there isn't any real difference between the two, except that the first one will return this inside the function, to the outside world, automatically (that is what new does), and by default if a different return value is not specified (regular functions return undefined).
The rest of the major differences are not really going to matter -- access to the prototype chain is going to be pointless, having the returned this.constructor point to the anonymous function would give you access to caching the anonymous function for use at a later time (like removing it from an event listener, if you somehow managed to stick the enclosed function in... ...that would be a trick in and of itself).
Allowing people to cache your immediately-invoked function as a constructor property of the returned this object might be a security-risk... ...or it might be really useful... ...in very specific scenarios.
Every-day purposes of firing code in-line -- no real difference.
Another difference is that the first invocation creates an extra object. Here I've put the names f and o to denote an objects:
var o = new function f(obj) {
console.log(obj);
}(extObj);
In second case we still create a function object f but we don't create an o:
(function f(obj) {
console.log(obj);
})(extObj);
A closure is still created but that's cheaper than the actual JavaScript object since it doesn't carry the whole prototype chain or other attributes (like hidden class reference) with it,
Related
If i need to write a java script function that takes an argument and returns a function that returns that argument, i can think of following two implementations. Are both of these same ? or there is anything different technically ? Both works and returns the same result.
/*Implemenation 1*/
function myWieredFunc(arg){
var retf=function inner(){
return arg;
};
return retf;
}
/* Implemenation 2 */
function myWieredFunc(arg){
return function(){
return arg;
};
}
To use these:
var f = myWieredFunc(84);
alert(f());
This would be the way to write it
function wrap(arg) {
return function() {
return arg;
};
};
If you wanted to make it more flexible you could allow multiple arguments:
function wrap() {
var args = arguments;
return function() {
return args;
};
};
var later = wrap('hello', 'world');
var result = later();
console.log(result); // ["hello", "world"]
There is no reason for the variable in the code shown - functions are objects are values. As you've shown this means that function-objects can be assigned to a variable which is later evaluated and returned, or returned directly from the Function Expression.
As such, both forms are generally held equivalent and the closure over arg is unaffected.
However, in the first form..
Function.toString and stack-traces will normally include the function name, this makes "named functions", as in the first example sometimes more useful in debugging. Additionally, Firefox will expose function names - e.g. "inner" - through the non-standard Function.name property. (The function name can be specified without the use of the retf variable.)
Two additional bindings are introduced - retf in the outer function and inner in the inner function. These variables could be observed in the the applicable scope when stopping via a break-point - but are not otherwise accessible in the code shown.
They are the same thing, the second is using an "Anonymous" function which just means its a function that is not given a name or assigned to a variable.
(Question 1)
In Flanagan's JS Definitive Guide, he defines the Function method bind() in case it's not available (wasn't available n ECMAScript 3).
It looks like this:
function bind(f, o) {
if (f.bind) return f.bind(o); // Use the bind method, if there is one
else return function() { // Otherwise, bind it like this
return f.apply(o, arguments);
};
}
He illustrates the use of it with an example (which I have modified to change the 3rd line from f.bind(o)):
function f(y) { return this.x + y; } // This function needs to be bound
var o = { x : 1 }; // An object we'll bind to
var g = bind(f, o); // Calling g(x) invokes o.f(x)
g(2) // => 3
When I first saw this, I thought "Wouldn't arguments refer to the arguments variable within the bind function we're defining? But we want the arguments property of the function we eventually apply it to, like g in the example above..."
I verified that his example did indeed work and surmised that the line return f.apply(o, arguments) isn't evaluated until var g = bind(f, o) up above. That is, I thought, when you return a function, are you just returning the source code for that function, no? Until its evaluated? So I tested this theory by trying out a slightly different version of bind:
function mybind2(f, o) {
var arguments = 6;
return function() { // Otherwise, bind it like this
return f.apply(o, arguments);
};
}
If it's simply returning tbe unevaluated function source, there's no way that it stores arguments = 6 when later evaluated, right? And after checking, I still got g(2) => 3. But then I realized -- if it's just returning unevaluated code, how is the o in return f.apply(o, arguments) getting passed?
So I decided that what must be happening is this:
The o and the arguments variables (even when arguments equals 6) are getting passed on to the function. It's just that when the function g is eventually called, the arguments variable is redefined by the interpreter to be the arguments of g (in g(2)) and hence the original value of arguments that I tried to pass on was replaced. But this implies that it was sort of storing the function as text up until then, because otherwise o and arguments would have simply been data in the program, rather than variables that could be overwritten. Is this explanation correct?
(Question 2) Earlier on the same page, he defines the following function which makes use the apply method to trace a function for debugging:
function trace(o, m) {
var original = o[m]; // Remember original method in the closure.
o[m] = function() { // Now define the new method.
console.log(new Date(), "Entering:", m); // Log message.
var result = original.apply(this, arguments); // Invoke original.
console.log(new Date(), "Exiting:", m); // Log message.
return result; // Return result.
};
}
Wouldn't the this here refer to the function that we're defining, rather than the object o? Or are those two things one and the same?
Question 1
For your first question, let's simplify the example so it's clear what being done:
function bind(func, thisArg) {
return function () {
return func.apply(thisArg, arguments);
};
}
What happens here is that a closure is created that allows the access of the original function and the value of this that is passed. The anonymous function returned will keep the original function in its scope, which ends up being like the following:
var func = function () {};
var thisArg = {};
func.apply(thisArg, [/*arguments*/]);
About your issue with arguments, that variable is implicitly defined in the scope of all functions created, so therefore the inner arguments will shadow the outer arguments, making it work as expected.
Question 2
Your problem is to your misunderstanding of the late binding of this -- this is one of the more confusing things about JavaScript to people used to more object-oriented languages that also have their own this keyword. The value of this is only set when it is called, and where it is called defines the value of this when it is called. It is simply the value of the parent object from where it is at the time the function is called, with the exception of cases where the this value is overridden.
For example, see this:
function a() {return this;};
a(); // global object;
var b = {};
b.a = a;
b.a(); // object b
If this was set when the function was defined, calling b.a would result in the global object, not the b object. Let's also simplify what happens with the second function given:
function trace(obj, property) {
var method = obj[property]; // Remember original method in the closure.
obj[property] = function () { // Now define the new method.
console.log(1); // Log message.
// Invoke original method and return its result
return original.apply(this, arguments);
};
}
What happens in this case is that the original method is stored in a closure. Assigning to the object that the method was originally in does not overwrite the method object. Just like a normal method assignment, the principles of the this value still work the same -- it will return the parent object, not the function that you've defined. If you do a simple assignment:
var obj = {};
obj.foo = function () { return this; };
obj.foo(); // obj
It does what was expected, returns the parent object at the time of calling. Placing your code in a nested function makes no difference in this regard.
Some good resources
If you'd like to learn more about writing code in JavaScript, I'd highly recommend taking a look at Fully Understanding the this Keyword by Cody Lindley -- it goes into much more detail about how the this keyword behaves in different contexts and the things you can do with it.
But this implies that it was sort of storing the function as text up until then, because otherwise o and arguments would have simply been data in the program, rather than variables that could be overwritten. Is this explanation correct?
No. this and arguments are just special variables which are implicitly set when a function is executed. They don't adhere to normal "closure rules". The function definition itself is still evaluated immediately and bind returns a function object.
You can easily verify this with:
var g = bind(f, o);
console.log(typeof g);
Here is a simpler example which doesn't involve higher order functions:
var arguments = 42;
function foo() {
console.log(arguments);
}
foo(1, 2);
I think you see that the definition of foo is evaluated like you'd expect. Yet, console.log(arguments) logs [1, 2] and not 42.
Wouldn't the this here refer to the function that we're defining, rather than the object o? Or are those two things one and the same?
this never refers to the function itself (unless you explicitly set it so). The value of this is completely determined by how the function is called. That's why this is often called "the context". The MDN documentation provides extensive information about this.
Reading material:
MDN - this
MDN - arguments
Regarding this code:
var name = "Jaguar";
var car = {
name:"Ferrari",
getName:function(){
return this.name;
}
};
alert((car.getName = car.getName)());
The output is: Jaguar.
Why does this object correspond to Window and not the object contained in the car variable?
It seems that the fact to reassign the object's function to itself leads to lose the assignment of this to the object when the function is called...
I'm trying to guess: Does it exist a kind of mechanism (using variable or other) that keep an eye on the non-reassignement of an object's function so that if that situation happens, this mechanism would prevent the assignement of the this keyword as usual (as being equals to the object)?
The reason is fairly subtle: this in JavaScript is determined entirely by how a function is called. To have this set to car during the call to getName, you have to call getName immediately upon retrieving it from the car object, like this:
car.getName() // or
car["getName"]()
(Or via Function#call or Function#apply, which let you specify the value for this explicitly.)
What you're doing in your example is effectively this:
// Set f to the result of the assignment expression,
// which is a reference to the getName function
var f = (car.getName = car.getName);
// Call it (separately)
f();
...which is different. Functions called in that way get this set to the global object (window, in browsers). (Except in strict mode; in strict mode this would be undefined.)
More (from my anemic blog):
Mythical methods
You must remember this
Does it exist a kind of mechanism (using variable or other) that keep an eye on the non-reassignement of an object's function so that if that situation happens, this mechanism would prevent the assignement of the this keyword as usual (as being equals to the object)?
I'm not entirely sure I follow that question, but if you want to have a function that always has a preset this value, then yes, there are a couple of ways to do that.
One is to use the new ES5 function bind:
var name = "Jaguar";
var car = {
name: "Ferrari"
};
car.getName = function(){
return this.name;
}.bind(car);
alert((car.getName = car.getName)()); // "Ferrari"
bind returns a function that always has this set to the argument you give it.
The other way is to use a closure. And in fact, you can create a bind-like function in ES3 very easily:
function pseudoBind(func, thisArg) {
return function() {
return func.apply(thisArg, arguments);
};
}
That doesn't do everything bind does, but it does the this part. Then you'd have:
var name = "Jaguar";
var car = {
name: "Ferrari"
};
car.getName = pseudoBind(function(){
return this.name;
}, car);
alert((car.getName = car.getName)()); // "Ferrari"
More on closures (again from the blog):
Closures are not complicated
In a future spec, we'll be getting a declarative way of creating functions that have a preset this value (so-called "arrow functions" because the syntax for them involves uses => rather than the function keyword).
Aaah, this resolution...Lets take a gander.
var toy = {
log : function () { console.log(this); }
};
toy.log() //logs the toy object
So far, it seems like this resolution is static: Wherever the method was defined in, that's its this value.
But! What if we do this:
var sneakyBastard = toy.log;
sneakyBastard(); //logs Window
this is bound to the object it's called with. In the case of toy.log, you called log in the context of the toy object. But, sneakyBastard has no set context, so it's as if you've called window.sneakyBastard.
Now let's take a goose (goose? gander? no...) at your expression:
(car.getName = car.getName)()
...and what does an assignment return? The assigned value, in this case, a function, car.getName. We can break this expression into two:
var returnedValue = (car.getName = car.getName);
returnedValue();
...and from here it's obvious.
Instead of calling getName from the context of an object, you're calling it from the context of the return result of the grouping operator (which in this case there's no context).
In JavaScript, when there's no clear context defined, a default is used. The default is...
the global object when in strict mode
undefined when not in strict mode
You have put your function call parenthesis (()) so they call the result of the expression (car.getName = car.getName) (which is the value (a function) assigned to car.getName)
Today I saw a JavaScript syntax (when invoking a function) that is unfamiliar to me. It was like:
def('Person') ({
init: function(name) {this.name=name;}
,speak: function(text) {alert(text || 'Hi, my name is ' + this.name);}
});
, and
def('Ninja') << Person ({
kick: function() {this.speak('I kick u!');}
});
1: What happens with the object within the parentheses in the first example? It is handled by the def function somehow, but I don't understand what is going on here (see the def function below). Where does the object go?
2: About the same thing again, but a use of the << operator that I never seen (I think!). What's that all about?
The code is from http://gist.github.com/474994, where Joe Dalton has made a small JavaScript-OO-inheritance thing (it is apparently a fork of someone else's work, but quite thoroughly rewritten, as it seems). Maybe you want to check it out there for the stuff referenced by the def function, which I give you here:
function def(klassName, context) {
context || (context = global);
// Create class on given context (defaults to global object)
var Klass =
context[klassName] = function Klass() {
// Called as a constructor
if (this != context) {
// Allow the init method to return a different class/object
return this.init && this.init.apply(this, arguments);
}
// Called as a method
// defer setup of superclass and plugins
deferred._super = Klass;
deferred._plugins = arguments[0] || { };
};
// Add static helper method
Klass.addPlugins = addPlugins;
// Called as function when not
// inheriting from a superclass
deferred = function(plugins) {
return Klass.addPlugins(plugins);
};
// valueOf is called to set up
// inheritance from a superclass
deferred.valueOf = function() {
var Superclass = deferred._super;
if (!Superclass)
return Klass;
Subclass.prototype = Superclass.prototype;
Klass.prototype = new Subclass;
Klass.superclass = Superclass;
Klass.prototype.constructor = Klass;
return Klass.addPlugins(deferred._plugins);
};
return deferred;
}
1: The call def('Person') returns a function, which is called with the object as parameter. It's the same principle as:
function x() {
return function(y) { alert(y); }
}
x()('Hello world!');
2: The << operator is the left shift operator. It shifts an integer value a specific number of bits to the left. I haven't found any reference for any other use for it, and there is no operator overloading in Javascript, so I can't make any sense out of using it on a function. So far it looks like a typo to me.
Edit:
As Tim explained, the shift operator is just used to induce a call to the valueOf method. It works like an overload of all operators, taking over the original purpose and doing something completely different.
Wow, it was convoluted enough for my tiny brain to understand, but I feel a lot better now knowing exactly how it works :) Thanks to #Tim for pointing out the valueOf() trick.
The general case of creating a "class" using:
def ("ClassName") ({
init: function() { .. },
foo: function() { .. }
});
is trivial, as the first call to def returns a function that accepts an object, and copies the properties of the passed in object, to the prototype of ClassName.
The more interesting case of using << to subclass relies on the evaluation order of the expression, as well as the attempted coercing of any object to a value by the implicit call to valueOf(). The underlying trick is basically a shared variable that records the super class and the properties to be applied to it. The expression,
def("ClassName") << ParentClass({ .. })
will be evaluated as follows:
def("ClassName") is called, and creates a global object ClassName and returns its constructor function. Let's call this returned object - initializeMeLater.
ParentClass(..) is called which stores the reference to ParentClass, and the passed in object/properties in a shared variable.
initializeMeLater.valueOf() is called, which gets the reference to the parent class, and the properties from that shared variable, and sets up the prototypes.
valueOf is called on the return value from step 2 which is useless and has no effect, as we have already setup the superclass relationship in step 3.
The code is trying to emulate Ruby syntax for creating subclasses which goes like:
class Child < Parent
def someMethod
...
end
end
I've written (in JavaScript) an interactive read-eval-print-loop that is encapsulated
within an object. However, I recently noticed that toplevel function definitions specified to the interpreter do not appear to be 'remembered' by the interpreter. After some diagnostic work, I've reduced the core problem to this:
var evaler = {
eval: function (str)
{
return eval(str);
},
};
eval("function t1() { return 1; }"); // GOOD
evaler.eval("function t2() { return 2; }"); // FAIL
At this point, I am hoping that the following two statements wil work as expected:
print(t1()); // => Results in 1 (This works)
print(t2()); // => Results in 2 (this fails with an error that t2 is undefined.)
What I get instead is the expected value for the t1 line, and the t2 line fails with an error that t2 is unbound.
IOW: After running this script, I have a definition for t1, and no defintion for t2. The act of calling eval from within evaler is sufficiently different from the toplevel call that the global definition does not get recorded. What does happen is that the call to
evaler.eval returns a function object, so I'm presuming that t2 is being defined and stored in some other set of bindings that I don't have access to. (It's not defined as a member in evaler.)
Is there any easy fix for this? I've tried all sorts of fixes, and haven't stumbled upon one that works. (Most of what I've done has centered around putting the call to eval in an anonymous function, and altering the way that's called, chainging __parent__, etc.)
Any thoughts on how to fix this?
Here's the result of a bit more investigation:
tl;dr: Rhino adds an intermediate scope to the scope chain when calling a method on an instance. t2 is being defined in this intermediate scope, which is immediately discarded. #Matt: Your 'hacky' approach might well be the best way to solve this.
I'm still doing some work on the root cause, but thanks to some quality time with jdb, I now have more understanding of what's happening. As has been discussed, a function statement like function t1() { return 42; } does two things.
It creates an anonymous instance of a function object, like you'd get with the expression function() { return 42; }
It binds that anonymous function to the current top scope with the name t1.
My initial question is about why I'm not seeing the second of these things happen when I call eval from within a method of an object.
The code that actually performs the binding in Rhino appears to be in the function org.mozilla.javascript.ScriptRuntime.initFunction.
if (type == FunctionNode.FUNCTION_STATEMENT) {
....
scope.put(name, scope, function);
For the t1 case above, scope is what I've set to be my top-level scope. This is where I want my toplevel functions defined, so this is an expected result:
main[1] print function.getFunctionName()
function.getFunctionName() = "t1"
main[1] print scope
scope = "com.me.testprogram.Main#24148662"
However, in the t2 case, scope is something else entirely:
main[1] print function.getFunctionName()
function.getFunctionName() = "t2"
main[1] print scope
scope = "org.mozilla.javascript.NativeCall#23abcc03"
And it's the parent scope of this NativeCall that is my expected toplevel scope:
main[1] print scope.getParentScope()
scope.getParentScope() = "com.me.testprogram.Main#24148662"
This is more or less what I was afraid of when I wrote this above: " In the direct eval case, t2 is being bound in the global environment. In the evaler case, it's being bound 'elsewhere'" In this case, 'elsewhere' turns out to be the instance of NativeCall... the t2 function gets created, bound to a t2 variable in the NativeCall, and the NativeCall goes away when the call to evaler.eval returns.
And this is where things get a bit fuzzy... I haven't done as much analysis as I'd like, but my current working theory is that the NativeCall scope is needed to ensure that this points to evaler when execution in the call to evaler.eval. (Backing up the stack frame a bit, the NativeCall gets added to the scope chain by Interpreter.initFrame when the function 'needs activation' and has a non-zero function type. I'm assuming that these things are true for simple function invocations only, but haven't traced upstream enough to know for sure. Maybe tomorrow.)
Your code actually is not failing at all. The eval is returning a function which you never invoke.
print(evaler.eval("function t2() { return 2; }")()); // prints 2
To spell it out a bit more:
x = evaler.eval("function t2() { return 2; }"); // this returns a function
y = x(); // this invokes it, and saves the return value
print(y); // this prints the result
EDIT
In response to:
Is there another way to create an interactive read-eval-print-loop than to use eval?
Since you're using Rhino.. I guess you could call Rhino with a java Process object to read a file with js?
Let's say I have this file:
test.js
function tf2() {
return 2;
}
print(tf2());
Then I could run this code, which calls Rhino to evaluate that file:
process = java.lang.Runtime.getRuntime().exec('java -jar js.jar test.js');
result = java.io.BufferedReader(java.io.InputStreamReader(process.getInputStream()));
print(result.readLine()); // prints 2, believe it or not
So you could take this a step further by WRITING some code to eval to a file, THEN calling the above code ...
Yes, it's ridiculous.
The problem you are running into is that JavaScript uses function level scoping.
When you call eval() from within the eval function you have defined, it is probably creating the function t2() in the scope of that eval: function(str) {} function.
You could use evaler.eval('global.t2 = function() { return 2; }'); t2();
You could also do something like this though:
t2 = evaler.eval("function t2() { return 2; }");
t2();
Or....
var someFunc = evaler.eval("function t2() { return 2; }");
// if we got a "named" function, lets drop it into our namespace:
if (someFunc.name) this[someFunc.name] = someFunc;
// now lets try calling it?
t2();
// returns 2
Even one step further:
var evaler = (function(global){
return {
eval: function (str)
{
var ret = eval(str);
if (ret.name) global[ret.name] = ret;
return ret;
}
};
})(this);
evaler.eval('function t2() { return 2; }');
t2(); // returns 2
With the DOM you could get around this function-level scoping issue by injecting "root level" script code instead of using eval(). You would create a <script> tag, set its text to the code you want to evaluate, and append it to the DOM somewhere.
Is it possible that your function name "eval" is colliding with the eval function itself? Try this:
var evaler = {
evalit: function (str)
{
return window.eval(str);
},
};
eval("function t1() { return 1; }");
evaler.evalit("function t2() { return 2; }");
Edit
I modified to use #Matt's suggestion and tested. This works as intended.
Is it good? I frown on eval, personally. But it works.
I think this statement:
evaler.eval("function t2() { return 2; }");
does not declare function t2, it just returns Function object (it's not function declaration, it's function operator), as it's used inside an expression.
As evaluation happens inside function, scope of newly created function is limited to evaler.eval scope (i.e. you can use t2 function only from evaler.eval function):
js> function foo () {
eval ("function baz() { return 'baz'; }");
print (baz);
}
js> foo ();
function baz() {
return "baz";
}
js> print(baz);
typein:36: ReferenceError: baz is not defined
https://dev.mozilla.jp/localmdc/developer.mozilla.org/en/core_javascript_1.5_reference/operators/special_operators/function_operator.html
https://dev.mozilla.jp/localmdc/developer.mozilla.org/en/core_javascript_1.5_reference/statements/function.html
I got this answer from the Rhino mailing list, and it appears to work.
var window = this;
var evaler = {
eval : function (str) {
eval.call(window, str);
}
};
The key is that call explicitly sets this, and this gets t2 defined in the proper spot.