Tuesday, March 31, 2015

Useful Git Command

1. Squash
Say your bug fix branch is called bugfix and you want to merge it into master:
git checkout master
git merge --squash bugfix
git commit

2. Delete unexpected stash pop
git clean -f

3. Delete remote branch (the local one has been deleted)
git push origin --delete 

4. Reset commit
git reset --hard <HEAD>
git push -f

5. How to show or change Git username
http://alvinalexander.com/git/git-show-change-username-email-address

6. Generating SSH keys
https://help.github.com/articles/generating-ssh-keys/

7. Check who is the latest person updated the branch
git for-each-ref --format='%(refname) - %(authorname) (%(committerdate))' 'refs/remotes'

8. Prune the local list of remote branches
git remote prune origin

Sunday, March 29, 2015

Unexpected request GET error in Angular JS

I got the
Error: Unexpected request: GET components/template.html
No more request expected
at $httpBackend ... 

For me, the reason for this problem is:
The relative path of template.html in karma.conf.js preprocessors, beforeEach(module) and myDirective.js are different, i.e:
in the karma.conf.js, it was:
preprocessors: {
    'src/components/template.html': ['ng-html2js']
},

in the beforeEach(module), it was:

beforeEach(module('src/components/template.html'))

and in the myDirective,js, it was:

function myDirective(){
    return{
        restrict: 'EA',
        templateUrl: 'src/components/template.html'
    };
}

To solve the problem, I change all the relative path to
'src/components/template.html'

Wednesday, March 25, 2015

Good articles about AngularJS


Basic usage
1. AngularJS code style guide
- Jhon Papa: 10 AngularJS patterns
https://www.youtube.com/watch?v=UlvCbnKAH3g
https://github.com/johnpapa/ng-demos
- Todd Motto
https://github.com/toddmotto/angularjs-styleguide
- Angular Best Practices: Directory Structure
https://scotch.io/tutorials/angularjs-best-practices-directory-structure
- Scalable code organization in AngularJS
https://medium.com/opinionated-angularjs/scalable-code-organization-in-angularjs-9f01b594bf06
- Code Organization in large AngularJS and JavaScript Applications
http://cliffmeyers.com/blog/2013/4/21/code-organization-angularjs-javascript
2. Understanding $emit, $broadcast and $on in AngularJS
http://www.dotnet-tricks.com/Tutorial/angularjs/HM0L291214-Understanding-$emit,-$broadcast-and-$on-in-AngularJS.html
3. Recipes with Angular.js
http://fdietz.github.io/recipes-with-angular-js//controllers/testing-controllers.html
4. Angularjs directive
http://www.chroder.com/2014/02/01/using-ngmodelcontroller-with-custom-directives/
5. Controller in directive
http://www.bennadel.com/blog/2446-using-controllers-in-directives-in-angularjs.htm
6. Derictive Isolate Scope
http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-2-isolate-scope
7. Understanding Dependency Injection
https://github.com/angular/angular.js/wiki/Understanding-Dependency-Injection
8. Directive's lifecycle in AngularJS
http://filimanjaro.com/2014/angular-directive-lifecycle-vs-link-compile-controller/
9. Developer Guide Recipe: Provider, Factory, Service, Constant
https://docs.angularjs.org/guide/providers
http://www.learn-angular.org/#!/lessons/the-provider-recipe


