difference between function() {} and new function() {} [duplicate] - javascript

This question already has answers here:
`new function()` with lower case "f" in JavaScript
(3 answers)
Closed 9 years ago.
in this question, I don't want to ask "Function", i want to ask "function" puzzle
<script type="text/javascript">
var test = function() {
alert('a');
};
var test1 = new function() {
alert('b');
};
</script>
why it will pop up the "b"?

Function (p1, p2, … , pn, body)
When the Function function is called with some arguments p1, p2, … , pn, body (where n might be 0, that is, there are no “p” arguments, and where body might also not be provided), the following steps are taken:
Create and return a new Function object as if the standard built-in constructor Function was used in a new expression with the same arguments.
check :Is JavaScript's "new" keyword considered harmful?

new function will execute the function, you can use an IIFE (Immediately- Invoked Function Expression) as well:
var test1 = (function() {
alert('b');
}());

new is used for the Factory pattern in Javascript.
It creates and returns an object by executing a constructor function. In your case it doesn't make sense to use new.

Functions which are built to be used as constructors don't require parens, if you aren't passing any arguments:
var Person = function () { this.is_alive = true; },
bob = new Person;
bob.is_alive;
...but any function can be called as a constructor, whether you're using the returned object or not...
new function () { console.log("Bob"); }
this won't save the function anywhere -- it will run it, in place, instantly.

See What is the 'new' keyword in JavaScript? for a basic description of the new keyword.
Essentially, you are calling the constructor to a new object. Let me show you.
var Animal = function(name) {
alert("Animal Created: " + name);
}
jaguar = new Animal("Cool");
The only difference from that and what you did was declare the function in the same line as defining the new object:
jaguar = new function(name) {
alert("Animal Created: " + name);
}
That's why the "b" was printed out.

Related

how does "new" work with classes in javascript?

How does the new work differently in the 2 examples below? I see that the 2nd example is replacing the annoymous funciton with a variable, but in the second one, the function/class "Person" is actually being called. Does it make any difference if it's being called or not? I tried it without the calling and it still worked. So that led me to believe that new is actually calling the function and setting up this to be assigned to the instance variable.
var person = new function() {
this.setName = function(name) {
this.name = name;
}
this.sayHi = function() {
return "Hi, my name is " + this.name;
}
}
person.setName("Rafael");
console.log(person.sayHi()); // Hi, my name is Rafael
var Person = function() {
this.setName = function(name) {
this.name = name;
}
this.sayHi = function() {
return "Hi, my name is " + this.name;
}
}
var personTwo = new Person()
personTwo.setName("Rafael");
console.log(personTwo.sayHi()); // Hi, my name is Rafael
There would be almost no difference between these two examples, if it was a simple function like this:
(function() { console.log("IIFE"); })();
// or
var f = function() { console.log("Function"); };
f();
You just store your function in a variable, and then call it.
However, it makes a little difference, since it is related to JS OOP mechanisms. In the first case you get Object instance, and in the second you get Person instance. This makes difference in OOP sense.
var person = new function() { };
console.log("Is instance of: " + person.constructor.name);
console.log("There is no way to check instanceof in this case");
var Person = function() { };
var person = new Person();
console.log("Is instance of: " + person.constructor.name);
console.log(person instanceof Person);
In general, new and classes are supposed to be used as in the second case in order to enable the full functionality of JS OOP. There is absolutely no sense or/and advantage in using anonymous class constructor.
Whether or not it is assigned into a variable: does not matter. It is completely parallel to this example:
var x = 1;
console.log(x);
and
console.log(1);
Whether it needs to be called or not: A function with the new operator is always being called, but with new, parentheses are optional when no parameters are passed: new Person() is equivalent to new Person, but new Person("Joe") cannot be done differently.
In the second example, you are passing to the new operator the exact same function. You simply are using a reference (logically stored in a variable) instead of writing literal function just in place.
So, your second example is the same as:
var personTwo = new (function() {
[...]
})()
[...]
Which, in fact, is much the same as the first one:
var person = new (function() {
[...]
})
[...]
NOTE that the parentheses surrounding the function are absolutely optional in this case. You could be placed there seven if you like: (((((((function(){[...]}))))))).
The point here is that when you say «in the second one, the function/class "Person" is actually being called» you are WRONG there: That function, which acts as a constructor isn't being called by you. You are simply passing it as a parameter (the constructor function) of the new operator which is, in fact, who is actually calling the constructor with the rest of parameters you provided, if any.
See new syntax documentation:
new constructor[([arguments])]
The constructor is the function you pass to the new operator and the parameters are specified between parentheses. But they are fully optional (including the parentheses itself).
This is why new constructor; without parentheses works.
To be clear: What you thought happens (but not) would be written as:
var person = new ((function(){...})()) ();
...or, more verbosely:
var person = new (
(function(){ // Constructor builder.
[...]
return function(){...}; // Actual constructor.
})() // Constructor builder call
//v-- Parentheses to force builder to be called.
) (); // <-- Parameters (if any) passed to the constructor.

