Self-executing functions [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Difference between (function(){})(); and function(){}();
I am trying to understand a few of the features of JavaScript a little better. In The Definitive JavaScript it says that self-executing functions should have brackets round them like so:
var obj = (function() {
var value = 0;
return {
increment: function(inc) {
value += typeof inc === "number" ? inc : 1;
},
getValue: function() {
return value;
}
}
})();
but in JavaScript - The Good Parts where this example is taken from, it has the above self-executing function without the brackets round, like so:
var obj = function() {
var value = 0;
return {
increment: function(inc) {
value += typeof inc === "number" ? inc : 1;
},
getValue: function() {
return value;
}
}
}();
Both of these examples work for me, but I wanted to ask if there were any differences in functionality that I should be aware of. I hope this isn't too trivial. I just wanted to be sure.
Thanks a lot.
Edit:
As Rob W has pointed out, there is another thread on the subject. This is an excellent blog regarding this issue that was linked to from the other post.

There isn't any difference in this case, but only because it's prefixed with:
var obj = ...
Without that, only the first version is correct, because you need the additional parentheses to allow the interpreter to correctly parse the function as a function expression and not as a function declaration.
You would of course only omit var obj if you only want the function to run (i.e. you want its side effects) but it either returns no value, or you don't care what its return value is.

JavaScript: The Good Parts was written by Doug Crockford, who has updated his example to look like this:
var obj = (function() {
var value = 0;
return {
increment: function(inc) {
value += typeof inc === "number" ? inc : 1;
},
getValue: function() {
return value;
}
};
}());
So the whole expression is within the brackets.
The idea of the outside brackets, which are not required, is that it makes it clear to developers that this is an intentionally self-executed function. So the value is readability.

There aren't, in this example, any functional differences, but I do think the parentheses make it much more readable. How do you know how it is scoped without the parens? Is it hoisted? This is a brilliant thread on the subject.
ASIDE:
JSLint will complain that "function statements are not invocable. Wrap the whole function invocation in parens." I think most browser parsers not running in strict-mode would generally let it pass, but it's better not to rely on that.

Related

Create instance methods in JS that apply function with a dot [duplicate]

I want to extend the number class to have instance functions such as odd and even so I can do something like this:
2.odd() => false
2.even() => true
1.even() => false
1.odd() => true
Extending classes is a good Ruby practise: "Ruby check if even number, float".
Is the same true in JavaScript, or does it cause performance issues or some other problem?
Anyway, I can't extend despite my best efforts:
var NumberInstanceExtensions = {
accuracy: function(){
return 'This is cool ' + this
}
}
$.extend(Number.prototype,NumberInstanceExtensions);
alert( $.type(5) ); //-> number
//alert( 5.accuracy() ); //-> Uncaught SyntaxError: Unexpected token ILLEGAL
http://jsfiddle.net/VLPTb/2/
How can I get this to work? The syntax error makes me think this isn't how JavaScript works on a fundamental level. Is my best bet extending the Math class and doing this instead:
Math.odd(2) => false
Math.even(2) => true
Math.even(1) => false
Math.odd(1) => true
That seems far more inelegant than 2.odd().
I think as long as you understand the side-effects of your "extension" then you're okay. I often modify the String prototype to add an "elipsis" method so I can do things like
"SomeString".elipsis()
But start at the beginning. You're not "extending classes" in JavaScript. JavaScript is a prototype-based language. You can modify prototypes to do what you need.
You won't be able to add a method directly to the number itself. You can, however modify the prototype of the Number object:
Number.prototype.even = function(){
return this.valueOf() % 2 === 0;
}
With this, you won't be able to use the following syntax:
10.even();
But, since you aren't hard-coding stuff, otherwise you wouldn't need this function anyways, you CAN do the following:
var a = 10;
a.even(); //true
I might say that you could consider adding a utilities object to do these things, because modifying primitive prototypes is not always guaranteed to be side-effect free.
This function does not really provide any gain for you. You're checking for odd and even, replacing one line of code with another. Think about the difference:
var a = 10;
var aIsEven = a.even();
vs:
var a = 10;
var aIsEven = a % 2 === 0;
You gain three characters of code, and the second option is less likely to break your "JavaScript".
You can extend natives JS objects by using (for example) Number.prototype.myFn = function(){}.
So you could do :
Math.prototype.odd = function(n){
return n % 2 === 0;
};
Math.prototype.even = function(n){
return n % 2 === 1;
};
And then use it like so :
var two = 2;
console.log(Math.odd(2)); // true
BUT I would strongly advise you against extending natives in JavaScript.
You can read more about it here
EDIT : After trying my code on JSFiddle, it appears the Math object has no prototype, you can read more about it here. The code above won't work !
Instead, you could do :
Math.odd = function(n){
return n % 2 === 0;
};
Math.even = function(n){
return n % 2 === 1;
};
console.log(Math.odd(2)); // true
or :
Number.prototype.odd = function(){
return this % 2 === 0;
};
Number.prototype.even = function(){
return this % 2 === 1;
};
console.log(new Number(2).odd()); // true
I'd like to point out that that is already available in the numbers class.
Just use the boolean methods, odd? and even?
2.odd?
=> false
2.even?
=> true
Hope this helps.
No need to create a new class, it already exists in the numbers class.

Rename builtin prototype method in javascript

I am asked a question today that took me by surprise . I know string.repeat(number) repeat string to the said numbers in javascript. Example.
"Father".repeat(3)
Should print
FatherFatherFather
I was asked to do the same thing but instead using .repeat , i should use my new method like strRepeater in such a way that.
"Father".strRepeater(3)
Should equal
"Father".repeat(3);
Please how do i do this ? Any help would be appreciated.
There are 3 options:
Creating an alias to the prototype:
String.prototype.strRepeater = String.prototype.repeat;
Creating a wrapper around the prototype:
String.prototype.strRepeater = function() {
return this.repeat.apply(this, arguments);
};
Creating your own method:
String.prototype.strRepeater = function(times) {
var res = "";
for (var i = 0; i < times; i++) {
res += this;
}
return res;
};
While the other answers adding to the prototype are completely correct, they're also a bad habit to get into.
If adding anything to a prototype you should be using Object.defineProperty() so it doesn't appear as a member of the method (ie, a for...in loop will show up members, but not when added properly).
While this isn't a requirement for the String prototype, it's always a bad idea to get into bad habits and then wonder why things aren't working correctly later...
So the safe way to add the method is:
Object.defineProperty(String.prototype, "strRepeater", {
value: function(number) {
return this.repeat(number)
}
};
Or to be even more safe:
if (!String.prototype["strRepeater"]) {
Object.defineProperty(String.prototype, "strRepeater", {
value: function(number) {
return this.repeat(number)
}
};
}
On a technical note, this sets it with the defaults of enumerator: false, configurable: false and writeable: false - which translates to "no, you can't list me, delete me, or change me".
Object.defineProperty on MDN.
Try this:
String.prototype.strRepeater = function(number) {
return this.repeat(number)
};
console.log("Father".strRepeater(3));
Explanations:
String.prototype.strRepeater add your function to the String object
this.repeat(number) will call the repeat built-in function with your current string inthis with number as param
return returns the result of .repeat() outside strRepeater()

Most efficient Javascript way to check if an object within an unknown object exists [duplicate]

This question already has answers here:
Test for existence of nested JavaScript object key
(64 answers)
Closed 6 years ago.
This is something that I come up against quite often in Javascript. Let's say I have an object like this:
var acquaintances = {
types: {
friends: {
billy: 6,
jascinta: 44,
john: 91
others: ["Matt", "Phil", "Jenny", "Anna"]
},
coworkers: {
matt: 1
}
}
}
In my theoretical program, all I know for sure is that acquaintances is an object; I have no idea whether acquaintances.types has been set, or whether friends has been set within it.
How can I efficiently check whether acquaintances.types.friends.others exists?
What I would normally do is:
if(acquaintances.types){
if(aquaintances.types.friends){
if(acquaintances.types.friends.others){
// do stuff with the "others" array here
}
}
}
Aside from being laborious, these nested if statements are a bit of a nightmare to manage (in practice my objects have far more levels than this!). But if I were to just try something like if(acquaintances.types.friends.others){) straight off the bat, and types hasn't been set yet, then the program will crash.
What ways does Javascript have of doing this in a neat, manageable way?
An alternative approach is:
((acquaintances.types || {}).friends || {}).others
which is shorter than other solutions, but may or may not thrill you.
You can also build a little helper to make the same idea a tiny bit more palatable:
function maybe(o) { return o || {}; }
Now you can do
maybe(maybe(acquaintances.types).friends).others
If you don't mind writing property names as strings, you could make a little helper:
function maybe(obj) {
return Object.defineProperty(
obj || {},
'get',
{ value: function(prop) { return maybe(obj[prop]); }
);
}
Now you can write
maybe(acquaintances.types').get('friends').others
In ES6, you can do this, albeit clumsily, using destructuring assignment with defaults:
var { types: { friends: { others } = {} } = {} } = acquaintances;
If you want to use this in an expression context, instead of assigning to a variable, in theory you could use argument destructuring:
(({ types: { friends: { others } = {} } = {} }) => others)(acquaintances)
After all is said and done, the standard approach remains
acquaintances.types &&
acquaintances.types.friends &&
acquaintances.types.friends.others
This is why there is an active (?) discussion in the ES6 design groups about a CoffeeScript-like existential operator, but it does not seem to be converging very rapidly.
The and operator is sequential so you can do this without nesting if statements.
if(acquaintances.types && aquaintances.types.friends && acquaintances.types.friends.others){
//acquaintances.types.friends.others exists!
}
It's not nice in JavaScript.
You could add them to one big condition...
if (obj.prop && obj.prop.someOtherProp) { }
...or write a helper function where you pass an object and a string...
var isPropSet = function(object, propPath) {
return !! propPath.split('.')
.reduce(function(object, prop) { return object[prop] || {}; }, object);
};
isPropSet(obj, 'prop.someOtherProp);
...or you could use CoffeeScript and its ? operator...
obj.prop?.someOtherProp
You could also wrap the lookup in a try/catch, but I wouldn't recommend it.
Instead of this:
if(acquaintances.types){
if(aquaintances.types.friends){
if(acquaintances.types.friends.others){
// do stuff with the "others" array here
}
}
}
Try this:
if(acquaintances &&
acquaintances.types &&
acquaintances.types.friends &&
acquaintances.types.friends.others) {
}
Or
acquaintances &&
acquaintances.types &&
acquaintances.types.friends &&
acquaintances.types.friends.others ?
doSomething() : doSomethingElse()

Is there a native way to parse a JavaScript object?

Say I want to access a.b.c.d and I'm not sure if b or c exist.
The 'naive' check would be:
if (a.b && a.b.c && a.b.c.d == 5) doSomething(a.b.c.d);
I thought this over and wrote this function that improves this:
Object.prototype.parse = function (keys, def) {
return keys.split('.').reduce(function (prev, curr) {
if (prev) {
return prev[curr];
}
}, this) || def;
};
And you would use it like this:
var a = {
b: {
c: {
d: 5
}
}
};
console.log(a.parse('b.c.d', 3)); // If b, c or d are undefined return 3
But I'm wondering if I'm missing a better, native way to achieve this instead of having to add this function to projects.
Thanks!
Maybe not quite what you were asking for, but probably as close to 'native' as you can get (a slightly more compact version of split/reduce snippet you provided):
var a = {b:{c:{d:5}}};
("b.c.d").split(".").reduce(function(p,c){return p && p[c];},a); //5
("b.c.e").split(".").reduce(function(p,c){return p && p[c];},a); //undefined
If you were hoping for a solution with a string like "a.b.c.d", then you'll need to use eval (not recoomended) or the object a will need to be global (also not recommended) or the object will need to be a property of another object which is little self-defeating.
The only native way is eval, but I wouldn't recommend it as can be used to execute arbitrary code. This might be OK, but not if your "a.b.c.d" style strings come from untrusted users. I'd stick with your handcrafted solution or use dotty.
var a = {
b: {
c: {
d: 5
}
}
};
console.log(eval("a.b.c.d"));
eval() will throw the same error that the native equivalent would when b or c are not defined so you'll need to wrap with a try {} catch {} block.
I think I have another solution to this problem, I was trying to achieve this for minutes. If you are working on window scope you can use my function to see if the object exist or return a default value.
function parseObj(obj){
try{
return eval(obj);
}catch(e){
return null;
}
}
Usage
alert(parseObj("a.b.c.d"));
I don't know if this is what you looking for but I am sure it will give you an another idea. Have a nice work.

JavaScript differences defining a function

I just bought the newest version of "JavaScript: The Definitive Guide" and already have a question. :D
Are the following lines semantically the same:
var square = function(n){
return n * n;
};
and
function square(n){
return n * n;
}
If yes, what are the advantages/disadvantages of using either of them?
Thanks for your help!
Check this out:
a(); // prints 'A'
function a(){
console.log('A');
};
and this:
b(); // throws error. b is not a function
var b = function() {
console.log('B');
};
Did you notice the difference?
Yes, they do the exact same thing.
The main advantage of the first approach is that it gives you a reference to that function so that you could pass it to another function or attach it to an object if you need to.
Difference is that in the first solution, you can do that :
var square = function(n){
return n * n;
};
// some code
square = function(n) { return n*n*n; }
you have reference to a function. On the other solution, the function is statically declared.
Disclaimer: need JS guru to tell me if I'm wrong =).

Categories