AngularJS Unit Test:
1. Introduction to Unit Testing in AngularJS App
http://www.smashingmagazine.com/2014/10/07/introduction-to-unit-testing-in-angularjs/
2. Mocking Dependencies in AngularJS Tests
http://www.sitepoint.com/mocking-dependencies-angularjs-tests/
3. spyOn and createSpy
http://www.htmlgoodies.com/html5/javascript/spy-on-javascript-methods-using-the-jasmine-testing-framework.html#fbid=e4VtfL1YKyJ
4. Unit Testing w/ AngularJS
http://moduscreate.com/unit-testing-w-angularjs/
5. How to Unit Test Controllers
http://nathanleclaire.com/blog/2013/12/13/how-to-unit-test-controllers-in-angularjs-without-setting-your-hair-on-fire/
6. AngularJS Unit Testing Best Practices
http://blog.codeship.com/angularjs-tdd/
7. Introduction to Unit Test: Directives
http://angular-tips.com/blog/2014/06/introduction-to-unit-test-directives/
8. Video: Testing Directives
https://www.youtube.com/watch?v=rB5b67Cg6bc
9. Video: Unit Testing a Directive  ---- Egghead
https://www.youtube.com/watch?v=NV5Zkthh7nw
10. Testing AngularJS directive: handling external templates
http://www.portlandwebworks.com/blog/testing-angularjs-directives-handling-external-templates
11. Unit Testing AngularJS Directives With External Templates
http://www.bluesphereinc.com/blog/unit-testing-angularjs-directives
12. Testing AngularJS directives with External Templates --- using templatecache
http://www.portlandwebworks.com/blog/testing-angularjs-directives-handling-external-templates
13. Testing AngularJS directive templates with Jasmine and Karma
http://www.portlandwebworks.com/blog/testing-angularjs-directives-handling-external-templates
14. Testing directive that appends template to element ---- stackoverflow
http://stackoverflow.com/questions/28363679/testing-directive-that-appends-template-to-element
15. When template path in templateUrl of directive.js, module(<template path>) of directive.spec.js and preprocessor of karma.conf.js are different:
https://github.com/vojtajina/ng-directive-testing/issues/3#issuecomment-87720458
http://tylerhenkel.com/how-to-test-directives-that-use-templateurl/
16. Testing AngularJS Directive with Jasmine ---- From simple to complex
http://busypeoples.github.io/post/testing-angularjs-directives/
http://busypeoples.github.io/post/testing-angularjs-hierarchical-directives/
17. Video and sample code: What, How, When to test ---- e2e, unit test, TFD
https://www.youtube.com/watch?v=9-kumGACGYk
https://github.com/auser/testing-example
18. Angular Testing Cheat Sheet
https://github.com/sydcanem/angularjs-testing-cheat-sheet
19. Change constant value that gets passed to Config for Unit Test
http://stackoverflow.com/questions/25295445/angularjs-change-constant-value-that-gets-passed-to-config-for-unit-test
20. Unit Test custom provider
http://stackoverflow.com/questions/14771810/how-to-test-angularjs-custom-provider
https://github.com/angular/angular.js/issues/2274
21. Example of testing isolate scope
http://plnkr.co/edit/QXprEUof2Ps0Vivg4L34?p=preview
http://stackoverflow.com/questions/27697747/angular-testing-directive-with-templateurl-isolate-scope
22. Introduction to Unit Test: Services
http://angular-tips.com/blog/2014/06/introduction-to-unit-test-services/
23. Writing Unit Tests for an AngularJS Service
https://busypeoples.github.io/post/writing-unit-tests-for-service-in-angular-js/
24. Supplying Mocks for Services via $provide
http://tech.pro/tutorial/1517/supplying-mocks-for-services-via-provide
25. AngularJS Unit Testing Best Practices
http://blog.codeship.com/angularjs-tdd/
26. Understanding Dependency Injection

Friday, March 20, 2015

close in ModalService --- AngularJS

The close of Modal is in ModalService.

beforeEach(inject(function(_ModalService_){
    close = ModalService.close;
}))

Monday, March 16, 2015

Notes of SCOPE & CLOSURE JS

1. If an RHS look-up fails to ever find a variable, anywhere in the nested scopes, this results in a ReferenceError being thrown by the engine. I's important to note that the error is of the type ReferenceError.
    If the engine is performing an LHS look-up and it arrives at the top floor (global scope) without finding it, if the program is not running in "strict mode", then the global scope will create a new variable of that name in the global scope, and hand it back to Engine.

2. Cheating Lexical
    1) eval
    2) with: Even though a with block treats an object like a lexical scope, a normal var declaration inside that with block will not be scoped to that with block, but instead the containing function scope.

Wednesday, March 11, 2015

Notes: John Papa - 10 AngularJS Patterns (Codes on the Beach 2014)

