官术网_书友最值得收藏!

A JavaScript primer

As we already know Node.js is not just another language, but JavaScript. The language syntax and tools you are used to while coding JavaScript on the browser will work verbatim on the server. Node.js has additional tools that are only available on the server, but the language and syntax again are the same as JavaScript. I'm assuming you have a general understanding of the basic JavaScript syntax, but I will introduce JavaScript to you with a very brief primer on the language just in case.

In general, JavaScript is a fairly simple language when it comes to syntax, and you only need to know a few important elements.

Syntax basics

The most basic thing you can do in pretty much any programming language is declare a variable. Unlike most other languages, JavaScript is a dynamically typed language, which means when you declare a variable, its value can be of any type and can change during the course of its lifetime. However, in contrast, a strongly typed language dictates that a variable defined as a type string must always be a string and must always have a value of a string.

To declare a variable in JavaScript, simply use the var keyword before your variable name:

var myVariable;    // declaring a variable with no value
var myFirstName = "Jason";  
var myLastName = "Krol";
var myFullName = myFirstName + ' ' + myLastName; 
// => Jason Krol

The preceding code snippet shows how we declare variables and define them with initial values alongside their declarations. The + operator is used for string concatenation.

Also, we use camel case for the variable names. It is not mandatory that you use camel case for variable naming, but it is more common in object-oriented languages to follow camel case as opposed to the underscore-based approach.

Note

JavaScript won't complain if you forget to put a semicolon at the end of each statement. Instead it will attempt to put the semicolons for you if there are proper statement terminations missing. This can lead to unexpected results. The rules of semicolon insertion are explained in this article at http://bclary.com/2004/11/07/#a-7.9.1.

Apart from var, ES6 introduced two more keywords for variable declarations, namely let and const, which we will not be discussing in this chapter to avoid confusion.

In the preceding example, the variables we created held string values. JavaScript supports a number of data types along with string. Let's take a look at them.

Data types

Data types are the base of any language. The data types available in JavaScript are as follows:

  • Number
  • String
  • Boolean
  • Object
  • Null
  • Undefined

In our code, every variable we declare will contain values that belong to any of the types above. Number, string, and Boolean types are quite straightforward to understand. These come under the primitive data types supported by the language. Here, one important point is to note that JavaScript has no distinction between integers or floating points at its type level.

Types such as array, function, regex, and date come under the object data type. They are considered to be composite data types. So the functions that you define in your code will also be nothing but objects.

Null and undefined are two special types supported by JavaScript. Null points to a deliberate non-value, whereas undefined points to an uninitialized value. So when you just declare a variable and haven't yet initialized it with a value, the variable will be of undefined type.

Understanding the scope of variables

Understanding the scope of variables is very important in JavaScript to gain a better hold of the language. Scope may be referred to as a bucket in which your variable or your function exists. Unlike Java and other popular languages, JavaScript follows function-level scoping as opposed to block-level scoping. So this means that the variables you define will be limited to a scope that is bound to its parent function.

Consider the following code snippet:

var outer = 10;
function myFunction() {
   var inner = 2;
   console.log(inner);// 2
   console.log(outer);// 10
}

As you can see, the scope of the inner variable is limited to the parent function named myFunction. It won't be accessible outside it. Also, the variables available in outer scopes are available in function scopes, and you don't need to make any extra effort to access them, as you have seen with the variable named outer in the preceding example.

An important thing to discuss in this context is the use of the var keyword. JavaScript won't complain if you missed var while declaring a new variable. But things can get really bad if that happens. See the following example:

(function (){  
    (function (){ 
          a = 10;  
    })(); 
})(); 
console.log(a);// 10

Here, as the var keyword was skipped along with the variable declaration inside the inner function, JavaScript considered that this variable should be searched in its parent scopes, then attached it to the global scope, and ended up making it available everywhere. So, to avoid such issues with the code, it is always useful if you pass your code through code quality tools such as JSHint. The preceding code may have confused you, as it used self-invoked functions just to induce scopes. So let's take a look at the various ways to define and use functions, arrays, and objects.

Operators and flows

JavaScript supports similar control structures to other languages in the C family. Conditional statements are written with if and else, and you can chain together the statements using else-if ladders.

var a = "some value";
if(a === "other value") {
  //do something
} else if (a === "another value") {
  //do something
} else {
  //do something
}

Control statements can be written using while, do-while, for, and switch statements. One important thing to consider while writing conditions in JavaScript is to understand what equates to true and/or false. Any value greater or less than zero, not null, and not undefined equates to true. Strings such as 0, null, undefined, or empty strings equate to false.

Some sample examples using while, do-while, for and switch statements are given below.

// for loop example