How is 'Function' (not 'function') defined in Javascript?

I happened to notice Javascript also supports the Function keyword just as in ActionScript. Since both are derived from ECMA Script, existence of such similarities is a common knowledge. But I was curious on what Function represents in case of Javascript, if not a Class(as in as3).
In JS,
var func = new Function(); or var func = new Function;
Assigns a function called 'anonymous' to the variable 'func'.
Could it be simply a method to implement the actual 'function' in an Object oriented way..
Since most browsers(ff, ie & chrome) seem to implement it in the same way, is it addressed in the spec?
Function is the "class" all function extend from. All functions are really Function objects.
(function(){}) instanceof Function === true
You can also use new Function to make a function from a string (like eval).
var func = new Function('x,y', 'return x+y;')
"Every function in JavaScript is actually a Function object." MDN Documentation.
function myFunc(a, b) {
console.log( 'test' );
}
is essentially equal to
var myFunc = new Function('a', 'b', 'console.log( "test" )');
There are however some differences between to two ways of declaring a function. Read the doc!
1 way:
var Person = function() {
this.name;
this.age;
}
var p1 = new Person();
2nd way:
function Person() {
this.name;
this.age;
}
var p1 = new Person();

Call javascript dynamic method in object

If I create a Class with two method like following:
var Car = function() {}
Car.prototype = {
run: function() {
alert('run');
},
stop: function() {
alert('stop');
}
}
And when the DOM is ready will call test() method,
and this test() method will create a instance of Car and call the method of Car
$(document).ready(function() {
test("run");
});
function test(method) {
var instance = new Car();
// call instance.run()
}
I know I have to use apply() method,
but I have tried lots of times and failed
So, how can I use apply() method in Object?
An object in javascript is an associative array, so you can use the [] operator to address by string any member of the object, functions as well.
function test(method) {
var instance = new Car();
instance[method]();
}
this will allow to call a function by name over the object Car.
See it working on JsFiddle.
The context inside the called method will properly point to the newly created Car instance without any additional effort, that I guess is what you want. Using apply or call is generally used when you need to change the default 'this' value to something else.
I know I have to use apply() method,
You don't. Uncomment the instance.run() code, call the test() method and it works.
demo: http://jsfiddle.net/JkAnb/
how can I use apply() method in Object
It depends on what you want to achieve. There is documentation at MDN.
perhaps you want to call
instance.method()
call dynamically i.e. based on value passed run/stop. You can try this -
instance[method].call(instance)
or
instance[method].apply(instance)
where instance is passed as scope param which is scope of the function to be called (value of "this" inside function).
Why do You need classes in an (object based) functional language?
Your intent is bit unclear. What is the implied type of the argument 'method' in Your test function?
I assume it is a method name. In any case code bellow might help.
/* prefer this class pattern */
var Car = (function () {
"use strict";
Car.prototype = {
name : undefined ,
run: function () {
return name_ + ":: run";
},
stop: function () {
return name_ + ":: stop";
}
};
/* constructor */
function Car(name) {
name_ = name;
}
return Car;
})();
function printer(msg_) {
document.body.innerHTML += msg_ + "<br/>";
}
function test(car_, method_name_1, method_name_2) {
printer(car_[method_name_1]());
printer(car_[method_name_2]());
}
test( new Car("BMW"), "run", "stop");
test( new Car("Lada"), "run", "stop")
in addition, you could also use the eval function:
var instance = new Car();
eval('instance.'+method+'();');
though Felice Pollano's way is far neater imo.
http://jsfiddle.net/VZdXb/

Is it possible to call function.apply without changing the context?