BE CONSISTENT!

1. Structure Patterns
    1) By Type:
        app/
              controllers/
              services/
              views/
              factories/
              directives/
      2)By Feature
         app/
               dashboard/
               layout/
               people/
               services/
               Speakers/
               Tracks/
               Sessions
       3) Somewhere in the middle
    LIFT
2. Data Patterns
    Separation of Concerns
    Don't put data access in the Controller
3. Decorate the $exceptionHandler Service
4.  Modularity
    Each module can be app, service or widgets
    Modules are containers
    Defining a Module:

    set a module
var app = angular.module('myApp',[]);

    get a module
var app = angular.module('myApp');
 
    inject dependencies into a Module (like a wrapper ):
angular.module('app',[
   'app.avengers',
   'app.dashboard',
   'app.widgets',
   'app.layout'
]);

    Categories of Dependencies:
angular.module('app',[
   //Angular Modules
   'ngRoute',
   //Custome Modules
   'common',
   // 3rd Party Modules
   'ui.bootstrap',
   'breeze.angular'
]);

                        avengers                ngAnimate
ModularApp   dashboard    core    ngRoute
                        widgets                  common
                        layout                     ui-bootstrap

5. Controller pattern
    Controller is like a constructor

angular
    .module('app.avengers')
    .controller('Avenger',Avenger);

// "Classic" $scope syntax
function Avenger($scope){
    $scope.name = 'Captain America';
    $scope.prop = 'shield';
}

// "Controller As" syntax
function Avenger(){
    var vm = this;
    vm.name = 'Captain America';
    vm.prop = 'shield';
}
6. Clean Code
    IIFE(Immediately Invoked Function Expression)
7. Dependency Injection
    Safely Minify Dependencies
 
angular
    .module('app.dashboard')
    .controller('Dashboard',Dashboard);

function Dashboard(common, dataservice){
    // when minified, the common and dataservice may become a and b, which won't be found
}

Safe way 1: Inline Dependency Array
angular
    .module('app.dashboard')
    .controller('Dashboard',['common','dataservice',Dashboard]);
function Dashboard(common, dataservice){
}

Safe way 2: $inject
angular
    .module('app.dashboard')
    .controller('Dashboard',Dashboard);
Dashboard.$inject = ['$q','dataservice','logger'];
function Dashboard($q, dataservice, logger){
}

8. Tasks and Annotations
    Grunt: Configuration over code; File based
    Gulp: Code over configuration; Stream based
9. Breeze, Local Storage, Validation, Karma, Gulp and More

Saturday, March 7, 2015

Problem when assigning value to a variable defined outside of a function

I wrote this code:

searchBtnIsEnabled: {value: function(){
    var isEnabled;
    this.searchBtn.isEnabled().then(function(result){
      isEnabled = result;
      console.log("the isEnabled is: "+isEnabled);
    });
    console.log(isEnabled);
  }}


But the logged isEnabled is undefined. Then I change it to:

searchBtnIsEnabled: {value: function(callback){
    this.searchBtn.isEnabled().then(function(result){
      callback(result);
    })
  }}

this.searchBtnIsEnabled(function(enable){
    console.log("The enable is: "+enable);
})

Then it works.

REASON : Javascript Asynchronous

Please read:
http://tech.pro/blog/1402/five-patterns-to-help-you-tame-asynchronous-javascript
http://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron

Friday, March 6, 2015

Repost: JavaScript "this"

Source Link:
http://www.2ality.com/2014/05/this.html

JavaScript’s “this”: how it works, where it can trip you up

In JavaScript, the special variable this is relatively complicated, because it is available everywhere, not just in object-oriented settings. This blog post explains how this works and where it can cause problems, concluding with best practices.To understand this, it is best to partition the locations where it can be used into three categories:
  • In functions: this is an extra, often implicit, parameter.
  • Outside functions (in the top-level scope): this refers to the global object in browsers and to a module’s exports in Node.js.
  • In a string passed to eval(): eval() either picks up the current value ofthis or sets it to the global object, depending on whether it is called directly or indirectly.