var myVar = 0;
for(var i = 0; i < 100; i += 1) { 
  myVar = i;
  console.log(myVar); // => 0 1 ... 99
}

// do while example
var x = 0;
do {
  x += 1;
  console.log(x); // => 1 2 ... 100
} while (x < 100);

// while example
while (x > 90) {
  x -= 1;
  console.log(x); // => 99 98 ... 90
}
//switch example

var x = 0;
switch(x) {
  case 1 : 
console.log(""one"");
break;
  case 2 : 
console.log("two"");
break;
  default:
console.log("none");

} // => "none"

Another important thing will be to understand the basic difference between the comparisons using == and ===. The == comparisons should be used where the type of variable is not your concern; and if the data type of the variables also should be compared, then you should opt for a === comparison symbol as given in the following command:

var a = '5';
var b = 5;
if(a == b) {
  //do something
}
if(a === b) {
  //do something
}

Here in the code snippet, the first condition evaluates to true while the second doesn't. So while you code, it's always safer to depend on strict (===) equality checks as a best practice.

Note

It's always advised to run your code through code quality tools such as JS Hint before you approve them for your application. You can automate the code quality checks via task runners such as Grunt so that each time we make a change in your code, the code quality tool runs and presents if there are any potential issues with the code that has been written.

Understanding objects

In JavaScript objects, the arrays and even functions we create fall into the same data type: Object. Declaring an object is a fairly straightforward process:

var myObject = {};    // that's it!

You may add properties or attributes to this object, which may belong to any type. It means you can add arrays, functions, or even other objects as properties of this object. Adding a new property to this object can be done in any of the two ways shown here:

var person = {};
person.firstName = 'Jason';    // via dot operator
person['lastName'] = 'Krol';   // via square brackets

Let's look at an example where we add arrays and functions as properties of this object:

var person = {};
person.firstName = 'Jason';    // properties
person.lastName = 'Krol';
person.fullName = function() {  // methods
  return this.firstName + ' ' + this.lastName;
};
person.colors = ['red', 'blue', 'green'];  // array property

You can see in the preceding code that we defined a basic object called person and assigned it some properties and a function. It's important to note the use of the this keyword in the fullName function. The this keyword refers to the object that the function is a part of. So via the this keyword, the function will be able to access the other properties that are part of the object it belongs to.

Apart from the approach of adding properties after the object creation, we can also attach the initial object properties as part of its creation, as follows:

// define properties during declaration
var book = {
  title: 'Web Development with MongoDB and NodeJS',
  author: 'Jason Krol',
  publisher: 'Packt Publishing'
};
console.log(book.title);
// => Web Development with MongoDB and NodeJS
book.pageCount = 150;    // add new properties

In the preceding example, we are creating objects without specifying any class from which they should be created by using {}. So, this results in the creation of this new object from the Object base class from which other composite types such as Arrays and Functions are extended. So when you use {}, it is equivalent to a new Object().

Note

Here, the objects we create via use of the object literal {} are instances of the Object class. To define custom classes for our application, we will need to use functions and prototypes. Mozilla has a fairly good tutorial on introducing this whole point, available at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript.

Understanding arrays

Arrays work the same way in JavaScript as they do in pretty much any other language. They are zero indexed, and you can declare a variable as an empty array or a pre-populated array. You can manipulate the items in an array, and arrays are not fixed in length:

var favFoods = ['pizza', 'cheeseburgers', 'french fries'];
var stuff = [];        // empty array
var moreStuff = new Array();       // empty array
var firstFood = favFoods[0];    // => pizza
// array functions:
favFoods.push('salad');    // add new item
// => ['pizza', 'cheeseburgers', 'french fries', 'salad']
favFoods.pop();        // remove the last item
// => ['pizza', 'cheeseburgers', 'french fries']
var first = favFoods.shift();     // remove the first item
// => first = 'pizza'; 
// => favFoods = ['cheeseburgers', 'french fries']

To be more precise, you can consider arrays as extended child classes of the base Object class with extra implementations of Array functions.

Understanding functions

Functions are first-class citizens in JavaScript. What this means is that a function by itself is an object, so it can be treated as such and extended with properties and additional functions to the base Object class. We will see a lot of situations where we pass functions as parameters to other functions and return functions from other function calls.

Here, we will take a standard function (in this case, myFunction). We will assign this function a timesRun property, just like we do for any other object during its execution, and see how to refer to that property later:

var myFunction = function() {
  if(this.timesRun)
    this.timesRun += 1;
  else
    this.timesRun = 1;
  // do some actual work
  
  console.log(this.timesRun);
};
myFunction();
// => 1;
myFunction();
// => 2;
myFunction();
// => 3;
As we have seen in the preceding example, by using the var keyword, we can define functions in the same way as variables:
function sayHello() {
    console.log('Hello!');
}
// or
var sayHello = function() {
  console.log('Hello!');
};

Both methods are almost identical in the preceding sample code. The first method is the most common way to define a function, and is called the named function approach. The second method discussed here is the function expression approach, where you assign the unnamed function as a reference to a variable and keep it unnamed.

The single most important difference between these two approaches is related to a concept called JavaScript hoisting. Basically, the difference is that when you adopt a function expression strategy, the function will not be available in its containing scope till the point in its definition statement gets executed. In the named function approach, regardless of the position you define it at, the function will be available throughout the containing scope as given in the following code:

one();//will display Hello 
two();//will trigger error as its definition is yet to happen.

function one() {
    console.log('Hello!');
}

var two = function() {
  console.log('Hello!');
};
two ();//will display Hello

In the preceding sample code snippet, function one can be invoked from anywhere in this parent scope. But function two will not be available before the point where its expression is evaluated.

Note

JavaScript hoisting is the process by which the function definitions and variable declarations are moved to the top of the containing scope by the JS interpreter before the script is executed. So in the previous case of named functions, the definition was moved to the top of the scope. However, for the function expression, only the declaration of the variable moved to the top of the scope, setting it to undefined till the point in the script where it was actually executed. You can read more about the concept of hoisting at http://code.tutsplus.com/tutorials/javascript-hoisting-explained--net-15092.

Anonymous functions and callbacks

Often, you will need to use a temporary function that you don't necessarily want to declare ahead of time. In this type of scenario, you can use an anonymous function, which is simply a function that is declared at the time you need it. This is similar to the function expression context we explored earlier, with a simple difference that the function isn't assigned to a variable so it has no way of being referenced to later. The most common use of anonymous functions is when they are defined as a parameter to another function (most notably when used as a callback).

One of the most common places to use an anonymous function (which also acts as a callback even if you didn't realize it) is with setTimeout or setInterval. These are two standard JavaScript functions that will execute code after a specified delay (in milliseconds) or repeat the execution of code every specified delay. Here is an example of one of them, setTimeout, using an anonymous inline function:

console.log('Hello...');
setTimeout(function() {
  console.log('World!');
}, 5000);
// => Hello...
// (5000 milliseconds i.e. 5 second delay)
// => World!

You can see that the anonymous function was passed as the first parameter to setTimeout because setTimeout expects a function. You can, if you so desire, declare the function ahead of time as a variable and pass that to setTimeout instead of the inline anonymous function:

var sayWorld = function() {
  console.log('World!');
}
setTimeout(sayWorld, 5000);
// (5 second delay)
// => World!

The anonymous function just acts as a clean inline disposable function.

Callbacks are important because one of the most powerful (and confusing) features of JavaScript is that it's asynchronous. This means that every line executes sequentially, but it doesn't wait around for code that might be taking longer than it should (even if by design). We have explored this via an example in the first chapter while looking into the asynchronous nature of Node.js.

Note

Mozilla has a detailed tutorial on JavaScript concepts, which we advise you to go through once you finish this chapter. The tutorial includes highly advanced concepts, such as closures, that were not covered in this chapter due to the depth of the topic. So refer to this Mozilla Development Network article at https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript.

JSON

JavaScript Object Notation (JSON) is the standard syntax used when dealing with data in JavaScript as well as most other languages and web services. The basic premise of JSON is that it looks exactly like a standard JavaScript object with a few strict exceptions:

  • JSON is pure text. There are no data types with properties; that is, date values are stored as strings and so on.
  • All names and string values must be in double quotes.
  • There can be no functions as properties.

Let's take a quick look at a pretty standard JSON object:

{
  "title": "This is the title",
  "description": "Here is where the description would be",
  "page-count": 150,
  "authors": [
    { "name": "John Smith" },
    { "name": "Jane Doe" },
    { "name": "Andrea Johnson" }
  ],
  "id": "1234-567-89012345"
}

If you are at all familiar with XML, JSON is somewhat similar, except it is much easier to read and make sense out of. As described best by the ECMA, JSON is a text format that facilitates structured data interchange between all programming languages.

主站蜘蛛池模板: 沾化县| 威宁| 郯城县| 阿尔山市| 十堰市| 安乡县| 婺源县| 高清| 临澧县| 浑源县| 乐陵市| 德令哈市| 鄢陵县| 颍上县| 枣庄市| 东阿县| 共和县| 遂宁市| 定襄县| 五原县| 汉中市| 沿河| 平南县| 阿拉善右旗| 平乡县| 万载县| 营山县| 岑巩县| 志丹县| 石嘴山市| 商南县| 建阳市| 林甸县| 阳泉市| 类乌齐县| 富宁县| 屯昌县| 新蔡县| 荆州市| 奉贤区| 沙湾县|