I've been using the below, I've seen other code using function() { } and then using the this keyword, what is the difference here, have I actually instantiated an object below?
var MyObj = {
propertyOne: 'a',
Method: (function() {
function MyFuncOne() {}
function MyFuncTwo() {}
return {
MyFuncOne: MyFuncOne,
MyFuncTwo: MyFuncTwo
}
})()
}
Yes, you've instantiated a "singleton" object with two methods.
I believe the outer curly braces are unnecessary, and you could just write:
var MyObj =
(function() {
function MyFuncOne() {}
function MyFuncTwo() {}
return {
MyFuncOne: MyFuncOne,
MyFuncTwo: MyFuncTwo
};
})();
Another way to do it is:
var MyObj =
(function() {
var obj = {};
obj.MyFuncOne = function() {};
obj.MyFuncTwo = function() {};
return obj;
})();
Wrapping your JS in (function() { /* code here */ })() is good practice for preventing variables leaking into global scope. In this case, you're using it to assemble an object.
The only reason I can think of for doing something like this is if you wanted to have some private variables that were shared between the two functions (after changing it to make it legal javascript):
var MyObj = (function() {
var x,y,z; // these will be accessible only to
// the MyFuncOne and MyFuncTwo functions
function MyFuncOneA() {}
function MyFuncTwoA() {}
return {
MyFuncOne: MyFuncOneA,
MyFuncTwo: MyFuncTwoA
}
})();
I had to change your syntax to even make it work because as you had it myObj = {{...}} which isn't very useful and may have not even been valid.
Other than this private, but shared variables notion, it's just extra (and confusing) syntax for declaring two methods on an object which there are much clearer ways to do.
If you weren't using the private variables, then the above example is functionally the same as this much simpler syntax which makes a lot more sense to me:
var MyObj = {
MyFuncOne: function() {},
MyFuncTwo: function() {}
};
Using a function with the this keyword allows you to do some more things than are possible (or, at least, easy) with an object literal (which is what your anonymous function above returns). Most commonly, creating "types".
function Animal () { }
Animal.prototype.speak = function () {
return "";
};
var dog = new Animal();
dog instanceof Animal; // returns true
This also makes inheritance easier:
function Feline () { }
Feline.prototype = new Animal;
Feline.prototype.speak = function () {
return "meow";
};
function Lion () { }
Lion.prototype = new Feline;
Lion.prototype.speak = function () {
return "roar";
};
function Cat () { }
Cat.prototype = new Feline;
var leo = new Lion();
var baxter = new Cat();
leo.speak(); // returns "roar"
baxter.speak(); // returns "meow" - from prototype chain
leo instanceof Feline; // returns true
leo instanceof Animal; // returns true
leo instanceof Cat; // returns false
Demo: http://jsfiddle.net/hEnJf/
Related
I have a javascript object from which I created from a constructor.
var obj = new Obj();
It has several functions but I wish to also use it as follows;
obj();
Obj is defined as:
function obj() {
this.blah = function () {
};
}
How can I do this?
It would be easier to have a function you call which returns an arbitrary function that is treated as both an object and a function. Each one would be unique, and you would not need to use new.
function Obj() {
var ret = function(){
console.log('Hello');
};
ret.blah = function () {
console.log('World');
};
return ret;
}
var obj = Obj();
obj();//Hello
obj.blah();//World
You can create properties on function objects. For instance, if you have the function
function foo() {
return "bar";
}
You can set a property on foo.
foo.baz = 42;
So now you can call foo and get the result "bar", and you can access its baz property.
I think you are looking for 'closure' here.
Try:
function MyObject(/* constructor params */) {
//assign properties to 'this'
return function() {
return this; //<== placeholder implementation
}.bind(this);
}
var obj1 = new MyObject();
Now if you do console.log(obj1) you will see function() { [...] } and you will be able to do obj1() to execute your function.
As a bonus in the code above, I also added this binding in the 'closure' as you will need it in most cases that you are doing anything interesting.
Very simple question, not sure if there are any differences in these ways of creating a javascript "module". I'm hoping somebody can clarify it for me.
A)
var foo = function() {
var bar = function() {
console.log('test');
};
return {
bar: bar
};
};
B)
var foo = function() {
function bar() {
console.log('test');
};
return {
bar: bar
};
};
C)
var foo = function() {
this.bar = function() {
console.log('test');
};
return {
bar: this.bar
};
};
A and B are essentially the same, though there is a very minor difference between A and B due to function/variable hoisting, theoretically you could write code which would work in B but break in A, but practically speaking you'd have to really write weird code to do so.
C will work, but is conceptually wrong. The point of using this.funcName in a function is as a constructor (creating lots of objects using new Thing(). If you aren't using the function as a constructor you shouldn't be using that style as someone scanning the code may mistake the function as a constructor instead of its actual purpose which is a module.
At first, you forgot to execute the function expression: the module pattern is an IEFE. You just create a function.
Your last example is nonsense, it looks like a constructor function when assigning properties to this - and when executed as a IEFE it breaks (and using it with new has undesired effects; an when returning an object it's useless).
For the difference between the first and the second snippet see var functionName = function() {} vs function functionName() {}. In context of the module pattern, the function declaration is recommended.
//Javascript Module Pattern
var person = (function() {
var cname = 'CheapFlight';
return {
name: "Santosh Thakur",
getAge: function() {
return cname;
},
growOlder: function() {
return cname + " Updated";
}
};
}());
person.cname = "New Company"
console.log(person.cname);
console.log(person.name);
console.log(person.getAge());
console.log(person.growOlder());
prefix var before a function makes it a "class"-ish, this means you can make many versions of it. This goes for A
For example:
var hi = function()
{
var bye = function()
{
alert("bye");
}
bye(); // this will call bye
var something = new bye(); // this will create a new instance of bye();
}
var something = new hi();
something();
B means you can only call bar, not make a new instance of it inside the function.
C is the same as bar because of its scope
Class-ish:
var Dog = function( hair, type )
{
this.hair = hair;
this.type = type;
}
var fred = new Dog( "long", "Dalmation" );
alert( fred.hair );
var dave = new Dog( "short", "Poodle" );
alert( dave.type);
This is a class ^
I'm trying to understand how to best use the JavaScript module pattern. My problem is that it seems there's no way to refer to the module from within itself, because this is set to the Window object.
I've got this simple test code:
var Test = function() {
var that = this;
return {
something: function() {
console.info(that);
}
}
}
var test1 = Test();
test1.something();
var test2 = Test();
test2.something();
Both test1 and test2 print a reference to the Window object instead of the module itself.
Any idea how to change it so that I have a valid this inside the module?
If you did
var test1 = new Test()
You could then do
test1.something();
An alternative module structure would be to do something like this:
var myModule = function () {
var obj = {};
obj.something = function () {
return console.log(obj);
};
obj.something2 = function () {
return console.log(obj === this); // true
};
return obj;
};
var test = myModule();
test.something();
test.something2();
Hope this helps
I think you're confusing the JavaScript module pattern with JavaScript constructor functions.
JavaScript constructor functions
If you write a function and call it with the new keyword in front of it, then that function is called as a constructor function.
It will automatically return a new object, that you can refer to within the constructor function using the this keyword.
var Test = function() {
var that = this;
this.something = function () {
console.info(that);
console.info(this);
};
}
var test1 = new Test();
test1.something();
You can return your own object instead, but you wouldn't normally do that in a constructor, you'd just use this instead:
var Test = function() {
var that = this;
return {
something: function () {
console.info(that);
console.info(this);
}
};
}
var test1 = new Test();
test1.something();
If you don't call it with the new keyword in front of it, then it's called like a regular function, meaning any references to this inside of it refer to the object of which the function is a property (which, in the absence of anything else, will be the global object, which in web browsers is window).
var geoff = {
Test: function () {
var that = this;
return {
something: function () {
console.info(that);
}
};
}
};
var test2 = geoff.Test();
var test3 = Test();
Note: with constructor functions, you'd normally define methods on their prototype object, so that the methods don't get unnecessarily redefined for each object you create using the constructor function:
var Test = function() {
this.else = "Something Else"
}
Test.prototype.something = function () {
console.info(this);
}
Test.prototype.somethingElse = function () {
console.info(this.else);
}
var test4 = new Test();
test1.somethingElse() // Logs "Something Else"
(Note that if you return your own object from the constructor function as we mentioned above, then you won't be able to access methods on the prototype object any more.)
Also note that each time you call a constructor function, it returns a new object. You can pass parameters into a constructor function (just like you can with any other function) and use them to customise the object returned:
var Test = function(else) {
this.else = else;
}
Test.prototype.somethingElse = function () {
console.info(this.else);
}
var test1 = new Test("Something else");
var test2 = new Test("Something else again");
test1.somethingElse(); // Logs "Something else"
test2.somethingElse(); // Logs "Something else again"
The problem you have is because this refers to an object, but Test() isn't an object; it's just a function. The object that owns Test() is the Window object (because Test is in the global scope), so therefore that's what you get back when you reference this from within Test().
You may want to try something like this:
var testObj = {
Test : function() {
var that = this;
return {
something: function() {
console.info(that);
}
}
}
}
Now you can call testObj.Test(); and you'll get a reference back to the testObj object.
Hope that clarifies things a bit.
I have the code below, as you can see I'm manually specifying the properties I want to return, I don't care about having private/public functions here, so I'd like a quick & dynamic way to just return all functions in the scope. Is this possible? I've tried a few things but having trouble, it has to be done inside the scope otherwise it can't see the functions.
var MyObj = {
(function() {
function MyFuncOne() {}
function MyFuncTwo() {}
return {
MyFuncOne: MyFuncOne,
MyFuncTwo: MyFuncTwo
}
})()
}
var MyObjTwo = {
(function() {
function MyFuncOne() {}
function MyFuncTwo() {}
return {
MyFuncOne: MyFuncOne,
MyFuncTwo: MyFuncTwo
}
})()
}
Pseudo code of what I want:
function ReturnAllProperties() { //foreach func in scope append to list }
then in the return { ReturnAllProperties(); }
Reading between the lines I think you want a singleton namespace pattern.
var MYNAMESPACE = (function(){
//Private vars
var x, y, z;
var MyFuncOne = function() {.....}
var MyFuncTwo = function() {.....}
return {
//Here expose functions as privileged methods
//You can also expose non-function vars (Numbers, Strings, plain Objects, Arrays) but in general you should expose only methods.
MyFuncOne: MyFuncOne,
MyFuncTwo: MyFuncTwo
};
})();
By convention, namespace members are CAPITALISED.
My colleague has been using "new function()" with a lower case "f" to define new objects in JavaScript. It seems to work well in all major browsers and it also seems to be fairly effective at hiding private variables. Here's an example:
var someObj = new function () {
var inner = 'some value';
this.foo = 'blah';
this.get_inner = function () {
return inner;
};
this.set_inner = function (s) {
inner = s;
};
};
As soon as "this" is used, it becomes a public property of someObj. So someObj.foo, someObj.get_inner() and someObj.set_inner() are all available publicly. In addition, set_inner() and get_inner() are privileged methods, so they have access to "inner" through closures.
However, I haven't seen any reference to this technique anywhere. Even Douglas Crockford's JSLint complains about it:
weird construction. Delete 'new'
We're using this technique in production and it seems to be working well, but I'm a bit anxious about it because it's not documented anywhere. Does anyone know if this is a valid technique?
I've seen that technique before, it's valid, you are using a function expression as if it were a Constructor Function.
But IMHO, you can achieve the same with an auto-invoking function expression, I don't really see the point of using the new operator in that way:
var someObj = (function () {
var instance = {},
inner = 'some value';
instance.foo = 'blah';
instance.get_inner = function () {
return inner;
};
instance.set_inner = function (s) {
inner = s;
};
return instance;
})();
The purpose of the new operator is to create new object instances, setting up the [[Prototype]] internal property, you can see how this is made by the [Construct] internal property.
The above code will produce an equivalent result.
Your code is just similar to the less weird construct
function Foo () {
var inner = 'some value';
this.foo = 'blah';
...
};
var someObj = new Foo;
To clarify some aspects and make Douglas Crockford's JSLint not to complain about your code here are some examples of instantiation:
1. o = new Object(); // normal call of a constructor
2. o = new Object; // accepted call of a constructor
3. var someObj = new (function () {
var inner = 'some value';
this.foo = 'blah';
this.get_inner = function () {
return inner;
};
this.set_inner = function (s) {
inner = s;
};
})(); // normal call of a constructor
4. var someObj = new (function () {
var inner = 'some value';
this.foo = 'blah';
this.get_inner = function () {
return inner;
};
this.set_inner = function (s) {
inner = s;
};
}); // accepted call of a constructor
In example 3. expression in (...) as value is a function/constructor. It looks like this:
new (function (){...})(). So if we omit ending brackets as in example 2, the expression is still a valid constructor call and looks like example 4.
Douglas Crockford's JSLint "thinks" you wanted to assign the function to someObj, not its instance. And after all it's just an warning, not an error.