Let’s examine each of these categories.

this in functions

That’s the most common way of using this, because functions represent all callable constructs in JavaScript, by playing three different roles:
  • Real functions (this is the global object in sloppy mode, undefined in strict mode)
  • Constructors (this refers to the newly created instance)
  • Methods (this refers to the receiver of the method call)
In functions, this can be thought of as an extra, often implicit, parameter.

this in real functions

In real functions, the value of this depends on the mode one is in:
  • Sloppy mode: this refers to the global object (window in browsers).
        function sloppyFunc() {
            console.log(this === window); // true
        }
        sloppyFunc();
    
  • Strict mode: this has the value undefined.
        function strictFunc() {
            'use strict';
            console.log(this === undefined); // true
        }
        strictFunc();
    
That is, this is an implicit parameter that is set to a default value (window or undefined). You can, however, make a function call via call() or apply() and specify the value ofthis explicitly:
    function func(arg1, arg2) {
        console.log(this); // a
        console.log(arg1); // b
        console.log(arg2); // c
    }
    func.call('a', 'b', 'c'); // (this, arg1, arg2)
    func.apply('a', ['b', 'c']); // (this, arrayWithArgs)

this in constructors

Functions become constructors if you invoke them via the new operator. That operator creates a new object and passes it to the constructor via this:
    var savedThis;
    function Constr() {
        savedThis = this;
    }
    var inst = new Constr();
    console.log(savedThis === inst); // true
Implemented in JavaScript, the new operator looks roughly as follows (a more accurate implementation is slightly more complex):
    function newOperator(Constr, arrayWithArgs) {
        var thisValue = Object.create(Constr.prototype);
        Constr.apply(thisValue, arrayWithArgs);
        return thisValue;
    }

this in methods

In methods, things are similar to more traditional object-oriented languages: this refers to the receiver, the object on which the method has been invoked.
    var obj = {
        method: function () {
            console.log(this === obj); // true
        }
    }
    obj.method();

this in the top-level scope

In browsers, the top-level scope is the global scope and this refers to the global object(like window does):
    <script>
        console.log(this === window); // true
    </script>
In Node.js, you normally execute code in modules. Therefore, the top-level scope is a special module scope:
    // `global` (not `window`) refers to global object:
    console.log(Math === global.Math); // true

    // `this` doesn’t refer to the global object:
    console.log(this !== global); // true
    // `this` refers to a module’s exports:
    console.log(this === module.exports); // true

this in eval()

eval() can be called either directly (via a real function call) or indirectly (via some other means). The details are explained here.If eval() is called indirectly, this refers to the global object:
    > (0,eval)('this === window')
    true
Otherwise, if eval() is called directly, this remains the same as in the surroundings ofeval(). For example:
    // Real functions
    function sloppyFunc() {
        console.log(eval('this') === window); // true
    }
    sloppyFunc();

    function strictFunc() {
        'use strict';
        console.log(eval('this') === undefined); // true
    }
    strictFunc();

    // Constructors
    var savedThis;
    function Constr() {
        savedThis = eval('this');
    }
    var inst = new Constr();
    console.log(savedThis === inst); // true

    // Methods
    var obj = {
        method: function () {
            console.log(eval('this') === obj); // true
        }
    }
    obj.method();

this-related pitfalls

There are three this-related pitfalls that you should be aware of. Note that in each case, strict mode makes things safer, because this is undefined in real functions and you get warnings when things go wrong.

Pitfall: forgetting new

If you invoke a constructor and forget the new operator, you are accidently using it as a real function. Hence, this does not have the correct value. In sloppy mode, this iswindow and you’ll create global variables:
    function Point(x, y) {
        this.x = x;
        this.y = y;
    }
    var p = Point(7, 5); // we forgot new!
    console.log(p === undefined); // true

    // Global variables have been created:
    console.log(x); // 7
    console.log(y); // 5
Thankfully, you get a warning in strict mode (this === undefined):
    function Point(x, y) {
        'use strict';
        this.x = x;
        this.y = y;
    }
    var p = Point(7, 5);
    // TypeError: Cannot set property 'x' of undefined

