Use AngularJS to compile a more elegant JavaScript code guide, angularjs
Download the sample code in this article: modulePattern.zip-all four HTML files and panacea. js-1.6 KB
Introduction
AngularJS library contains many things, but I only want to focus on small ones in this article. I believe they can provide a better introduction to Angular. understanding this article does not require you to have any Angular-related or even JavaScript experience. I hope you can see some benefits of using Angular from this article and are willing to try it out.
Background
I have been using Angular for a while, and I also like to build some samples when learning Angular, so when I first went deep into it, I did not think much about the module or JavaScript design pattern, which is helpful for maintaining Code Organization and organization. that is all the key points: Keep the code organized and organized. as a result, I have created an extremely small sample to demonstrate how simple the modules can be. along the way, I hope it will become a good introduction to Angular.
(Majority) problems in explaining patterns
Most of the time, people will try to describe a pattern before the reader knows the concept of a pattern, which basically misleads everyone. efforts should be made to make this article as simple as possible. Let's take a look at this question first. Which problem? It is about the Javascript of all things that will be created in the global memory space by default.
The following is what I mean.
Default global JavaScript Problems
Suppose your HTML contains the following script.
<script> var isDoingWork = false;</script>
Range?
Do you know the scope of this variable?
Yes, it is global. This Boolean value is actually added to the global window object of the browser.
Set it to Action
Here you can see how it is in Action.
- Download the sample code in this article.
- Open modulePattern.htm in your browser.
- Open the browser development tool -- F12 (Chrome, IE) or Ctrl-Shift-I (Opera) -- (then you can see the console)
- In the browser tool console, ENTER isDoingWork and press ENTER <ENTER>
- The output value is false.
- ENTER isDoingWork = true, and press ENTER.
- The downloaded value is true. You have changed the value.
- You can see that this value has been added to the global window object by entering doingwindow. isDoingWork = true and then press ENTER.
This may cause some name conflicts and some serious bugs. This may be a bit worrying for you, right? However, imagine that you decided to implement a new JS library, which can be created every second. suppose you find this is called Panacea. js's great library will solve all your problems.
Therefore, you reference it in your page as follows:
<script src="panacea.js"></script>
So easy, you have solved all the problems you encountered before. however, because it is a huge library, you only want to solve the problem, but do not go back and dig into every line of code in this huge (thousands of lines of code) source file. and buried in Panacea. the following code does exist in a certain corner of js:
var isDoingWork = false; setInterval(function(){isDoingWork = !isDoingWork;}, 3000);
This code is really cool, you know?
Every 3 seconds, it sets this Boolean value to a relative value. Ah!
Start by yourself
If you want to verify this by yourself, you can perform the following steps:
- Download the sample code in this article.
- Open modulePattern2.htm in your browser.
- Open the browser development tool-F12 (Chrome, IE) or Ctrl-Shift-I (Opera)-(so that you can see the console)
- On the console of the browser development tool, ENTER isDoingWork and press ENTER <ENTER>
- Repeat Step 1 several times, and you will find that the isDoingWork value changes every 3 seconds.
Is that great?
My first point is that the module mode is very useful.
I need to explain this to show you why the JavaScript module mode is useful. I want to show you the module mode of JavaScript so that I can tell you how it is used or implemented in AngularJS.
Module mode: Encapsulation
In fact, the module mode is basically encapsulated. encapsulation sounds familiar. If you have some object-oriented programming experience-and I hope you have some experience. encapsulation is one of the three principles of object-oriented programming. Another encapsulation is data hiding. In classical object-oriented programming-unlike prototype OOP on which JavaScript depends-Data Hiding is an internal part of building a class template.
For example, in C #, Animal class encapsulation -- hide data -- specific values are associated with Animal objects. in this way, if someone decides to change those values, he or she must explicitly Initialize an Animal object and set the value of this object to achieve the goal. in JavaScript, we can set values in global window objects at will.
public class Animal { // constructor allows user to set the commonName public animal(string name) { this.commonName = name; } // making commonName private hides (encapsulates) it in the class private string commonName; //explicitly exposing the value for reading only public string CommonName get { return this.commonName }}
In JavaScript, the module has been created to simulate this encapsulation behavior, so that we will not organize our variables into a global namespace, it also causes hidden problems that are hard to be found and fixed.
Now you know why. Let's see how it works.
Expression for immediate function call (IIFE)
It looks like every time we push forward, we have to move around. to obtain the JavaScript syntax that allows us to create the module mode, we have to extract an expression syntax called the function to be called immediately, also known as IIFE (the IIFE pronunciation is "iffy ").
The most basic IIFE looks like this:
(function(){ // lines // of // code}());
If you have never seen anything like this, you can't say it.
Called immediately
First, the first part of the name is called immediately because the source file containing this special function is loaded, and the code contained in this function will run.
More careful observation of IIFE syntax
You can see that the center of this syntax is a function. Let's take a look at this code block. I have segmented the code and labeled some rows with numbers, so we can discuss it.
(// 1. function () // 2. {// 3. // a row of // code} () // 4.); // 5.
First, check the 2nd rows of the above script. This line usually seems to be an anonymous (that is, an unnamed) function declaration. Then, 3rd to 4th is the topic part of the function. Finally, Row 3 ends with a pair of arc, which tells the JavaScript interpreter to call this function. Eventually, all these will be wrapped in an arc (lines 1st and 5th) that does not belong to any part, and this arc will tell the interpreter to call this external anonymous function, it contains the defined functions.
IIFE can contain parameters
This strange syntax will look even more strange after it comes with parameters. It looks like the following:
(function(thing1, thing2){ // lines // of // code}("in string", 382));
Now, you can see that this function includes two thing1 and thing2 parameters that will be referenced by internal functions. The passed values are "in string" and 382.
Now we understand the IIFE syntax. Let's create another code example. We will run this code to see how encapsulation works.
(function(){ var isDoingWork = false; console.log("isDoingWork value : " + isDoingWork);}());
Start by yourself
To see how it works, you can perform the following steps:
- Download the source code of this article.
- Open modulePattern3.htm in your browser.
- Open the browser's development tool-F12 (Chrome, IE) or Ctrl-Shift-I (Opera)-(so that you can see the console)
- You can see things shown in the following figure.
When the method is called-this occurs immediately when the code is loaded with support by the JavaScript interpreter-then the function creates the isDoingWork variable and calls the console. log () to output the value of this variable in the console.
Now, let's use the console in the development tool to try the steps we have tried before:
ENTER isDoingWork and press ENTER <ENTER>
After you do this, you will see that the browser no longer believes that the isDoingWork value has been defined. Even if you try to get this value from the global window object, the browser does not think that the isDoingWork value is defined in this object. the error message you see appears as shown in the following figure.
A function is an object that creates a range.
This is because now you have created the isDoingWork variable in a function-that is, our anonymous IIFE-and this variable can only be accessed through this function. interestingly, all functions in Javascript are the first class objects. it is very concise, meaning that a function is an object, which may be accessed through a variable. or, another way to describe is to store a reference to the function and get its variable at a later time.
In our first example, the problem is that a reference pointing to our anonymous function is not saved, so we can never get the isDoingWork value. This is what we need to improve in the next example.
Function is an object: use this
Because every function is an object, every function has a this variable, which provides developers with reference to the current object. in order to provide access to our functions and their scopes from the outside, we can return this variable -- and it will provide a reference pointing to the current object.
Then, unless we add this private isDoingWork variable to function reference (this), we cannot reference this variable. For this reason, we need to make minor changes to the previous example. It looks like the following:
thing = (function(){ // 1. this.isDoingWork = false; // 2. console.log("isDoingWork value : " + isDoingWork); return this; // 3.}());
You can see that the first line adds a new global variable thing, which contains the value returned from the anonymous function. From the beginning of the sample code to the third line, you can see that this variable is returned. That means we have returned a reference pointing to an anonymous function.
In the second line, we have added isDoingWork to this reference, so that we can use the syntax thing. isDoingWork to reference this value from outside.
Start by yourself
To see how it works, you can perform the following steps:
- Download the sample code in this article.
- Open modulePattern4.htm in your browser.
- Open the browser development tool-F12 (Chrome, IE) or Ctrl-Shift-I (Opera)-(then you can see the console)
- You will see that the isDoingWork value is output to the console, as you saw in the first example.
- However, now you have to enter thing. isDoingWork to obtain this value.
Module mode Summary
In the final example, the variable value is successfully encapsulated, while other JavaScript libraries can explicitly reference the thing object to get this value. it seems unlikely, and this helps us keep the global namespace clean, and it seems to be a better form of code organization. this makes code maintenance easier.
Finally, we used AngularJS
The use of the module mode is a best practice, AngularJS developers build a module system into the library.
Plunker code
First you can pass to this Plunker (http://plnkr.co/edit/js8rbKpIuAuePzLF2DcP? P = preview-open in a new window or Tab) obtain the example of AngularJS.
The code is displayed here, so that we can talk about it more conveniently.
First, let's take a look at this HTML.
<!DOCTYPE html>
Angular command: ng-app
What Angular defines and uses is a command. These commands are basically defined by Angular, and AngularJS Compiler (Angular JavaScript) converts them into other things.
We applied the ng-app command to define a name for our Angular application called mainApp.
MainApp is the starting point of the module mode we will see later.
Introduced Script: each is a module
Now, note that three scripts are introduced into this HTML.
The first is the necessary AngularJS library.
The other two are Angular controllers implemented as modules.
They are implemented as modules to keep code independent from each other.
AngularJS: Create a score
Next, you will see two divs starting with the following code:
<div ng-controller="MainCtrl as mc"> <div ng-controller="SecondCtrl as sc">
This is to set ng-controller for every div. Each of these divs has its own range. The first controller is named MainCtrl, and the second is called SecondCtrl.
The AngularJS compiler will use these two names in your provided (introduced) code to find the corresponding function.
If the AngularJS compiler does not find a function corresponding to the two names, it will throw an error.
MainCtrl. js: The first Controller
Let's take a look at some things in the mainCtrl. js file.
You can click it on the left side of the Plunker page to open it in Plunker.
When you open it, you will see some code that looks familiar to you. Well, at least you will see that they are all wrapped in an IIFE.
(function() { var app = angular.module('mainApp', []); app.controller('MainCtrl', function() { console.log("in MainCtrl..."); // vt = virtual this - just shorthand vt = this; vt.name = 'MainCtrl'; vt.allThings = ["first", "second", "third"]; });})();
That's because we need the code to run when the file mainCtrl. js is loaded.
Now, pay attention to the first line of code in this IIFE.
var app = angular.module('mainApp', []);
This line of code is how Angular adds a module to its namespace. here, we have added a module to demonstrate our applications. this is the application module, and we have named it itmainApp. It is the same as the value specified by ng-app on the HTML page.
We also created a local variable called app (only visible locally in IIFE) so that we can add another controller in this function.
Strange Angular syntax
Please take a closer look at the first line. You will notice that we are creating the mainApp module for the first time. If it is the first time, we must provide any dependencies it may need in the form of a string array (, indicates the name of the dependent database ). however, in this simple example, we do not need any dependencies. Angular still needs to input an empty array so that it knows that we are creating a new module, rather than trying to load a created module.
Tip: you will see that we will load the mainApp module in secondCtrl. js, And the array mentioned above will have more functions.
After we create a mainApp, we need to add our controllers to it. These are the controllers Angular expects to add to HTML (in the div.
Add controller to App Module
The code for adding a controller looks like the following:
app.controller('MainCtrl', function() { console.log("in MainCtrl..."); // vt = virtual this - just shorthand vt = this; vt.name = 'MainCtrl'; vt.allThings = ["first", "second", "third"]; });
To add our controller functions, we provide a controller name and a function to the app. controller () function. Here we provide an anonymous function.
Therefore, the main code of our controller is the following lines:
console.log("in MainCtrl..."); // vt = virtual this - just shorthand vt = this; vt.name = 'MainCtrl'; vt.allThings = ["first", "second", "third"];
Here, when our controller is running, a line is output to the console. then, we will rename this variable to vt (for convenience, it will be called its virtual this), and then I added a name attribute and a string array named allThings for it.
Controller and Encapsulation
That is the code that runs when the controller is called by Angular. the Controller will run when the file is loaded, that is, when the HTML is loaded at the beginning. this means that the Controller will be loaded into the app module, and these attributes will be added to the Controller object (function. Because we want to add attributes to this variable, we can get these attributes later, but they are encapsulated, so they cannot be changed randomly by everyone.
Now, let's jump to the location where the controller is referenced and used in HTML.
First Div
This is the first Div referenced and used by our MainCtrl controller. It looks like the following:
<div ng-controller="MainCtrl as mc"> <p>mc refers to MainCtrl which has been added to the angular app module</p> <p>Hello {{mc.name}}!</p> <ol><li ng-repeat="a in mc.allThings">{{a}}</li></ol> </div>
This div outputs the following parts of our web page, which looks as shown in the following figure.
The output is created using the Angular command.
However, it uses a special method to create the output. It uses two Angular commands:
{{mc.name}} ng-repeat
The first command is associated with the MainCtrl statement and reference on the line above the Div. We tell Angular that we want to reference our MainCtrl function (object) with the mc name ). Angular provides a great abbreviated function.
Now, because we put an attribute on the MainCtrl this object, we can reference those items through mc and the attribute name. We include some special double braces in {}, so the Angular compiler can understand that the code can be run, and you will see Angular converts it into HTML:
<p>Hello {{mc.name}}!</p>
Programming the following:
Hello MainCtrl!
Then, we set a pretty no-need list and use the ng-repeat command to iterate each row in the output array.
Angular then falls down the entire allThings array and changes it to the following HTML
<li ng-repeat="a in mc.allThings">{{a}}</li>
The output is as follows:
1. first2. second3. third
That's simple. This is all modular, and our value will never be moved by anyone.
SecondCtrl: almost the same thing
Here is the code of SecondCtrl. The chance of code is the same, except that we get the original app module is a little different-not the first time I created it.
(function() { var app = angular.module('mainApp'); app.controller('SecondCtrl', function() { console.log("in SecondCtrl..."); // vt = virtual this - just shorthand vt = this; vt.name = 'SecondCtrl'; vt.allThings = ["bacon", "lettuce", "tomato"]; });})();
Take a closer look at the following line:
var app = angular.module('mainApp');
The only difference is that we do not provide reference arrays.
That's because mainApp already exists, and we just want to add another module (SecondCtrl) to it ).
Conclusion: Best Practices
The Code in all other scripts and HTML are basically the same. The most important thing here is that all the code is modularized and the data is encapsulated, in order to better organize our code. this is a best practice that Google software developers should follow. Learn about him, use it, and be with it (Amen ).