In some Javascript code (node.js specifically), I need to call a function with an unknown set of arguments without changing the context. For example:
function fn() {
var args = Array.prototype.slice.call(arguments);
otherFn.apply(this, args);
}
The problem in the above is that when I call apply, I'm change the context by passing this as the first argument. I'd like to pass args to the function being called without changing the context of the function being called. I essentially want to do this:
function fn() {
var args = Array.prototype.slice.call(arguments);
otherFn.apply(<otherFn's original context>, args);
}
Edit: Adding more detail regarding my specific question. I am creating a Client class that contains a socket (socket.io) object among other info pertaining to a connection. I am exposing the socket's event listeners via the client object itself.
class Client
constructor: (socket) ->
#socket = socket
#avatar = socket.handshake.avatar
#listeners = {}
addListener: (name, handler) ->
#listeners[name] ||= {}
#listeners[name][handler.clientListenerId] = wrapper = =>
# append client object as the first argument before passing to handler
args = Array.prototype.slice.call(arguments)
args.unshift(this)
handler.apply(this, args) # <---- HANDLER'S CONTEXT IS CHANGING HERE :(
#socket.addListener(name, wrapper)
removeListener: (name, handler) ->
try
obj = #listeners[name]
#socket.removeListener(obj[handler.clientListenerId])
delete obj[handler.clientListenerId]
Note that clientListenerId is a custom unique identifier property that is essentially the same as the answer found here.
If I understand you correctly:
changes context
| n | y |
accepts array n | func() | func.call() |
of arguments y | ???????? | func.apply() |
PHP has a function for this, call_user_func_array. Unfortunately, JavaScript is lacking in this regard. It looks like you simulate this behavior using eval().
Function.prototype.invoke = function(args) {
var i, code = 'this(';
for (i=0; i<args.length; i++) {
if (i) { code += ',' }
code += 'args[' + i + ']';
}
eval(code + ');');
}
Yes, I know. Nobody likes eval(). It's slow and dangerous. However, in this situation you probably don't have to worry about cross-site scripting, at least, as all variables are contained within the function. Really, it's too bad that JavaScript doesn't have a native function for this, but I suppose that it's for situations like this that we have eval.
Proof that it works:
function showArgs() {
for (x in arguments) {console.log(arguments[x]);}
}
showArgs.invoke(['foo',/bar/g]);
showArgs.invoke([window,[1,2,3]]);
Firefox console output:
--
[12:31:05.778] "foo"
[12:31:05.778] [object RegExp]
[12:31:05.778] [object Window]
[12:31:05.778] [object Array]
Simply put, just assign the this to what you want it to be, which is otherFn:
function fn() {
var args = Array.prototype.slice.call(arguments);
otherFn.apply(otherFn, args);
}
'this' is a reference to your function's context. That's really the point.
If you mean to call it in the context of a different object like this:
otherObj.otherFn(args)
then simply substitute that object in for the context:
otherObj.otherFn.apply(otherObj, args);
That should be it.
If you bind the function to an object and you use everywhere the bound function, you can call apply with null, but still get the correct context
var Person = function(name){
this.name = name;
}
Person.prototype.printName = function(){
console.log("Name: " + this.name);
}
var bob = new Person("Bob");
bob.printName.apply(null); //window.name
bob.printName.bind(bob).apply(null); //"Bob"
One way that you can work around the change of context that can happen in JavaScript when functions are called, is to use methods that are part of the object's constructor if you need them to be able to operate in a context where this is not going to mean the parent object, by effectively creating a local private variable to store the original this identifier.
I concede that - like most discussions of scope in JavaScript - this is not entirely clear, so here is an example of how I have done this:
function CounterType()
{
var counter=1;
var self=this; // 'self' will now be visible to all
var incrementCount = function()
{
// it doesn't matter that 'this' has changed because 'self' now points to CounterType()
self.counter++;
};
}
function SecondaryType()
{
var myCounter = new CounterType();
console.log("First Counter : "+myCounter.counter); // 0
myCounter.incrementCount.apply(this);
console.log("Second Counter: "+myCounter.counter); // 1
}
These days you can use rest parameters:
function fn(...args) {
otherFn(...args);
}
The only downside is, if you want to use some specific params in fn, you have to extract it from args:
function fn(...args) {
let importantParam = args[2]; //third param
// ...
otherFn(...args);
}
Here's an example to try (ES next version to keep it short):
// a one-line "sum any number of arguments" function
const sum = (...args) => args.reduce((sum, value) => sum + value);
// a "proxy" function to test:
var pass = (...args) => sum(...args);
console.log(pass(1, 2, 15));
I'm not going to accept this as an answer, as I'm still hoping for something more suitable. But here's the approach I'm using right now based upon the feedback on this question so far.
For any class that will be calling Client.prototype.addListener or Client.prototype.removeListener, I did added the following code to their constructor:
class ExampleClass
constructor: ->
# ...
for name, fn of this
this[name] = fn.bind(this) if typeof(fn) == 'function'
message: (recipient, body) ->
# ...
broadcast: (body) ->
# ...
In the above example, message and broadcast will always be bound to the new ExampleClass prototype object when it's instantiated, allowing the addListener code in my original question to work.
I'm sure some of you are wondering why I didn't just do something like the following:
example = new ExampleClass
client.addListener('message', example.bind(example))
# ...
client.removeListener('message', example.bind(example))
The problem is that every time .bind( ) is called, it's a new object. So that means that the following is true:
example.bind(example) != example.bind(example)
As such, the removeListener would never work successfully, thus my binding the method once when the object is instantiated.
Since you seem to want to be using the bind function as it is defined in Javascript 1.8.5, and be able to retrieve the original this object you pass the bind function, I recommend redefining the Function.prototype.bind function:
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
/** here's the additional code **/
fBound.getContext = function() {
return oThis;
};
/**/
return fBound;
};
Now you can retrieve the original context that you called the bind function with:
function A() {
return this.foo+' '+this.bar;
}
var HelloWorld = A.bind({
foo: 'hello',
bar: 'world',
});
HelloWorld(); // returns "hello world";
HelloWorld.getContext(); // returns {foo:"hello", bar:"world"};
I was just reminded of this question after a long time. Looking back now, I think what I was really trying to accomplish here was something similar to how the React library works with its automatic binding.
Essentially, each function is a wrapped bound function being called:
function SomeClass() {
};
SomeClass.prototype.whoami = function () {
return this;
};
SomeClass.createInstance = function () {
var obj = new SomeClass();
for (var fn in obj) {
if (typeof obj[fn] == 'function') {
var original = obj[fn];
obj[fn] = function () {
return original.apply(obj, arguments);
};
}
}
return obj;
};
var instance = SomeClass.createInstance();
instance.whoami() == instance; // true
instance.whoami.apply(null) == instance; // true
Just push properties directly to the function's object and call it with it's own "context".
function otherFn() {
console.log(this.foo+' '+this.bar); // prints: "hello world" when called from rootFn()
}
otherFn.foo = 'hello';
otherFn.bar = 'world';
function rootFn() {
// by the way, unless you are removing or adding elements to 'arguments',
// just pass the arguments object directly instead of casting it to Array
otherFn.apply(otherFn, arguments);
}