Pitfall: extracting methods improperly

If you retrieve the value of a method (instead of invoking it), you turn the method into a function. Calling the value results in a function call, not a method call. This kind of extraction can happen when you pass a method as an argument for a function or method call. Real-world examples include setTimeout() and registering event handlers. I’ll use the function callIt() to simulate this use case synchronously:
    /** Similar to setTimeout() and setImmediate() */
    function callIt(func) {
        func();
    }
If you call a sloppy-mode method as a function, this refers to the global object and global variables will be created:
    var counter = {
        count: 0,
        // Sloppy-mode method
        inc: function () {
            this.count++;
        }
    }

    callIt(counter.inc);

    // Didn’t work:
    console.log(counter.count); // 0

    // Instead, a global variable has been created
    // (NaN is result of applying ++ to undefined):
    console.log(count);  // NaN
If you call a strict-mode method as a function, this is undefined. Things don’t work, either. But at least you get a warning:
    var counter = {
        count: 0,
        // Strict-mode method
        inc: function () {
            'use strict';
            this.count++;
        }
    }

    callIt(counter.inc);

    // TypeError: Cannot read property 'count' of undefined
    console.log(counter.count);
The fix is to use bind():
    var counter = {
        count: 0,
        inc: function () {
            this.count++;
        }
    }

    callIt(counter.inc.bind(counter));

    // It worked!
    console.log(counter.count); // 1
bind() created a new function that always receives a this whose value is counter.

Pitfall: shadowing this

When you use a real function inside a method, it is easy to forget that the former has its own this (even though it has no need for it). Therefore, you can’t refer from the former to the method’s this, because it is shadowed. Let’s look at an example where things go wrong:
    var obj = {
        name: 'Jane',
        friends: [ 'Tarzan', 'Cheeta' ],
        loop: function () {
            'use strict';
            this.friends.forEach(
                function (friend) {
                    console.log(this.name+' knows '+friend);
                }
            );
        }
    };
    obj.loop();
    // TypeError: Cannot read property 'name' of undefined
In the previous example, this.name fails, because the function’s this is undefined, it is not the same as the this of the method loop(). There are three ways to fix … this.Fix 1: that = this. Assign this to a variable that isn’t shadowed (another popular name is self) and use that one.
    loop: function () {
        'use strict';
        var that = this;
        this.friends.forEach(function (friend) {
            console.log(that.name+' knows '+friend);
        });
    }
Fix 2: bind(). Use bind() to create a function whose this always has the correct value (the method’s this in the following example).
    loop: function () {
        'use strict';
        this.friends.forEach(function (friend) {
            console.log(this.name+' knows '+friend);
        }.bind(this));
    }
Fix 3: forEach’s second parameter. This method has a second parameter whose value is passed to the callback as this.
    loop: function () {
        'use strict';
        this.friends.forEach(function (friend) {
            console.log(this.name+' knows '+friend);
        }, this);
    }

Best practices

Conceptually, I think of real functions as not having their own this and think of the aforementioned fixes as keeping up that illusion. ECMAScript 6 supports this approach via arrow functions – functions without their own this. Inside such functions, you can freely use this, because there is no shadowing:
    loop: function () {
        'use strict';
        // The parameter of forEach() is an arrow function
        this.friends.forEach(friend => {
            // `this` is loop’s `this`
            console.log(this.name+' knows '+friend);
        });
    }
I don’t like APIs that use this as an additional parameter of real functions:
    beforeEach(function () {  
        this.addMatchers({  
            toBeInRange: function (start, end) {  
                ...
            }  
        });  
    });  
Turning such an implicit parameter into an explicit one makes things more obvious and is compatible with arrow functions.
    beforeEach(api => {
        api.addMatchers({
            toBeInRange(start, end) {
                ...
            }
        });
    });

Thursday, March 5, 2015

Repost: Understanding Baidu — The Chinese Google

Source Link of the Article:
http://www.sitepoint.com/baidu-chinese-google/




