├── .gitattributes ├── .gitignore ├── LICENSE ├── LearnJavascript ├── .bowerrc ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── .travis.yml ├── Gruntfile.js ├── Topics │ ├── 01 - Booleans.js │ ├── 02 - Strings.js │ ├── 03 - Variables.js │ ├── 04 - Loops.js │ ├── 05 - Conditionals.js │ ├── 06 - BuiltInFunctions.js │ ├── 07 - Arrays.js │ ├── 08 - Functions.js │ ├── 09 - FunctionExpressions.js │ ├── 10 - Closure.js │ ├── 11 - FunctionExpressionsAsParameters.js │ ├── 12 - Hoisting.js │ ├── 13 - Objects.js │ ├── 14 - ObjectsFunctionality.js │ ├── 15 - ObjectPrototype.js │ ├── 16 - Prototypes.js │ ├── 17 - LogicalAssignment.js │ ├── 18 - SwitchBlock.js │ ├── 19 - GeneralPerformance.js │ ├── 20 - TernaryConditionals.js │ ├── 21 - Comparisons.js │ ├── 22 - Exceptions.js │ ├── 23 - Numbers.js │ ├── 24 - BadPracticesAndSolutions.js │ ├── 25 - Namespaces.js │ ├── 26 - TruthyValues.js │ ├── 27 - FalsyValues.js │ └── 28 - FunctionalJavascript.js ├── bower.json ├── package.json └── test │ ├── .jshintrc │ └── karma.conf.js ├── README.md └── RunTests.png /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | 45 | #Webstorm 46 | .idea/** 47 | .idea/ 48 | .idea/workspace.xml 49 | *.xml 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Martin Chavez 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LearnJavascript/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /LearnJavascript/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /LearnJavascript/.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /LearnJavascript/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .tmp 4 | .sass-cache 5 | bower_components 6 | idea/** 7 | .idea/** 8 | .idea/ 9 | .idea/workspace.xml 10 | -------------------------------------------------------------------------------- /LearnJavascript/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 2, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "regexp": true, 16 | "undef": true, 17 | "unused": true, 18 | "strict": true, 19 | "trailing": true, 20 | "smarttabs": true, 21 | "globals": { 22 | "angular": false 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /LearnJavascript/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | before_script: 5 | - 'npm install -g bower grunt-cli' 6 | - 'bower install' 7 | -------------------------------------------------------------------------------- /LearnJavascript/Gruntfile.js: -------------------------------------------------------------------------------- 1 | // Generated on 2015-04-18 using generator-angular 0.9.2 2 | 'use strict'; 3 | 4 | // # Globbing 5 | // for performance reasons we're only matching one level down: 6 | // 'test/spec/{,*/}*.js' 7 | // use this if you want to recursively match all subfolders: 8 | // 'test/spec/**/*.js' 9 | 10 | module.exports = function (grunt) { 11 | 12 | // Load grunt tasks automatically 13 | require('load-grunt-tasks')(grunt); 14 | 15 | // Time how long tasks take. Can help when optimizing build times 16 | require('time-grunt')(grunt); 17 | 18 | // Configurable paths for the application 19 | var appConfig = { 20 | app: require('./bower.json').appPath || 'app', 21 | dist: 'dist' 22 | }; 23 | 24 | // Define the configuration for all the tasks 25 | grunt.initConfig({ 26 | 27 | // Project settings 28 | yeoman: appConfig, 29 | 30 | // Watches files for changes and runs tasks based on the changed files 31 | watch: { 32 | bower: { 33 | files: ['bower.json'], 34 | tasks: ['wiredep'] 35 | }, 36 | js: { 37 | files: ['<%= yeoman.app %>/scripts/{,*/}*.js'], 38 | tasks: ['newer:jshint:all'], 39 | options: { 40 | livereload: '<%= connect.options.livereload %>' 41 | } 42 | }, 43 | jsTest: { 44 | files: ['test/spec/{,*/}*.js'], 45 | tasks: ['newer:jshint:test', 'karma'] 46 | }, 47 | styles: { 48 | files: ['<%= yeoman.app %>/styles/{,*/}*.css'], 49 | tasks: ['newer:copy:styles', 'autoprefixer'] 50 | }, 51 | gruntfile: { 52 | files: ['Gruntfile.js'] 53 | }, 54 | livereload: { 55 | options: { 56 | livereload: '<%= connect.options.livereload %>' 57 | }, 58 | files: [ 59 | '<%= yeoman.app %>/{,*/}*.html', 60 | '.tmp/styles/{,*/}*.css', 61 | '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}' 62 | ] 63 | } 64 | }, 65 | 66 | // The actual grunt server settings 67 | connect: { 68 | options: { 69 | port: 9000, 70 | // Change this to '0.0.0.0' to access the server from outside. 71 | hostname: 'localhost', 72 | livereload: 35729 73 | }, 74 | livereload: { 75 | options: { 76 | open: true, 77 | middleware: function (connect) { 78 | return [ 79 | connect.static('.tmp'), 80 | connect().use( 81 | '/bower_components', 82 | connect.static('./bower_components') 83 | ), 84 | connect.static(appConfig.app) 85 | ]; 86 | } 87 | } 88 | }, 89 | test: { 90 | options: { 91 | port: 9001, 92 | middleware: function (connect) { 93 | return [ 94 | connect.static('.tmp'), 95 | connect.static('test'), 96 | connect().use( 97 | '/bower_components', 98 | connect.static('./bower_components') 99 | ), 100 | connect.static(appConfig.app) 101 | ]; 102 | } 103 | } 104 | }, 105 | dist: { 106 | options: { 107 | open: true, 108 | base: '<%= yeoman.dist %>' 109 | } 110 | } 111 | }, 112 | 113 | // Make sure code styles are up to par and there are no obvious mistakes 114 | jshint: { 115 | options: { 116 | jshintrc: '.jshintrc', 117 | reporter: require('jshint-stylish') 118 | }, 119 | all: { 120 | src: [ 121 | 'Gruntfile.js', 122 | '<%= yeoman.app %>/scripts/{,*/}*.js' 123 | ] 124 | }, 125 | test: { 126 | options: { 127 | jshintrc: 'test/.jshintrc' 128 | }, 129 | src: ['test/spec/{,*/}*.js'] 130 | } 131 | }, 132 | 133 | // Empties folders to start fresh 134 | clean: { 135 | dist: { 136 | files: [{ 137 | dot: true, 138 | src: [ 139 | '.tmp', 140 | '<%= yeoman.dist %>/{,*/}*', 141 | '!<%= yeoman.dist %>/.git*' 142 | ] 143 | }] 144 | }, 145 | server: '.tmp' 146 | }, 147 | 148 | // Add vendor prefixed styles 149 | autoprefixer: { 150 | options: { 151 | browsers: ['last 1 version'] 152 | }, 153 | dist: { 154 | files: [{ 155 | expand: true, 156 | cwd: '.tmp/styles/', 157 | src: '{,*/}*.css', 158 | dest: '.tmp/styles/' 159 | }] 160 | } 161 | }, 162 | 163 | // Automatically inject Bower components into the app 164 | wiredep: { 165 | options: { 166 | cwd: '<%= yeoman.app %>' 167 | }, 168 | app: { 169 | src: ['<%= yeoman.app %>/index.html'], 170 | ignorePath: /\.\.\// 171 | } 172 | }, 173 | 174 | // Renames files for browser caching purposes 175 | filerev: { 176 | dist: { 177 | src: [ 178 | '<%= yeoman.dist %>/scripts/{,*/}*.js', 179 | '<%= yeoman.dist %>/styles/{,*/}*.css', 180 | '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', 181 | '<%= yeoman.dist %>/styles/fonts/*' 182 | ] 183 | } 184 | }, 185 | 186 | // Reads HTML for usemin blocks to enable smart builds that automatically 187 | // concat, minify and revision files. Creates configurations in memory so 188 | // additional tasks can operate on them 189 | useminPrepare: { 190 | html: '<%= yeoman.app %>/index.html', 191 | options: { 192 | dest: '<%= yeoman.dist %>', 193 | flow: { 194 | html: { 195 | steps: { 196 | js: ['concat', 'uglifyjs'], 197 | css: ['cssmin'] 198 | }, 199 | post: {} 200 | } 201 | } 202 | } 203 | }, 204 | 205 | // Performs rewrites based on filerev and the useminPrepare configuration 206 | usemin: { 207 | html: ['<%= yeoman.dist %>/{,*/}*.html'], 208 | css: ['<%= yeoman.dist %>/styles/{,*/}*.css'], 209 | options: { 210 | assetsDirs: ['<%= yeoman.dist %>','<%= yeoman.dist %>/images'] 211 | } 212 | }, 213 | 214 | // The following *-min tasks will produce minified files in the dist folder 215 | // By default, your `index.html`'s will take care of 216 | // minification. These next options are pre-configured if you do not wish 217 | // to use the Usemin blocks. 218 | // cssmin: { 219 | // dist: { 220 | // files: { 221 | // '<%= yeoman.dist %>/styles/main.css': [ 222 | // '.tmp/styles/{,*/}*.css' 223 | // ] 224 | // } 225 | // } 226 | // }, 227 | // uglify: { 228 | // dist: { 229 | // files: { 230 | // '<%= yeoman.dist %>/scripts/scripts.js': [ 231 | // '<%= yeoman.dist %>/scripts/scripts.js' 232 | // ] 233 | // } 234 | // } 235 | // }, 236 | // concat: { 237 | // dist: {} 238 | // }, 239 | 240 | imagemin: { 241 | dist: { 242 | files: [{ 243 | expand: true, 244 | cwd: '<%= yeoman.app %>/images', 245 | src: '{,*/}*.{png,jpg,jpeg,gif}', 246 | dest: '<%= yeoman.dist %>/images' 247 | }] 248 | } 249 | }, 250 | 251 | svgmin: { 252 | dist: { 253 | files: [{ 254 | expand: true, 255 | cwd: '<%= yeoman.app %>/images', 256 | src: '{,*/}*.svg', 257 | dest: '<%= yeoman.dist %>/images' 258 | }] 259 | } 260 | }, 261 | 262 | htmlmin: { 263 | dist: { 264 | options: { 265 | collapseWhitespace: true, 266 | conservativeCollapse: true, 267 | collapseBooleanAttributes: true, 268 | removeCommentsFromCDATA: true, 269 | removeOptionalTags: true 270 | }, 271 | files: [{ 272 | expand: true, 273 | cwd: '<%= yeoman.dist %>', 274 | src: ['*.html', 'views/{,*/}*.html'], 275 | dest: '<%= yeoman.dist %>' 276 | }] 277 | } 278 | }, 279 | 280 | // ngmin tries to make the code safe for minification automatically by 281 | // using the Angular long form for dependency injection. It doesn't work on 282 | // things like resolve or inject so those have to be done manually. 283 | ngmin: { 284 | dist: { 285 | files: [{ 286 | expand: true, 287 | cwd: '.tmp/concat/scripts', 288 | src: '*.js', 289 | dest: '.tmp/concat/scripts' 290 | }] 291 | } 292 | }, 293 | 294 | // Replace Google CDN references 295 | cdnify: { 296 | dist: { 297 | html: ['<%= yeoman.dist %>/*.html'] 298 | } 299 | }, 300 | 301 | // Copies remaining files to places other tasks can use 302 | copy: { 303 | dist: { 304 | files: [{ 305 | expand: true, 306 | dot: true, 307 | cwd: '<%= yeoman.app %>', 308 | dest: '<%= yeoman.dist %>', 309 | src: [ 310 | '*.{ico,png,txt}', 311 | '.htaccess', 312 | '*.html', 313 | 'views/{,*/}*.html', 314 | 'images/{,*/}*.{webp}', 315 | 'fonts/*' 316 | ] 317 | }, { 318 | expand: true, 319 | cwd: '.tmp/images', 320 | dest: '<%= yeoman.dist %>/images', 321 | src: ['generated/*'] 322 | }, { 323 | expand: true, 324 | cwd: 'bower_components/bootstrap/dist', 325 | src: 'fonts/*', 326 | dest: '<%= yeoman.dist %>' 327 | }] 328 | }, 329 | styles: { 330 | expand: true, 331 | cwd: '<%= yeoman.app %>/styles', 332 | dest: '.tmp/styles/', 333 | src: '{,*/}*.css' 334 | } 335 | }, 336 | 337 | // Run some tasks in parallel to speed up the build process 338 | concurrent: { 339 | server: [ 340 | 'copy:styles' 341 | ], 342 | test: [ 343 | 'copy:styles' 344 | ], 345 | dist: [ 346 | 'copy:styles', 347 | 'imagemin', 348 | 'svgmin' 349 | ] 350 | }, 351 | 352 | // Test settings 353 | karma: { 354 | unit: { 355 | configFile: 'test/karma.conf.js', 356 | singleRun: true 357 | } 358 | } 359 | }); 360 | 361 | 362 | grunt.registerTask('serve', 'Compile then start a connect web server', function (target) { 363 | if (target === 'dist') { 364 | return grunt.task.run(['build', 'connect:dist:keepalive']); 365 | } 366 | 367 | grunt.task.run([ 368 | 'clean:server', 369 | 'wiredep', 370 | 'concurrent:server', 371 | 'autoprefixer', 372 | 'connect:livereload', 373 | 'watch' 374 | ]); 375 | }); 376 | 377 | grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) { 378 | grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.'); 379 | grunt.task.run(['serve:' + target]); 380 | }); 381 | 382 | grunt.registerTask('test', [ 383 | 'clean:server', 384 | 'concurrent:test', 385 | 'autoprefixer', 386 | 'connect:test', 387 | 'karma' 388 | ]); 389 | 390 | grunt.registerTask('build', [ 391 | 'clean:dist', 392 | 'wiredep', 393 | 'useminPrepare', 394 | 'concurrent:dist', 395 | 'autoprefixer', 396 | 'concat', 397 | 'ngmin', 398 | 'copy:dist', 399 | 'cdnify', 400 | 'cssmin', 401 | 'uglify', 402 | 'filerev', 403 | 'usemin', 404 | 'htmlmin' 405 | ]); 406 | 407 | grunt.registerTask('default', [ 408 | 'newer:jshint', 409 | 'test', 410 | 'build' 411 | ]); 412 | }; 413 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/01 - Booleans.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Booleans', function () { 4 | 5 | /*Boolean : Represents one of two values: true or false. 6 | * We will demonstrate the use of this Type with different operators and comparators. 7 | * */ 8 | 9 | /*Operators*/ 10 | /*Common Operators used in Javascript Language*/ 11 | it('Addition', function () { 12 | expect(6+4 === 10).toBe(true); 13 | expect(6+4 === 11).toBe(false); 14 | }); 15 | it('Subtraction', function () { 16 | expect(10-4 === 6).toBe(true); 17 | expect(10-4 === -6).toBe(false); 18 | }); 19 | it('Division', function () { 20 | expect(12/4 === 3).toBe(true); 21 | }); 22 | /*Grouping Expressions*/ 23 | /*PEMDAS: Parentheses, Exponents, Multiplication, Division, Addition and Subtraction. */ 24 | it('Javascript follows PEMDAS: Order of Operations', function () { 25 | expect((-5 * 6) - 7 * -2 === -16).toBe(true); 26 | }); 27 | 28 | /*Comparators*/ 29 | /*Common Number Comparators used in Javascript Syntax*/ 30 | it('Greater than', function () { 31 | expect(6>4).toBe(true); 32 | }); 33 | it('Less than', function () { 34 | expect(6<4).toBe(false); 35 | }); 36 | it('Equals', function () { 37 | expect(4==4).toBe(true); 38 | }); 39 | it('Not Equals', function () { 40 | expect(4!=5).toBe(true); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/02 - Strings.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Strings', function () { 4 | 5 | /*Strings*/ 6 | /*In javascript we need to use "Quotes" in order to process and manipulate strings*/ 7 | it('You can create a String by surrounding text with quotes', function () { 8 | expect(typeof "String").toEqual("string"); 9 | }); 10 | it('Javascript Strings support concatenation', function () { 11 | expect("First" + "Second").toEqual("FirstSecond"); 12 | }); 13 | it('Concatenation works with numbers', function () { 14 | expect("StringFirst" + 1).toEqual("StringFirst1"); 15 | }); 16 | it('Concatenation evaluates expressions', function () { 17 | expect("Multiply 4*2 =" + 4 * 2).toEqual("Multiply 4*2 =8"); 18 | }); 19 | it('You can escape quotation marks with backslash', function () { 20 | expect("Escape\"Quotes\"").toEqual("Escape" + '"' + "Quotes" + '"'); 21 | }); 22 | it('Double equals will compare exact contents', function () { 23 | expect("String" == "String").toBe(true); 24 | }); 25 | it('Double equals on strings is case sensitive', function () { 26 | expect("String" == "string").toBe(false); 27 | }); 28 | it('Length of strings can be accessed with the .length property', function () { 29 | expect("ThisStringIsVeryLong".length).toBe(20); 30 | }); 31 | 32 | /*Common and Useful String Methods*/ 33 | 34 | it('You can convert a number, Boolean or an object to string using the String() constructor', function () { 35 | 36 | var boolean = false; 37 | expect(String(boolean)).toBe("false"); 38 | 39 | var number = 6; 40 | expect(String(number)).toBe("6"); 41 | 42 | var object = {}; 43 | expect(String(object)).toBe("[object Object]"); 44 | 45 | }); 46 | 47 | it('You can split a String into multiple sub-strings (inside an Array) using the split() method', function () { 48 | 49 | var numbers = "0,1,2"; 50 | //split() method takes as an argument the separator 51 | var numbersArray = numbers.split(','); 52 | 53 | expect(numbersArray[0]).toBe("0"); 54 | expect(numbersArray[1]).toBe("1"); 55 | expect(numbersArray[2]).toBe("2"); 56 | }); 57 | 58 | it('You can locate a Substring within a String using the indexOf() method', function () { 59 | //The indexOf() method starts searching for the substring (the first argument passed in) from the beginning of the string 60 | // The method returns the position of the start of the first occurrence of the substring. 61 | var fullName = "Martin Chavez Aguilar"; 62 | expect(fullName.indexOf("Chavez")).toBe(7); 63 | }); 64 | 65 | it('You can replace a Substring using the replace() method', function () { 66 | var fullName = "Marvin Chavez Aguilar"; 67 | //The first argument is the substring you want to replace, the second argument is the new substring. 68 | fullName = fullName.replace("Marvin","Martin"); 69 | // This will only replace the first instance of the matched substring. 70 | expect(fullName).toBe("Martin Chavez Aguilar"); 71 | }); 72 | 73 | it('You can delete a Substring from a string using the slice() method', function () { 74 | //The first argument is the character at which to begin the substring (using zero-based numbering) 75 | //the second argument (which is optional) is the character in the string after you want the substring to end 76 | var fullName = "Martin Chavez Aguilar"; 77 | fullName = fullName.slice(7); 78 | expect(fullName).toBe("Chavez Aguilar"); 79 | }); 80 | 81 | it('You can convert a string to Uppercase or Lowercase using the toUpperCase() and toLowerCase() methods', function () { 82 | var word = "ABC"; 83 | expect(word.toLowerCase()).toBe("abc"); 84 | }); 85 | 86 | /*Performance*/ 87 | 88 | it('Use standard concatenation for small string concatenations', function () { 89 | //Standard concatenation operator has been optimized in most modern browser versions 90 | var stringOne = "One"; 91 | var stringTwo = "Two"; 92 | var stringThree = "Three"; 93 | 94 | var finalString = ""; 95 | finalString += stringOne; 96 | finalString += stringTwo; 97 | finalString += stringThree; 98 | 99 | expect(finalString).toBe("OneTwoThree"); 100 | }); 101 | 102 | it('You can also use concat() method for string concatenations', function () { 103 | //Standard concatenation operator has been optimized in most modern browser versions 104 | var stringOne = "One"; 105 | var stringTwo = "Two"; 106 | var stringThree = "Three"; 107 | 108 | var finalString = stringOne.concat(stringTwo,stringThree); 109 | 110 | expect(finalString).toBe("OneTwoThree"); 111 | }); 112 | 113 | it('When strings are present in an array, use the join() method to concatenate', function () { 114 | //The join() method is inherited from the Array Prototype 115 | var stringArrays = ["StringOne", "StringTwo", "StringThree"]; 116 | //Apart for performing better than string concatenation, the code becomes more readable 117 | expect(stringArrays.join("")).toBe("StringOneStringTwoStringThree"); 118 | }); 119 | 120 | 121 | }); 122 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/03 - Variables.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Variables', function () { 4 | 5 | /*Variables*/ 6 | /*Javascript uses variables to store and manage data*/ 7 | /*'var' is the keyword it is used to reserve memory and create variables*/ 8 | it('you can assign strings to var', function () { 9 | var variable = "ValueToBeAssigned"; 10 | expect(variable).toBe("ValueToBeAssigned"); 11 | }); 12 | it('you can assign numerical values to a variable', function () { 13 | var variable = 5; 14 | expect(variable).toBe(5); 15 | }); 16 | it('you can change the value of a variable', function () { 17 | var variable = 5; //This allocates memory for var 'variable' 18 | variable = 6; //Once the variable is defined, you don't need to reserve more memory 19 | expect(variable).toBe(6); 20 | }); 21 | it('you can change the value of the variable by using the value of the same variable', function () { 22 | var variable = 5; 23 | variable = variable + variable; //By using the value of variable, which is 5, we can re-write the value of variable 24 | expect(variable).toBe(10); 25 | }); 26 | it('Variable names also act as substitutes for the data they point to', function () { 27 | var five = 5; 28 | var fiveString = "Five is " + five; 29 | expect(fiveString).toBe("Five is 5"); 30 | }); 31 | it('You can use a simpler syntax to increase the numeric values of variables', function () { 32 | var fivePlusOne = 5; 33 | fivePlusOne++; //This is the same as : var five = five + 1; 34 | expect(fivePlusOne).toBe(6); 35 | }); 36 | it('Variables can hold strings', function () { 37 | var stringVariable = "This is a string variable"; 38 | expect(typeof stringVariable).toEqual('string'); 39 | }); 40 | it('You can compare string lengths using the length property', function () { 41 | var stringVariable = "This is a string variable"; 42 | var stringVariableTwo = "This is a second string variable"; 43 | expect(stringVariableTwo.length > stringVariable.length).toBe(true); 44 | }); 45 | it('Length property of string is zero-based', function () { 46 | // char '4' is at position 4, because we start counting at zero 47 | var stringVariable = "01234"; 48 | //but the length is still five 49 | expect(stringVariable.length).toBe(5); 50 | }); 51 | it('You can use charAt property to retrieve the char at a given position', function () { 52 | var stringVariable = "01234"; 53 | expect(stringVariable.charAt(4)).toBe("4"); 54 | }); 55 | 56 | }); 57 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/04 - Loops.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Loops', function () { 4 | 5 | /*Loops*/ 6 | /*While Loop*/ 7 | it('The while-loop runs its code as long as its boolean expression is true', function () { 8 | var currentNumber = 0; 9 | //loop runs as long as (currentNumber < 5) is true 10 | while (currentNumber < 5) { 11 | currentNumber++; //All statements inside the body will be executed during each loop 12 | }//The body of the loop is enclosed in curly braces 13 | expect(currentNumber).toBe(5); 14 | }); 15 | /*For-Loop*/ 16 | it('The for-loop runs has three sections and it is a different way of producing looping behavior', function () { 17 | // Initialization Conditions Statements that control the loop 18 | for (var currentNumber = 0;currentNumber <5 ;currentNumber++) { 19 | //All statements inside the body will be executed during each loop 20 | } 21 | expect(currentNumber).toBe(5); 22 | }); 23 | 24 | /*Performance Optimizations*/ 25 | it('You can minimize memory access inside for loops', function () { 26 | var numbers = [0,1,2,3,4,5,6,7,8,9]; 27 | //At the start of every cycle, the program needs to access the numbers array and access it's length property 28 | for (var index = 0;index < numbers.length ;index++) { 29 | expect(numbers[index]).toBe(index); 30 | } 31 | //You can use cached values to improve the loop performance by reducing memory access. 32 | //By creating both variables in the loop parameters, 33 | //we signal to the compiler that they are only intended for use inside the loop 34 | for (var index = 0,numbersLength = numbers.length;index < numbersLength ;index++) { 35 | expect(numbers[index]).toBe(index); 36 | } 37 | }); 38 | it('You should use for-loops(vs in-loops) for array iteration', function () { 39 | Array.prototype.extraMethod = function (){}; 40 | 41 | var numbers = [0,1,2]; 42 | //Using a property approach to access indices will also add in all the methods that have been added to the prototype 43 | for (var property in numbers) { 44 | if(isNaN(property)){ 45 | expect(property).toBe('extraMethod'); 46 | } 47 | } 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/05 - Conditionals.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Conditionals', function () { 4 | 5 | /*Conditionals*/ 6 | /*Expressions that allow to execute code paths based on specific conditions*/ 7 | it('If then Else', function () { 8 | var shouldBeTrue; 9 | //If the conditional evaluates to true, the code block is executed 10 | if (true) { 11 | shouldBeTrue = true; 12 | } else { //Else follows up with code to execute only when the If conditional is not satisfied. 13 | // It is ignored otherwise. 14 | shouldBeTrue = false; 15 | } 16 | expect(shouldBeTrue).toBe(true); 17 | }); 18 | it('Else-If when two conditionals are not enough', function () { 19 | var shouldBeTrue; 20 | //If the conditional does not evaluates to true, the code block is not executed 21 | if (false) { 22 | shouldBeTrue = false; 23 | } else if (true) { //This condition is checked only when the first If conditional is not met 24 | // These statements are executed if the else condition is met 25 | shouldBeTrue = true; 26 | } 27 | expect(shouldBeTrue).toBe(true); 28 | }); 29 | /*Complex Conditionals*/ 30 | it('Binary AND', function () { 31 | var value; 32 | //Binary AND returns true if All values are true 33 | value = true && false; 34 | expect(value).toBe(false); 35 | value = false && true; 36 | expect(value).toBe(false); 37 | value = false && false; 38 | expect(value).toBe(false); 39 | value = true && true; 40 | expect(value).toBe(true); 41 | 42 | }); 43 | it('Binary OR', function () { 44 | var value; 45 | //Binary OR returns true if Either value is true 46 | value = true || false; 47 | expect(value).toBe(true); 48 | value = false || true; 49 | expect(value).toBe(true); 50 | value = false || false; 51 | expect(value).toBe(false); 52 | value = true || true; 53 | expect(value).toBe(true); 54 | }); 55 | 56 | }); 57 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/06 - BuiltInFunctions.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Built-In Functions', function () { 4 | 5 | /*Built-In Functions*/ 6 | /*Helper functions that are available at any execution level*/ 7 | it('typeof is used to identify the type of value inside a variable or expression', function () { 8 | expect(typeof true).toBe("boolean"); 9 | expect(typeof "String").toBe("string"); 10 | expect(typeof 100).toBe("number"); 11 | expect(typeof undefined).toBe("undefined"); 12 | expect(typeof null).toBe("object"); 13 | }); 14 | 15 | it('toString() function returns the string representation of the variable', function () { 16 | expect(true.toString()).toBe("true"); 17 | expect("String".toString()).toBe("String"); 18 | var number = 100; 19 | expect(number.toString()).toBe("100"); 20 | }); 21 | 22 | }); 23 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/07 - Arrays.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Arrays', function () { 4 | 5 | /*Arrays*/ 6 | /* An array is a data structure with automatically indexed positions*/ 7 | it('Arrays can be accessed by indices', function () { 8 | //The brackets indicate to the compiler to make an array and to fill it with the comma-separated values between the brackets 9 | var arrayOfStrings = [ "StringZero" , "StringOne" , "StringTwo"]; 10 | expect(arrayOfStrings[1]).toBe("StringOne");//We can access any location of the zero-based array 11 | }); 12 | it('You can reference and change specific cells with indices', function () { 13 | var arrayOfStrings = [ "StringOne" , "StringOne" , "StringTwo"]; 14 | arrayOfStrings[0] = "StringZero"; //You can change the value contained at any index 15 | expect(arrayOfStrings[0]).toBe("StringZero"); 16 | }); 17 | it('You can access the length of Arrays with the .length property', function () { 18 | var arrayOfStrings = [ "StringZero" , "StringOne" , "StringTwo"]; 19 | expect(arrayOfStrings.length).toBe(3); 20 | }); 21 | it('Pop() function removes a cell from the back of the array', function () { 22 | var arrayOfStrings = [ "StringZero" , "StringOne" , "StringTwo"]; 23 | expect(arrayOfStrings.pop()).toBe("StringTwo");//Pop() function deletes the last position and retrieves its value 24 | expect(arrayOfStrings.length).toBe(2);//The array length automatically adjusts 25 | }); 26 | it('shift() function removes a cell from the beginning of the array', function () { 27 | var arrayOfStrings = [ "StringZero" , "StringOne" , "StringTwo"]; 28 | expect(arrayOfStrings.shift()).toBe("StringZero");//shift() function deletes the first position and retrieves its value 29 | expect(arrayOfStrings.length).toBe(2);//The array length automatically adjusts 30 | }); 31 | it('Push() function adds a cell and its contents to the back of the array', function () { 32 | var arrayOfStrings = [ "StringZero" , "StringOne" ]; 33 | arrayOfStrings.push('StringTwo'); 34 | expect(arrayOfStrings[2]).toBe("StringTwo");//Push() will add a cell onto the back of the arrays 35 | expect(arrayOfStrings.length).toBe(3);//The array length automatically adjusts 36 | }); 37 | 38 | it('splice() function removes elements from anywhere in the array', function () { 39 | var arrayOfStrings = [ "StringZero" , "StringOne" , "StringTwo"]; 40 | //The first argument is the index where you want to start 41 | //The second argument is the number of elements you want to remove 42 | arrayOfStrings.splice(1,1); 43 | expect(arrayOfStrings[1]).toBe("StringTwo"); 44 | expect(arrayOfStrings.length).toBe(2);//The array length automatically adjusts 45 | }); 46 | 47 | it('Arrays can hold different types of variables ', function () { 48 | var StringTwoVariable = "StringTwo"; 49 | var arrayOfStrings = [ "StringZero" , 1 , StringTwoVariable]; 50 | //When assigning variables to an entry of an array, the variable name is not used, 51 | //Instead, the internal value is retrieved 52 | expect(arrayOfStrings[2]).toBe("StringTwo"); 53 | }); 54 | it('Arrays can hold Arrays ', function () { 55 | var firstArrayOfStrings = [ "StringZero" , "StringOne" , "StringTwo"]; 56 | var secondArrayOfStrings = [ "StringThree" , "StringFour" , "StringFive"]; 57 | var firstAndSecondArrays = [firstArrayOfStrings , secondArrayOfStrings]; 58 | expect(Array.isArray(firstAndSecondArrays)).toBe(true);// By combining Arrays, you create a new Array 59 | expect(firstAndSecondArrays[1][0]).toBe("StringThree");//You can access any index of the composed array 60 | }); 61 | it('Arrays can hold undefined values ', function () { 62 | var arrayOfStrings = ["StringZero" , "StringOne" , "StringTwo"]; 63 | arrayOfStrings[1] = undefined; //to make a cell empty. we can use the keyword 'undefined', which means 'NO CONTENTS' 64 | expect(arrayOfStrings[1]).toBeUndefined(); 65 | expect(arrayOfStrings.length).toBe(3);//The array length does not change when some of the values are undefined 66 | }); 67 | it('Arrays can be created with no values ', function () { 68 | var arrayOfStrings = []; 69 | expect(Array.isArray(arrayOfStrings)).toBe(true); 70 | //When you access an index of the array, but you haven't assigned a value, the array returns 'undefined' 71 | expect(arrayOfStrings[1]).toBeUndefined(); 72 | expect(arrayOfStrings.length).toBe(0); 73 | }); 74 | }); 75 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/08 - Functions.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Functions', function () { 4 | 5 | /*Functions*/ 6 | /*Functions take some input, then execute a series of statements using the input, and outputs a result*/ 7 | it('functions help write reusable code', function () { 8 | expect(addNumbers(1, 2)).toBe(3); 9 | expect(addNumbers(2, 3)).toBe(5); 10 | expect(addNumbers(1 + 1, 2 + 1)).toBe(5);//Parameters can also be expressions, which the function will resolve before starting 11 | var numberOne = 2; 12 | var numberTwo = 3; 13 | expect(addNumbers(numberOne, numberTwo)).toBe(5);//Parameters can also be variables 14 | }); 15 | 16 | //'function' keyword tells the compiler that you are defining a function 17 | function addNumbers(numberOne, numberTwo) { //The function's name follows the 'function' keyword and should indicate the function's purpose 18 | //Parameters are passed in a set of parentheses before the first curly brace 19 | return numberOne + numberTwo; 20 | //The return keyword works as a terminating statement and exits the function returning the value in front of it 21 | } //The statements that will be executed should be enclosed in curly braces. 22 | 23 | /*Scopes*/ 24 | it('Global and Local Variables', function () { 25 | /*Global Variables (on this scope)*/ 26 | var globalVariable = 1;//global variables could be accessed from anywhere in the program 27 | 28 | function addUsingGlobalVariable(localNumberOne) { 29 | //localNumberOne is a Local Variable and could only be accessed from the function's scope 30 | return globalVariable + localNumberOne; //Local and global variables can interact with each other 31 | } 32 | 33 | expect(addUsingGlobalVariable(1)).toBe(2); 34 | 35 | //You can modify the global variables inside any method 36 | function addToGlobalVariable(localNumberOne) { 37 | globalVariable = globalVariable + localNumberOne; 38 | } 39 | addToGlobalVariable(1); 40 | expect(globalVariable).toBe(2); 41 | }); 42 | it('A functions local variables are not available once the functions scope is closed', function () { 43 | 44 | var localVariable = 6; 45 | function localFunction() { 46 | var localVariable = 5; 47 | return localVariable; 48 | } 49 | localFunction(); 50 | expect(localVariable).toBe(6); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/09 - FunctionExpressions.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Function Expressions', function () { 4 | 5 | /*Function Expressions*/ 6 | /*We can build functions within code execution rather than at program load time*/ 7 | it('Normal functions are built in memory when the program loads', function () { 8 | expect(typeof addTwoNumbers).toBe("function"); 9 | }); 10 | function addTwoNumbers(numberOne,numberTwo){ 11 | return numberOne+numberTwo; 12 | } 13 | it('Assigning functions to variables allows them to only load them when the runtime executes that line', function () { 14 | var subtract = function subtractTwoNumbers(numberOne,numberTwo){ //In Js we can assign a function to a variable 15 | return numberOne-numberTwo; 16 | }; 17 | expect(typeof subtract).toBe("function"); //The variable is still considered a function 18 | expect(subtract(3,2)).toBe(1);// Then we can call the function variable by name 19 | }); 20 | it('We can create Anonymous Functions without a name', function () { 21 | var multiply = function (numberOne,numberTwo){ //The function is being assigned to variable, therefore, we don't need a name 22 | return numberOne*numberTwo; 23 | }; 24 | expect(multiply(3,2)).toBe(6); 25 | }); 26 | it('A variable that holds a function can be passed into other functions', function () { 27 | var divideTenByTwo = function (){ 28 | return 10/2; 29 | }; 30 | var divideTenByFive = function (){ 31 | return 10/5; 32 | }; 33 | expect(executeOperation(divideTenByTwo)).toBe(5); 34 | expect(executeOperation(divideTenByFive)).toBe(2); 35 | }); 36 | function executeOperation(operation){//You can encapsulate common functionality in a function 37 | return operation(); 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/10 - Closure.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Closure', function () { 4 | 5 | /*Closure*/ 6 | /*A closure wraps up an entire environment, binding necessary variables from other scopes*/ 7 | it('Normal functions are built in memory when the program loads', function () { 8 | 9 | function outsideClosure() { 10 | var closureVariable = "Closure Variable"; //This values is saved in the insideClosure 11 | function insideClosure() { 12 | return closureVariable;//The context of this function is saved in the outsideClosure 13 | } 14 | return insideClosure; 15 | } 16 | 17 | var insideClosure = outsideClosure(); 18 | expect(insideClosure()).toBe("Closure Variable"); 19 | }); 20 | it('Closures functions can modify bound variables in the background', function () { 21 | function outsideClosure() { 22 | var numberOfTimes = 0; 23 | function insideClosure() { 24 | numberOfTimes++; 25 | return numberOfTimes; 26 | } 27 | return insideClosure; 28 | } 29 | 30 | var insideClosureOne = outsideClosure(); 31 | insideClosureOne(); //Calling it one time increments numberOfTimes to 1 32 | insideClosureOne(); //Calling it two times increments numberOfTimes to 2 33 | //Calling it the third times increments numberOfTimes to 3 34 | expect(insideClosureOne()).toBe(3); 35 | }); 36 | it('Closures bind values at the very last opportunity ', function () { 37 | 38 | function outsideClosure() { 39 | var key = 3; 40 | var insideFunction; 41 | for (var currentNumber = 0; currentNumber < 6; currentNumber++) { 42 | if (currentNumber === key) { 43 | //Although we match the key 3, the loop continues and the function will always 44 | //set the value to the last iteration of the loop 45 | insideFunction = function insideClosure() { 46 | return currentNumber; 47 | } 48 | } 49 | } 50 | return insideFunction; 51 | } 52 | var insideClosure = outsideClosure(); 53 | expect(insideClosure()).toBe(6);//The closure respects the final state of the variables 54 | }); 55 | 56 | }); 57 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/11 - FunctionExpressionsAsParameters.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Function Expressions as Parameters', function () { 4 | 5 | /*Function Expressions as Parameters*/ 6 | it('Map function takes in a function as a parameter and returns a new array with the results', function () { 7 | var numbers = [1, 2, 3, 4, 5]; 8 | var results = numbers.map( 9 | //We build an anonymous functions for map's parameter, it takes in the contents of each cell of numbers and returns an operation using the cell's value 10 | function (arrayCell) { 11 | return arrayCell * 2; 12 | } 13 | );// results = [2, 4, 6, 8, 10]; 14 | for (var currentNumberIndex = 0; currentNumberIndex < numbers.length; currentNumberIndex++) { 15 | expect(results[currentNumberIndex]).toBe(numbers[currentNumberIndex] * 2); //The map function allows us to perform a condensed loop in one statement 16 | } 17 | }); 18 | it('Functions can return Function expressions', function () { 19 | var concatenatingStringToRightFunction = concatenateString("rightSide"); 20 | expect(concatenatingStringToRightFunction("First")).toBe("FirstString"); 21 | var concatenatingStringToLeftFunction = concatenateString("leftSide"); 22 | expect(concatenatingStringToLeftFunction("Second")).toBe("StringSecond"); 23 | }); 24 | it('Functions can return Function expressions without using an intermediate variable', function () { 25 | //By using parenthesis we invoke the returning function 26 | expect(concatenateString("rightSide")("First")).toBe("FirstString"); 27 | }); 28 | 29 | function concatenateString(side) { 30 | 31 | if (side === "rightSide") { 32 | return function (stringValue) { 33 | return stringValue + "String"; 34 | }; 35 | } 36 | if (side === "leftSide") { 37 | 38 | return function (stringValue) { 39 | return "String"+stringValue; 40 | }; 41 | } 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/12 - Hoisting.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Hoisting', function () { 4 | 5 | /*Hoisting*/ 6 | /*JavaScript's default behavior of moving declarations to the top.*/ 7 | it('Javascript loads functions and variables that need space in memory first', function () { 8 | 9 | function Universe() { 10 | //This variable is loaded as var variableInMemory = undefined; 11 | var variableInMemory = functionResult(); 12 | return variableInMemory; 13 | 14 | function functionResult() { //This function gets loaded at the top 15 | return 5; 16 | } 17 | } 18 | 19 | expect(Universe()).toBe(5); 20 | }); 21 | it('Hoisting functions with the same name get overridden', function () { 22 | 23 | function Universe() { 24 | 25 | function functionResult() { //This function gets loaded at the top at first 26 | return 3; 27 | } 28 | return functionResult(); 29 | 30 | function functionResult() { //This function gets loaded at the after the first function, since it has the same name, the first function is destroyed 31 | return 5; 32 | } 33 | } 34 | 35 | expect(Universe()).toBe(5); 36 | }); 37 | it('Function Expressions are never hoisted', function () { 38 | 39 | function Universe() { 40 | try { 41 | return functionVariable(); 42 | } catch (e) { 43 | return "NotLoaded"; 44 | } 45 | var functionVariable = function functionResult() { //This function is never reached since it exists after the return statement 46 | return 5; 47 | } 48 | } 49 | expect(Universe()).toBe("NotLoaded"); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/13 - Objects.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Objects', function () { 4 | 5 | /*Objects*/ 6 | /* Containers of related information */ 7 | it('You can build objects using different types', function () { 8 | 9 | var person = { // to allocate memory for an Object, you need the '{}' 10 | firstName : "Martin", //You can assign strings to properties 11 | age : 27// You can assign numbers to properties 12 | }; 13 | 14 | expect(person.firstName).toBe("Martin");//We can access an object's property with a dot 15 | expect(person.age).toBe(27);//We can access all the object's properties 16 | }); 17 | 18 | it('You can build objects with the Object construct', function () { 19 | 20 | // Use the 'new' keyword followed by a call for the Object construct 21 | var person = new Object(); 22 | person.firstName = "Martin"; 23 | person.age = 27; 24 | 25 | expect(person.firstName).toBe("Martin"); 26 | expect(person.age).toBe(27); 27 | }); 28 | 29 | it('You can change the property values of an object', function () { 30 | 31 | var person = { 32 | firstName : "Corrie", 33 | age : 27 34 | }; 35 | person.firstName = "Martin"; //The dot operator allows modification of properties 36 | expect(person.firstName).toBe("Martin"); 37 | }); 38 | 39 | it('You can assign Arrays as properties values', function () { 40 | 41 | var programmingLanguages = ['C#','Javascript']; 42 | 43 | var person = { 44 | firstName : "Martin", 45 | programmingLanguages : programmingLanguages // You are assigning a reference to the array 46 | }; 47 | person.programmingLanguages.push('Java'); 48 | expect(person.programmingLanguages[2]).toBe('Java'); 49 | expect(person.programmingLanguages.length).toBe(programmingLanguages.length); //the property and the array have the same length since we pushed the item to the same array 50 | }); 51 | 52 | it('You can add new properties to objects after they have been created', function () { 53 | 54 | var person = { 55 | firstName : "Martin" 56 | }; 57 | 58 | person.lastName = "Chavez"; //If the property does not exists on the object, it gets created at runtime 59 | expect(person.lastName).toBe("Chavez"); 60 | }); 61 | 62 | it('You can use brackets on Objects to access properties', function () { 63 | 64 | var person = { 65 | firstName : "Martin" 66 | }; 67 | 68 | expect(person["firstName"]).toBe("Martin"); 69 | }); 70 | 71 | it('You can place string-based expressions in the brackets to construct specific property names', function () { 72 | 73 | var person = { 74 | name1 : "Martin", 75 | name2 : "Chavez", 76 | name3 : "Aguilar" 77 | }; 78 | 79 | expect(person["name" + 1]).toBe("Martin"); 80 | expect(person["name" + 2]).toBe("Chavez"); 81 | expect(person["name" + 3]).toBe("Aguilar"); 82 | 83 | }); 84 | 85 | it('You can delete properties with the delete keyword', function () { 86 | 87 | var person = { 88 | firstName : "Martin", 89 | age : 27 90 | }; 91 | 92 | delete person.age; //delete keyword deletes the property value and the property itself 93 | 94 | expect(person["age"]).toBeUndefined(); 95 | }); 96 | 97 | }); 98 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/14 - ObjectsFunctionality.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Object Functionality', function () { 4 | 5 | /*Object Functionality*/ 6 | 7 | it('Properties can be functions', function () { 8 | 9 | var person = { 10 | firstName : "Martin", 11 | age : 27, 12 | //Properties that hold a function are often called methods 13 | updateAge : function(newAge){ 14 | //'this' keyword always refers to the owner Object of the function 15 | this.age = newAge; 16 | } 17 | }; 18 | person.updateAge(28); 19 | expect(person.age).toBe(28); 20 | 21 | }); 22 | it('Methods can be created after the Objects creation', function () { 23 | 24 | var person = { 25 | firstName : "Martin", 26 | age : 27 27 | }; 28 | person.updateAge = function(newAge){ 29 | //'this' keyword references the person's object 30 | this.age = newAge; 31 | } 32 | person.updateAge(28); 33 | expect(person.age).toBe(28); 34 | }); 35 | 36 | it('Methods functions are loosely tied to the objects they are attached to', function () { 37 | 38 | var person = { 39 | firstName : "Martin", 40 | age : 27, 41 | updateAge : function(newAge){ 42 | this.age = newAge; 43 | } 44 | }; 45 | 46 | // Using the call method, you can specify any object you want to use instead of 'this' 47 | person.updateAge.call({firstName: "Corrie", age: 28}); 48 | expect(person.age).toBe(27);//The original age is still the same 49 | }); 50 | 51 | it('Objects do not have a native length property', function () { 52 | 53 | var person = { 54 | firstName : "Martin", 55 | age : 27 56 | }; 57 | //we cannot iterate through objects the same way we iterate Arrays 58 | expect(person.length).toBeUndefined(); 59 | }); 60 | 61 | it('To iterate through an object we need to use the for-in loop', function () { 62 | 63 | var person = { 64 | firstName : "Martin", 65 | age : 27 66 | }; 67 | 68 | for(var propertyName in person){ 69 | //We iterate all properties, they have to match the names of the object 'person' 70 | var foundProperty = (propertyName === "firstName" || propertyName === "age"); 71 | expect(foundProperty).toBe(true); 72 | } 73 | }); 74 | }); 75 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/15 - ObjectPrototype.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Object Prototype', function () { 4 | 5 | /*Useful Properties in the Object Prototype*/ 6 | it('you can use valueOf to retrieve the primitive type associated with an object', function () { 7 | var fiveNumber = 5; 8 | var fiveString = "5"; 9 | 10 | expect(fiveNumber.valueOf()).toBe(5); 11 | expect(fiveString.valueOf()).toBe("5"); 12 | // '==' operator performs Type Coercion which turns a number contained in a string into an actual number 13 | expect(fiveNumber.valueOf() == fiveString.valueOf()).toBe(true); 14 | // '===' operator does not ignore the type of the value 15 | expect(fiveNumber.valueOf() === fiveString.valueOf()).toBe(false); 16 | 17 | }); 18 | 19 | it('you can use valueOf to retrieve the type of an object', function () { 20 | function Person (firstName ){ 21 | this.firstName = firstName; 22 | } 23 | Person.prototype = {}; 24 | var person = new Person("Martin"); 25 | expect(person.valueOf()).toEqual(Object({ firstName: 'Martin' })); 26 | }); 27 | 28 | it('you can override properties of prototypes, even if these are inherited', function () { 29 | function Person (firstName ){ 30 | this.firstName = firstName; 31 | } 32 | Person.prototype.valueOf = function() { 33 | return this.firstName; 34 | }; 35 | var person = new Person("Martin"); 36 | expect(person.valueOf()).toBe("Martin"); 37 | person.firstName = "Corrie"; 38 | //the value of ValueOf is retrieved every time, even if the object's property changes 39 | expect(person.valueOf()).toBe("Corrie"); 40 | 41 | }); 42 | 43 | it('you can use toString() method to convert variables into a string', function () { 44 | var fiveNumber = 5; 45 | var fiveString = "5"; 46 | 47 | expect(fiveNumber.toString()).toBe("5"); 48 | //there is no effect in using toString() for strings 49 | expect(fiveString.toString()).toBe("5"); 50 | 51 | var fiveDotTwo = 5.2; //toString() also works with numbers and decimals 52 | expect(fiveDotTwo.toString()).toBe("5.2"); 53 | 54 | var array = [1,2,3]; //toString() converts Arrays into a comma-separated string 55 | expect(array.toString()).toBe("1,2,3"); 56 | 57 | }); 58 | 59 | it('you can use constructor keyword to find the nearest prototype ancestor ', function () { 60 | 61 | function Person (firstName ){ 62 | this.firstName = firstName; 63 | } 64 | Person.prototype.lastName = function() { 65 | return "Chavez"; 66 | }; 67 | var person = new Person("Martin"); 68 | 69 | expect(person.constructor.name).toEqual("Person"); 70 | //the prototype of a Class is an object 71 | expect(typeof(person.constructor.prototype)).toEqual('object'); 72 | //the prototype method 'lastName' of Person is a function which returns a string 73 | expect(typeof(person.constructor.prototype.lastName())).toEqual('string'); 74 | expect(person.constructor.prototype.lastName()).toEqual('Chavez');//every instance of the class Person share the prototype property 75 | expect(person.__proto__.lastName()).toEqual('Chavez');//another way of finding a Class Prototype is with the keyword '__proto__' 76 | }); 77 | 78 | it('you can use hasOwnProperty to identify the property location', function () { 79 | 80 | function Person (firstName ){ 81 | this.firstName = firstName; 82 | } 83 | Person.prototype.lastName = function() { 84 | return "Chavez"; 85 | }; 86 | var person = new Person("Martin"); 87 | 88 | expect(person.hasOwnProperty('lastName')).toEqual(false); 89 | expect(person.constructor.hasOwnProperty('lastName')).toEqual(false); 90 | expect(person.__proto__.hasOwnProperty('lastName')).toEqual(true); 91 | }); 92 | 93 | }); 94 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/16 - Prototypes.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Prototypes', function () { 4 | 5 | /*Prototypes*/ 6 | /* Objects have properties that belong to and come from the Object's (parent of all object's) prototype*/ 7 | /* A Prototype is a blueprint Object for the Object we are trying to create*/ 8 | /* 9 | * Inheritance: Allows code reuse by sharing properties and methods in similar objects 10 | * 11 | * Object Prototype => Array Prototype, String Prototype, Number Prototype, Function Prototype 12 | * 13 | * */ 14 | it('Properties can be functions', function () { 15 | 16 | var string = "String Variable"; //This string variable inherits all the properties from the String Prototype and Object Prototype 17 | 18 | //hasOwnProperty and constructor are both properties of Object, not String, but we can still use hasOwnProperty, this is achieved due to the prototype chain 19 | expect(string.hasOwnProperty('constructor')).toBe(false); 20 | expect(Object.constructor.prototype.hasOwnProperty('constructor')).toBe(true); 21 | //'charAt' is a property of the String Prototype, therefore the prototype chain stops there and does not 'query' the Object prototype for such property 22 | expect(string.charAt(1)).toBe('t'); 23 | 24 | }); 25 | 26 | /*You can add base functionality to all objects of the same type*/ 27 | it('Adding a new function into the Strings Prototype', function () { 28 | //.prototype finds the prototype for all Strings values 29 | String.prototype.lengthPlusOne = function (){ // By adding a function to the String Prototype,it makes it inheritable by all the Strings 30 | return this.length+1; 31 | }; 32 | //Now all strings can use this new property 33 | expect("String".lengthPlusOne()).toBe(7); 34 | 35 | }); 36 | 37 | /*Constructors*/ 38 | it('Using Inheritance, we can create new Objects with our existing Objects as Prototypes', function () { 39 | var person = { firstName: "Martin" , age: 27}; 40 | 41 | var newPerson = Object.create(person); //The first argument of the Object.create method will be used as the prototype of the newly created Object 42 | //The newPerson Object inherited all of the properties from person 43 | expect(newPerson.firstName).toBe("Martin"); 44 | expect(newPerson.age).toBe(27); 45 | 46 | }); 47 | 48 | it('You can add new properties to an object without modifying the parent prototype', function () { 49 | var person = { firstName: "Martin" , age: 27}; 50 | var newPerson = Object.create(person); 51 | newPerson.lastName = "Chavez"; 52 | 53 | expect(newPerson.lastName).toBe("Chavez"); 54 | expect(person.lastName).toBeUndefined(); //property 'lastName' does not exists on person object 55 | }); 56 | 57 | it('You can verify that an object is a prototype of another object', function () { 58 | var person = { firstName: "Martin" , age: 27}; 59 | var newPerson = Object.create(person); 60 | 61 | expect(Object.prototype.isPrototypeOf(newPerson)).toBe(true); 62 | expect(person.isPrototypeOf(newPerson)).toBe(true); 63 | //The isPrototypeOf method will look upward through the entire hierarchy (prototype chain) 64 | //to see whether the Object.prototype Object is a prototypical ancestor of newPerson 65 | expect(newPerson.isPrototypeOf(person)).toBe(false); 66 | }); 67 | 68 | it('You can create generic objects and build all the inherited objects with such properties', function () { 69 | var person = { firstName: undefined , lastName: undefined , age: undefined}; 70 | var newPerson = Object.create(person); 71 | 72 | newPerson.firstName = "Martin"; 73 | newPerson.lastName = "Chavez"; 74 | newPerson.age = 27; 75 | 76 | expect(newPerson.firstName).toBe("Martin"); 77 | }); 78 | 79 | /*Class : Set of Objects that inherit properties from the same prototype*/ 80 | 81 | it('You can create Constructors that allow to set up inheritance while also assigning specific property values', function () { 82 | //Capitalizing this function's name distinguishes it as a maker of an entire "Class" of objects 83 | function Person (firstName, lastName ,age){ 84 | //'this' keyword inside a constructor will automatically refer to the new instance of the class that is being made 85 | this.firstName = firstName; 86 | this.lastName = lastName; 87 | this.age = age; 88 | } 89 | 90 | //'new' keyword produces a new Object of the specified class 91 | var martinPerson = new Person("Martin", "Chavez", 27); 92 | 93 | expect(martinPerson.firstName).toBe("Martin"); 94 | expect(martinPerson.lastName).toBe("Chavez"); 95 | expect(martinPerson.age).toBe(27); 96 | }); 97 | 98 | it('You can assign a prototype to a constructor', function () { 99 | function Person (firstName, lastName ,age){ 100 | this.firstName = firstName; 101 | this.lastName = lastName; 102 | this.age = age; 103 | } 104 | //Setting a constructor prototype property allows the instances to access these properties 105 | Person.prototype = { 106 | address: "House 123" 107 | }; 108 | var martinPerson = new Person("Martin", "Chavez", 27); //There is no need to define the address for each person 109 | expect(martinPerson.address).toBe("House 123"); 110 | 111 | }); 112 | it('You can modify the message functions in a prototype to use the data values in the calling instance', function () { 113 | function Person (firstName, lastName){ 114 | this.firstName = firstName; 115 | this.lastName = lastName; 116 | } 117 | 118 | Person.prototype = { 119 | //'this' keyword searches for the particular Object(Person) that called the inherited function and retrieves the data from it 120 | fullName: function() { return(this.firstName + " " + this.lastName); } 121 | }; 122 | var martinPerson = new Person("Martin", "Chavez"); 123 | 124 | expect(martinPerson.fullName()).toBe("Martin Chavez"); 125 | }); 126 | 127 | it('You can use prototype chaining to reuse functionality', function () { 128 | function Person (firstName, lastName){ 129 | this.firstName = firstName; 130 | this.lastName = lastName; 131 | this.blackHair = true; 132 | } 133 | 134 | function Baby(firstName, lastName){ 135 | //You can call the Person constructor within the Baby constructor 136 | Person.call(this,firstName, lastName); 137 | // We need to add a reference to this Object constructor, otherwise it will use the Person constructor 138 | this.constructor = Baby; 139 | } 140 | 141 | // By setting a parent object as a constructors prototype, objects build with that construct gain access to 142 | // all the methods on that object, including the methods on its contractor prototype and so on 143 | Baby.prototype = new Person(); 144 | 145 | // You can also add specific methods to this prototype 146 | Baby.prototype.cry = function(){ 147 | this.isCrying = true; 148 | }; 149 | 150 | var baby = new Baby("Martin", "Chavez"); 151 | baby.cry(); 152 | 153 | // Property from the Baby object 154 | expect(baby.isCrying).toBeTruthy(); 155 | expect(baby.firstName).toBe("Martin"); 156 | expect(baby.lastName).toBe("Chavez"); 157 | expect(baby.constructor).toBe(Baby); 158 | // Property from the Person object 159 | expect(baby.blackHair).toBe(true); 160 | }); 161 | 162 | /*Performance Optimizations*/ 163 | 164 | it('You can improve the memory efficiency of the program by adding common functionality on the objects prototype', function () { 165 | function Person (firstName, lastName){ 166 | this.firstName = firstName; 167 | this.lastName = lastName; 168 | } 169 | 170 | Person.prototype = { 171 | //By adding this array to the prototype, we don't have to create an array every time we create a Person's object 172 | longArray : [0,1,2,3,4,5,6,7,8,9] 173 | }; 174 | var martinPerson = new Person("Martin", "Chavez"); 175 | var corriePerson = new Person("Corrie", "McQueen"); 176 | 177 | expect(martinPerson.longArray[8]).toBe(8); 178 | expect(corriePerson.longArray[8]).toBe(8); 179 | }); 180 | 181 | }); 182 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/17 - LogicalAssignment.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Logical Assignment', function () { 4 | 5 | /*Logical Operators can make conditional assignments.*/ 6 | 7 | it('You can make assignments with ternary conditions', function () { 8 | var object = { 9 | addValueToArray : function(value){ 10 | //We can verify that this.objectArray previously exists (it is looking for a truthy value), if that is the case, return the same value 11 | //Otherwise, return a new array 12 | this.objectArray = this.objectArray ? this.objectArray : []; 13 | this.objectArray.push(value); 14 | } 15 | }; 16 | expect(object.objectArray).toBeUndefined(); 17 | object.addValueToArray(5); 18 | expect(object.objectArray[0]).toBe(5); 19 | }); 20 | it('You can make assignments with logical operators making the code less verbose', function () { 21 | var object = { 22 | addValueToArray : function(value){ 23 | //Using the || during assignment, it will return the first Truthy value 24 | this.objectArray = this.objectArray || []; 25 | this.objectArray.push(value); 26 | } 27 | }; 28 | expect(object.objectArray).toBeUndefined(); 29 | object.addValueToArray(5); 30 | expect(object.objectArray[0]).toBe(5); 31 | }); 32 | it('Logical Operators results for ||', function () { 33 | //The || assignment returns the first truthy value 34 | expect(4||5).toBe(4); 35 | //If some values are truthy and others are falsy, the || assignment returns the first truthy value 36 | expect(4||0).toBe(4); 37 | expect(0||4).toBe(4); 38 | //If all values are falsy, the || assignment returns the last element 39 | expect(0||""||undefined).toBeUndefined(); 40 | }); 41 | 42 | it('Logical Operators results for &&', function () { 43 | //The && assignment returns the right-most truthy value 44 | expect(4&&5).toBe(5); 45 | expect(5&&4).toBe(4); 46 | //The && assignment returns the first falsy value 47 | expect(4&&5&&0).toBe(0); 48 | expect(5&&4&&undefined).toBeUndefined(); 49 | expect(""&&null&&0).toBe(""); 50 | 51 | //If all values are truthy, the && assignment returns the last element 52 | expect(1&&2&&3).toBe(3); 53 | }); 54 | 55 | }); 56 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/18 - SwitchBlock.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Switch Block', function () { 4 | 5 | /*Switch Block*/ 6 | /*A conditional for multiple possibilities*/ 7 | it('Switch keyword allows to invoke an expression based on a value', function () { 8 | var country = "Italy"; 9 | var capital; 10 | 11 | /*The switch block contains multiple case's, where the case keyword is followed by one or more expressions*/ 12 | /*Cases in Javascript allow execution Fall-through, which means, that once you find a matching case, it will continue executing all the cases*/ 13 | switch(country){ 14 | case "Mexico" : capital = "Mexico City"; 15 | case "Germany" : capital = "Berlin"; 16 | case "Italy" : capital = "Rome"; 17 | case "USA" : capital = "Washington DC"; 18 | } 19 | expect(capital).toBe("Washington DC"); 20 | }); 21 | 22 | it('Switch blocks require break to remove fall-through', function () { 23 | var country = "Germany"; 24 | var capital; 25 | 26 | /*'break' keyword will allow us to remove the fall-through of the cases */ 27 | switch(country){ 28 | case "Mexico" : capital = "Mexico City"; break; 29 | case "Germany" : capital = "Berlin"; break; 30 | case "Italy" : capital = "Rome"; break; 31 | case "USA" : capital = "Washington DC"; break; 32 | } 33 | expect(capital).toBe("Berlin"); 34 | }); 35 | 36 | it('Switch blocks allows joining cases for which you want to execute the same action', function () { 37 | var country = "Italy"; 38 | var currency; 39 | 40 | switch(country){ 41 | case "Mexico" : currency = "Peso"; break; 42 | case "Germany" : 43 | case "Italy" : currency = "Euro"; break; 44 | case "USA" : currency = "Dollar"; break; 45 | } 46 | expect(currency).toBe("Euro"); 47 | }); 48 | 49 | it('On a Switch block, when there is no matching case, no action is executed', function () { 50 | var country = "Turkey"; 51 | var currency; 52 | 53 | switch(country){ 54 | case "Mexico" : currency = "Peso"; break; 55 | case "Germany" : 56 | case "Italy" : currency = "Euro"; break; 57 | case "USA" : currency = "Dollar"; break; 58 | } 59 | expect(currency).toBeUndefined(); 60 | }); 61 | 62 | it('On a Switch block, when there is no matching case, we can specify the desired action with the default keyword', function () { 63 | var country = "Turkey"; 64 | var currency; 65 | 66 | switch(country){ 67 | case "Mexico" : currency = "Peso"; break; 68 | case "Germany" : 69 | case "Italy" : currency = "Euro"; break; 70 | case "USA" : currency = "Dollar"; break; 71 | default : currency = "Unknown"; break; 72 | } 73 | expect(currency).toBe("Unknown"); 74 | }); 75 | 76 | }); 77 | -------------------------------------------------------------------------------- /LearnJavascript/Topics/19 - GeneralPerformance.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('General Performance Concepts', function () { 4 | 5 | /*Script Execution 6 | 7 | - A Browser can download up to 6 components at the same time (parallel download) 8 | - A browser stops downloading when it encounters a script tag