Skip to content

Commit 2089cc9

Browse files
committed
initial javascript gotchas
1 parent 3bc7827 commit 2089cc9

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
---
2+
layout: post
3+
title: "JavaScript gotchas"
4+
author: NodeKC
5+
tags:
6+
---
7+
8+
# JavaScript gotchas
9+
10+
JavaScript is a language that many developers are familiar with but lack a deep understanding. The language lends itself to new programmers because its simple syntax. Many of the core fundamentals can be avoided provided that the application being built is sufficiently simple. The goal of this lab is to give you a better understanding of some core concepts and things to look for with JavaScript.
11+
12+
## What's ```this```?
13+
14+
Have a look at this snippet and pay special attention to the use of the keyword ```this```.
15+
16+
{% highlight javascript %}
17+
var obj = {
18+
doSomething: function () {
19+
this.a = "bob";
20+
21+
function doAnotherThing () {
22+
console.log("Name: " + this.a);
23+
};
24+
25+
console.log("Name: " + this.a);
26+
doAnotherThing();
27+
}
28+
};
29+
30+
//What does this print?
31+
obj.doSomething();
32+
{% endhighlight %}
33+
34+
Those unfamiliar with how ```this``` is handled may think the call to ```obj.doSomething``` might think the output of running the above snippet is this:
35+
36+
```
37+
Name: bob
38+
Name: bob
39+
```
40+
41+
What's actually output is this:
42+
43+
```
44+
Name: bob
45+
Name: undefined
46+
```
47+
48+
Here's another example and then we'll explain what's going on.
49+
50+
{% highlight javascript %}
51+
function Adder (a) {
52+
this.a = a;
53+
};
54+
55+
Adder.prototype.addAsync = function (b) {
56+
setTimeout(function () {
57+
console.log(this.a + b);
58+
}, 10);
59+
};
60+
61+
var r = new Adder(5);
62+
r.addAsync(10);
63+
64+
{% endhighlight %}
65+
66+
This example is supposed to add two numbers together after 10 milliseconds. What's the output of this example? Some may think it would print 15, the result of 5 + 10. The correct answer is ```NaN```. Why? The answer lies in the value of ```this```.
67+
68+
If there's anything you'll walk away from after this lab I hope you'll no longer write bugs that involve ```this```.
69+
70+
The value of ```this``` is the object that a function is defined on. Inner functions or function calls that aren't a part of the object will have the default object set to ```this```. The default object in browsers is ```window``` and in Node.js is ```process```.
71+
72+
{% highlight javascript %}
73+
var obj = { a: "Example" };
74+
75+
var printer = function () {
76+
console.log(this);
77+
console.log(this.a);
78+
};
79+
80+
obj.p = printer;
81+
82+
printer() // => undefined
83+
84+
obj.p() // => Example
85+
{% endhighlight %}
86+
87+
Notice how the value of the call to ```printer``` that wasn't attached to an object was ```undefined```. Once we set the property p to the printer function and invoke it you'll see that this now refers to the object defined. When an object is created from a constructor function using the new keyword, a brand new object is set to ```this```. For example:
88+
89+
{% highlight javascript %}
90+
var ctor = function (a) {
91+
this.a = a;
92+
};
93+
94+
ctor.prototype.print = function () {
95+
console.log(this.a);
96+
};
97+
98+
var o1 = new ctor('test1');
99+
o1.print(); // => test1
100+
101+
var o2 = new ctor('test2');
102+
o2.print(); // => test2
103+
{% endhighlight %}
104+
105+
So, you've seen the default behavior of how JavaScript handles the ```this``` keyword. The value of ```this``` can be controlled in a function call by using two methods available on Function.prototype ```apply``` and ```call```. Both of these methods invoke the function they're called on with ```this``` as set to the first argument. Here's an example:
106+
107+
{% highlight javascript %}
108+
var obj = { a: "Example" };
109+
110+
//Note this is not defined on obj
111+
var printer = function () {
112+
console.log(this.a);
113+
};
114+
115+
printer.apply(obj); // => "Example"
116+
printer.call(obj); // => "Example"
117+
{% endhighlight %}
118+
119+
The difference between ```apply``` and ```call``` is that apply allows you to invoke the function with the arguments as an array; ```call`` requires the parameters to be listed explicitly.
120+
121+
122+
# Var
123+
124+
The keyword ```var``` is used to define variables. Unfortunately, JavaScript does not require the use of this keyword when defining variables. Forgetting to leave off the var keyword can pollute the global object with unnecessary properties. It can also create innocent looking bugs. Have a look at the following example, What's the output?
125+
126+
{% highlight javascript %}
127+
function doStuff() {
128+
for (i = 0; i < 5; i++) {
129+
console.log(i);
130+
}
131+
}
132+
133+
function example() {
134+
for (i = 0; i < 5; i++) {
135+
doStuff();
136+
}
137+
}
138+
139+
example();
140+
{% endhighlight %}
141+
142+
At first glance it looks like it would output the numbers 0 to 5 - 5 times. Sadly, it doesn't; instead it outputs the number 0 - 5 just once! What's the problem? It's the fact that this example omits the use of the var keyword. To fix this we must declare the loop control variables within the function. Fixing the above example looks like this (note the use of var):
143+
144+
{% highlight javascript %}
145+
function doStuff() {
146+
var i;
147+
for (i = 0; i < 5; i++) {
148+
console.log(i);
149+
}
150+
}
151+
152+
function example() {
153+
for (var i = 0; i < 5; i++) {
154+
doStuff();
155+
}
156+
}
157+
158+
example();
159+
{% endhighlight %}

0 commit comments

Comments
 (0)