Shaumik Daityari

Although China represents a huge chunk of netizens (over 600 million users), the Chinese government is very strict when it comes to what content is shown to its people. They have stringent regulations and their ruthlessness is shown in partially or fully blocking popular websites like Google and Facebook in the past.
In spite of the absence of these American giants in the Chinese world, local websites have emerged, which perform the tasks of their American counterparts quite well. In this post, we look at the progress of one such website — Baidu.
Although the primary product of Baidu is the search engine, it also has services like Baidu Yun (cloud services), Baidu NewsBaidu Dictionary and many more. Baidu’s advertisements are also similar to Google’s Adwords and AdSense. In this article, let’s focus on the search engine and how to give your site the best chance of appearing in Chinese search results.

Why Care about Baidu?

Source: NetMarketShare
Source: NetMarketShare
To understand the importance of Baidu, you should consider the market share of different search engines. As the January 2015 search engine market share results show, Google accounts for over two thirds of searches, but Baidu comes in second with 18.7%. Bing currently has 8.7% and Yahoo is close behind with 7.8%

Getting Ready for Baidu

Baidu Screenshot
If the primary audience of your website is English speaking then it’s not necessary or wise to implement any of the tips that I provide here. However, if you run a product line or service with a large portion of your audience being Chinese-speaking, you can’t ignore this huge potential market. Let’s have a look at what you can do to help your website attract more Baidu users.

Use Chinese Keywords in Meta Tags

Although Google does not use the “keywords” meta tag to rank search results, Baidu has no such policy. Therefore, you can add Chinese words to your meta description and meta keywords. I’m not saying that you’ll immediately shoot to the top of Baidu’s rankings but it looks like at this stage, it can’t hurt!
An easy approach to this would be to translate your existing keywords and make copies of them in Chinese. Naturally, this leads to redundancy and you would do this only if you cater to a Chinese audience.

Be careful with JavaScript and Flash

Although web crawlers do not have the ability to execute JavaScript, the Google crawler is smarter and sometimes tries to crawl pages that the JavaScript pages point to. However, the Baidu crawler absolutely hasno way of interpreting your JavaScript. You should therefore have alternate text for anything that might be invisible to the crawler. You may also want to provide alternate non-JavaScript versions of webpages to point the crawlers to.
In addition to JavaScript, the Baidu crawler also has no way of detecting Flash content. If you can’t avoid Flash content, make sure you provide alternate text strings that describe the content and relevant meta tags.

Avoid sensitive content

The reason the American giants aren’t successful in China is because of the strong censorship by the Chinese government. Baidu adheres to those censorship policies. If you host content that the Chinese government thinks is not suitable for the Chinese public, your website will be taken off Baidu search results. You may refer to the list of blacklisted keywords in China to make sure you do not violate any terms.

Avoid duplicate content

By now you should know that every search engine hates duplicate content, Baidu is not different. Make sure you write a proper robots.txt to tell the crawler explicitly what to search for.

Get a Chinese domain

Baidu prefers sites hosted locally, so there is a higher preference to sites with the domain .cn or .com.cn. If you want significant traffic from China (this might be important for e-commerce sites for instance), it may be worth maintaining a Chinese version of your website with a .cn domain name to rank higher in Baidu.

Final Thoughts

Baidu has a huge market share and as a webmaster, you should be aware of its potential to drive Chinese traffic. If a large portion of your users or target market is Chinese and Baidu doesn’t index your website properly, you are missing out.

Repost: Understanding module.exports and exports in Node.js




Source Link of the article:
http://www.sitepoint.com/understanding-module-exports-exports-node-js/






Cho S. Kim

As developers, we often face situations where we need to use unfamiliar code. A question will arise during these moments. How much time should I invest in understanding the code that I’m about to use? A typical answer is learn enough to start coding; then explore that topic further when time permits. Well, the time has come to gain a better understanding of module.exports and exports in Node.js. Here’s what I have learned.

What is a Module