Javascript and prototypal Inheritance

Is there a difference between these two statements in Javascript?
function p() {
this.do = function(){alert('cool')};
}
and this one?:
function p(){};
p.prototype.do = function(){alert('cool')};
One more thing, why can't you do:
function p(){};
p.do = function(){alert('cool')};
Thank you so much!
Given your first two examples, assuming you call p() as a constructor:
on the surface, they will behave identically
But the first example...
will create a new, identical function for each object created from new p()
[that function] will have access to the local variables and parameters inside the p() constructor
// p.prototype = {}
new p(); // { do:function(){alert('cool')}; } ------^
new p(); // { do:function(){alert('cool')}; } ------^
new p(); // { do:function(){alert('cool')}; } ------^
and the second example...
will share the function placed on the prototype between all the objects created from new p()
[that function] will not have access to private variables/parameters in the constructor
//p.prototype = {do:function(){alert('cool')};}
new p(); // {} ------^
new p(); // {} ------^
new p(); // {} ------^
The third example does not work because in JavaScript, a function is an object, so all you're doing it placing a new property on that object. It has no effect on the invocation of that function.
Functionally speaking, they are the same.
The first one defines a function for each object var o = new p() so it is not optimal from a memory viewpoint.
You can do what you're showing in your 3rd example, but you're not going to accomplish what you think:
function p(){};
p.do = function(){alert('cool')};
p.do(); // this will work
var o = new p(); // This won't have the 'do' function because that's not how it works in javascript.

Categories

Resources