A module encapsulates related code into a single unit of code. When creating a module, this can be interpreted as moving all related functions into a file. Let’s illustrate this point with an example involving an application built with Node.js. Imagine that we created a file called greetings.js and it contains the following two functions:
1
2
3
4
5
6
7
8
// greetings.js
sayHelloInEnglish = function() {
  return "Hello";
};
sayHelloInSpanish = function() {
  return "Hola";
};

Exporting a Module

The utility of greetings.js increases when its encapsulated code can be utilized in other files. So let’s refactor greetings.js to achieve this goal. To comprehend what is actually happening, we can follow a three-step process:
1) Imagine that this line of code exists as the first line of code in greetings.js:
1
2
// greetings.js
var exports = module.exports = {};
2) Assign any expression in greetings.js that we want to become available in other files to the exportsobject:
1
2
3
4
5
6
7
8
9
10
// greetings.js
// var exports = module.exports = {};
         
exports.sayHelloInEnglish = function() {
  return "HELLO";
};
    
exports.sayHelloInSpanish = function() {
  return "Hola";
};
In the code above, we could have replaced exports with module.exports and achieved the same result. If this seems confusing, remember that exports and module.exports reference the same object.
3) This is the current value of module.exports:
1
2
3
4
5
6
7
8
9
module.exports = {
  sayHelloInEnglish: function() {
    return "HELLO";
  },
        
  sayHelloInSpanish: function() {
    return "Hola";
  }
};

Importing a Module

Let’s import the publicly available methods of greetings.js to a new file called main.js. This process can be described in three steps:
1) The keyword require is used in Node.js to import modules. Imagine that this is how require is defined:
1
2
3
4
5
6
var require = function(path) {
  // ...
  return module.exports;
};
2) Let’s require greetings.js in main.js:
1
2
// main.js
var greetings = require("./greetings.js");
The above code is equivalent to this:
1
2
3
4
5
6
7
8
9
10
// main.js
var greetings = {
  sayHelloInEnglish: function() {
    return "HELLO";
  },
        
  sayHelloInSpanish: function() {
    return "Hola";
  }
};
3) We can now access the publicly available methods of greetings.js as a property of our greetingsvariable in main.js.
1
2
3
4
5
6
7
8
// main.js
var greetings = require("./greetings.js");
// "Hello"
greetings.sayHelloInEnglish();
         
// "Hola" 
greetings.sayHelloInSpanish();

Salient Points

The keyword require returns an object, which references the value of module.exports for a given file. If a developer unintentionally or intentionally re-assigns module.exports to a different object or different data structure, then any properties added to the original module.exports object will be unaccessible.
An example will help elaborate this point:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// greetings.js
// var exports = module.exports = {};
exports.sayHelloInEnglish = function() {
  return "HELLO";
};
exports.sayHelloInSpanish = function() {
  return "Hola";
};
/*
 * this line of code re-assigns 
 * module.exports
 */
module.exports = "Bonjour";
Now let’s require greetings.js in main.js:
1
2
// main.js
var greetings = require("./greetings.js");
At this moment, nothing is different than before. We assign the variable greetings to any code that is publicly available in greetings.js.
The consequence of re-assigning module.exports to a data structure other than its default value is revealed when we attempt to invoke sayHelloInEnglish and sayHelloInSpanish:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// main.js
// var greetings = require("./greetings.js");
     
/*
 * TypeError: object Bonjour has no
 * method 'sayHelloInEnglish'
 */
greetings.sayHelloInEnglish();
         
/*
 * TypeError: object Bonjour has no
 * method 'sayHelloInSpanish'
 */
greetings.sayHelloInSpanish();
To understand why these errors are occuring, let’s log the value of greetings to a console:
1
2
// "Bonjour"
console.log(greetings);
At this point, we are trying to access the methods sayHelloInEnglish and sayHelloInSpanish on the string “Bonjour.” module.exports, in other words, is no longer referencing the default object that contain those methods.

Conclusion

Importing and exporting modules is a ubiqutous task in Node.js. I hope that the difference between exportsand module.exports is clearer. Moreover, if you ever encounter an error in accessing publicly available methods in the future, then I hope that you have a better understanding of why those errors may occur.