diff --git a/.bookignore b/.bookignore new file mode 100644 index 0000000..47f6177 --- /dev/null +++ b/.bookignore @@ -0,0 +1,5 @@ +.grunt +.bookignore +.gitignore +Gruntfile.js +package.json \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..f38c41f --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,35 @@ +var path = require("path"); + +module.exports = function (grunt) { + grunt.loadNpmTasks('grunt-gitbook'); + grunt.loadNpmTasks('grunt-gh-pages'); + grunt.loadNpmTasks('grunt-contrib-clean'); + + grunt.initConfig({ + 'gitbook': { + development: { + output: path.join(__dirname, ".grunt/gitbook"), + input: "./", + title: "Javascript Challenges", + description: "Challenge your self to learn and understand the most obscure and tricky parts of Javascript.", + github: "tcorral/javascript-challenges-book" + } + }, + 'gh-pages': { + options: { + base: '.grunt/gitbook' + }, + src: ['**'] + }, + 'clean': { + files: '.grunt' + } + }); + + grunt.registerTask('publish', [ + 'gitbook', + 'gh-pages', + 'clean' + ]); + grunt.registerTask('default', 'gitbook'); +}; \ No newline at end of file diff --git a/README.md b/README.md index c365565..6608a25 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,12 @@ # Javascript Challenges -This book will challenge you to get and understand the most obscure and tricky parts of Javascript. +This book will challenge you to learn and understand the most obscure and tricky parts of Javascript. -I hope you enjoy this book. +In order to perform the best that you can I recommend you not to cheat taking a look at solutions before you suggest one. + +This book can be used as a learning resource for Javascript training if you want, but please send a tweet recommending us to other people. + +I hope you enjoy this book because this is the purpose of this book. + +Feedback is welcome. + +Thanks a lot to [GITBOOK team](http://www.gitbook.io/) for it's amazing project to write your own books using Github repos. diff --git a/SUMMARY.md b/SUMMARY.md index a281170..7c449fc 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -11,4 +11,22 @@ * [Don't judge a book by its cover](utf8/README.md) * [Encapsulate collection](encapsulate_collection/README.md) * [Even or Odd](even_odd/README.md) -* [Exit nested loop](nested_loop/README.md) \ No newline at end of file +* [Exit nested loop](nested_loop/README.md) +* [#1 Fooling around boolean](fooling_around_boolean/README.md) +* [#2 Fooling around boolean](fooling_around_boolean_2/README.md) +* [Ghost Array](ghost_array/README.md) +* [Input Search](input_search/README.md) +* [Invaluable](invaluable/README.md) +* [JSON](json/README.md) +* [Nested Scopes](nested_scopes/README.md) +* [Now you see me...](now_you_see_me/README.md) +* [Frozen](frozen/README.md) +* [Point](point/README.md) +* [Running Man](running_man/README.md) +* [Scope](scope/README.md) +* [Spartacus](spartacus/README.md) +* [Terminator](terminator/README.md) +* [Timers](timers/README.md) +* [Undefined Values in Arrays](undefined_values_in_array/README.md) +* [Array Map and ParseInt](array_map_parseint/README.md) +* [Variable Scope](variable_scope/README.md) \ No newline at end of file diff --git a/array_map_parseint/README.md b/array_map_parseint/README.md new file mode 100644 index 0000000..419984a --- /dev/null +++ b/array_map_parseint/README.md @@ -0,0 +1,63 @@ +# Using Array.prototype.map and parseInt + +## Snippet 1 +``` +var result = ['1','10','100','1000','10000', '100000', '1000000'].map(parseInt) +``` + +## Expected +``` +var result = [1, 10, 100, 1000, 10000, 100000, 100000]; +``` +--- +What's the result of executing Snippet 1 code? +```js +var result = ; +``` +```js +var result = [1, NaN, 4, 27, 256, 3125, 46656]; +``` +```js +assert(result[0] === 1 && isNaN(result[1]) && result[2] === 4 && result[3] === 27 && result[4] === 256 &&& result[5] === 3125 && result[6] === 46656); +``` +--- + +--- +Why? +```js + +``` +```js +Array.prototype.map has three arguments that pass to the callback we set as argument: +* value +* index +* arr +When we check the specifications of parseInt we can see that parseInt could receive two arguments. +The former is the string to be parsed and the latter is the ratio to convert the value. + +When we execute the previous code, this is that it's executed when we run the Snippet 1 code: + * parseInt(1, 0) => 1 + * parseInt(10, 1) => NaN + * parseInt(100, 2) => 4 + * parseInt(1000, 3) => 27 + * parseInt(10000, 4) => 256 + * parseInt(100000, 5) => 3125 + * parseInt(1000000, 6) => 46656 +``` +```js +assert(true); +``` +--- + +--- +We need to get the same array as in Expected 1, please fix the code: +```js +var result = ['1','10','100','1000','10000', '100000', '1000000'].map(parseInt) +``` +```js +var result = ['1','10','100','1000','10000', '100000', '1000000'].map(Number) +``` +```js +assert(result[0] === 1 && result[1] === 10 && result[2] === 100 && result[3] === 1000 && result[4] === 10000 && result[5] === 100000 && result[6] === 1000000 ); +``` +--- \ No newline at end of file diff --git a/autoexecute/README.md b/autoexecute/README.md index 60a3dda..5091b63 100644 --- a/autoexecute/README.md +++ b/autoexecute/README.md @@ -3,8 +3,8 @@ I want to set variable 'a' to 3 using a Self Invoking Function, can you help me? ``` -var a; -function test() { a = 3; }(); +var testValue; +function test() { testValue = 3; }(); ``` --- @@ -27,7 +27,7 @@ assert(true); --- -What is the value of variable 'a'? +What is the value of variable 'testValue'? ```js @@ -53,7 +53,7 @@ Why? ``` ```js - +The value of testValue is undefined because the function has not been autoexecuted. ``` ```js @@ -67,17 +67,17 @@ assert(true); Write the code to execute this function adding only one more character to the sentence. ```js -var a; -function test() { a = 3; }(); +var testValue; +function test() { testValue = 3; }(); ``` ```js -var a; -!function test() { a = 3; }(); +var testValue; +!function test() { testValue = 3; }(); ``` ```js -assert(a == 3); +assert(testValue == 3); ``` --- \ No newline at end of file diff --git a/banking/README.md b/banking/README.md index 261f65d..be7f030 100644 --- a/banking/README.md +++ b/banking/README.md @@ -25,7 +25,7 @@ var yourChange = calculateChange(); What returns calculateAmountOfStockOptions ? Input the number value. ```js -var stockOptions = +var stockOptions = ; ``` ```js @@ -43,7 +43,7 @@ assert(stockOptions == 1.94392523364486); What is the value of calculateChange ? Input the number value. ```js -var change = +var change = ; ``` ```js @@ -65,7 +65,7 @@ Why? ``` ```js - +'Javascript has several problems operating with floating point, this is one of the causes that it should not be to operate with floats.' ``` ```js diff --git a/conditionals_functions/README.md b/conditionals_functions/README.md index 5987f5d..56e9fc4 100644 --- a/conditionals_functions/README.md +++ b/conditionals_functions/README.md @@ -59,7 +59,9 @@ What's the reason of this behaviour? ``` ```js - +The execution of Snippet 1 shows "That's true" because function expressions are evaluated in execution time. +The execution of Snippet 2 shows "That's false" because function declarations are evaluated in evaluation time, and the second one overwrittes the first one. +The execution of Snippet 3 shows "That's true" because when the code has been evaluated it has changed to the function that could return "That's false" but when the code has been executed it has been overwritten again with the function expression. ``` ```js diff --git a/delete/README.md b/delete/README.md index bfc1896..ef1c5c4 100644 --- a/delete/README.md +++ b/delete/README.md @@ -13,6 +13,7 @@ Animal = function(){}; Animal.prototype.name = 'animal'; mammal = new Animal(); +mammal.name = 'mammal'; delete name; @@ -46,57 +47,65 @@ The execution of this code logs: ``` --- -Why #1: John is logged? + +Why **#1: John** is logged? ```js ``` ```js - +John is logged because name is a global variable and global variables can't be deleted. ``` ```js assert(true); ``` + --- --- -Why #2: undefined is logged? + +Why **#2: undefined** is logged? ```js ``` ```js - +undefined is logged because we have deleted the name property of obj, properties or members of objects can be deleted excluding the properties or members of the global object. ``` ```js assert(true); ``` + --- --- -Why #3: function toString() { [native code] } is logged? + +Why **#3: function toString() { [native code] }** is logged? ```js ``` ```js - +function toString() { [native code] } is logged because toString is an inherited method from Object and inherited methods or members can't be deleted. ``` ```js assert(true); ``` + --- --- -Why #4: animal is logged? + +Why **#4: animal** is logged? ```js ``` ```js - +animal is logged because we have deleted the own mammal.name property but the inherited property is shown. ``` ```js assert(true); ``` + --- \ No newline at end of file diff --git a/even_odd/README.md b/even_odd/README.md index 7049980..d748827 100644 --- a/even_odd/README.md +++ b/even_odd/README.md @@ -53,7 +53,7 @@ Please explain why Number.MAX_VALUE has not been added: ``` ```js - +Number.MAX_VALUE can't be handled properly by Javascript to work with it in operations because the overflow issue. ``` ```js diff --git a/fooling_around_boolean/README.md b/fooling_around_boolean/README.md new file mode 100644 index 0000000..ae14e0c --- /dev/null +++ b/fooling_around_boolean/README.md @@ -0,0 +1,41 @@ +# #1 Fooling around boolean + +Look at the following "implementation" of a xor method on the prototype of the Boolean type. + +``` +Boolean.prototype.xor = function ( value ) { return !!this !== !!value; }; +``` + +When we execute the following statement we get an unexpected result. + +``` +false.xor(false); // => true +``` + +--- +Why does xor resolves in an unexpected manner? + +```js + +``` +```js +Because this is not false, this inside the function is the complete object and it evaluates to true when it's converted to true the same way that !!{} is true. +``` +```js +assert(true); +``` + +--- + +--- +Write the code to fix the implementation of xor method: +```js +Boolean.prototype.xor = function ( value ) { return !!this !== !!value; }; +``` +```js +Boolean.prototype.xor = function ( value ) { return !!this.valueOf() !== !!value; }; +``` +```js +assert(false.xor(false) === false); +``` +--- \ No newline at end of file diff --git a/fooling_around_boolean_2/README.md b/fooling_around_boolean_2/README.md new file mode 100644 index 0000000..036438b --- /dev/null +++ b/fooling_around_boolean_2/README.md @@ -0,0 +1,44 @@ +# #2 Fooling around boolean + +All the following statements are true + +``` +!!{} == true; +``` +``` +[] == false; +``` + +We have the following code: + +``` +var hasTruthyStuff = function (aSymbols) { + var nResult = 0, + i = 0, + nLen = aSymbols.length; + + for (; i < nLen; i++) { + nResult |= aSymbols[i]; + } + return !!nResult; +}; +``` +But when we execute the following statement it returns false when we expected to return true because {} should return true. + +``` +hasTruthyStuff([{},[], 0]) +``` + +--- +Why does calling the previous statement returns false? + +```js + +``` +```js +You have to be careful when using |= because when it's used to perform a test besides an object it will not modify the original value, then it remains to be zero. +``` +```js +assert(true); +``` +--- \ No newline at end of file diff --git a/frozen/README.md b/frozen/README.md new file mode 100644 index 0000000..347a70f --- /dev/null +++ b/frozen/README.md @@ -0,0 +1,42 @@ +#Frozen +This challenge will need a bit of knowledge of one of the new features in Javascript 1.8.5, this feature is Object.freeze to get the correct result. + +--- +Assume: +* You can use anything of ECMASCRIPT 5 but not DOM or BOM, just Javascript +* There are more than one answer but only the most simple will win. + +Here you have the code to be fixed: +```js +var dog = { + sound: 'Bark!' +}; + +Object.freeze(dog); + +/* Put your code here */ + +//This method should return 'Bark!' +var result = dog.talk(); +``` + +```js +var dog = { + sound: 'Bark!' +}; + +Object.freeze(dog); + +Object.prototype.talk = function () { + return this.sound; +}; + +//This method should return 'Bark!' +var result = dog.talk(); +``` + +```js +assert( result === 'Bark!'); +``` + +--- \ No newline at end of file diff --git a/ghost_array/README.md b/ghost_array/README.md new file mode 100644 index 0000000..736e63b --- /dev/null +++ b/ghost_array/README.md @@ -0,0 +1,167 @@ +# Ghost Array + +Take a look at this code: + +## Snippet 1 +``` +var arr = []; +arr[999] = 'john'; +console.log(arr.length); +``` + +--- +What is the result of execute "Snippet 1" code? + +```js +var result = ; +``` +```js +var result = 1000; +``` +```js +assert(result === 1000); +``` +--- + +## Snippet 2 +``` +var arr = []; +arr[4294967295] = 'james'; +console.log(arr.length); +``` + +--- +What is the result of execute "Snippet 2" code? + +```js +var result = ; +``` +```js +var result = 0; +``` +```js +assert(result === 0); +``` +--- + +--- +Why? + +```js + +``` +```js +Because 4294967295 overflows the max number of elements that could be handled by Javascript in Arrays. +``` +```js +assert(true); +``` +--- + +## Snippet 3 + +``` +var arr = []; +arr[4294967295] = 'james'; +console.log(arr[4294967295]); +``` + +--- +What is the result of execute "Snippet 3" code? + +```js +var result = ; +``` +```js +var result = "james"; +``` +```js +assert(result === "james"); +``` +--- + +--- +Why? + +```js + +``` +```js +Javascript arrays can work as objects, dictionaries, when you are using as key any value that can not be handled by Array objects. +``` +```js +assert(true); +``` +--- + +## Snippet 4 + +``` +var arr = []; +arr[Number.MIN_VALUE] = 'mary'; +console.log(arr.length); +``` + +--- +What is the result of execute "Snippet 4" code? + +```js +var result = ; +``` +```js +var result = 0; +``` +```js +assert(result === 0); +``` +--- + +--- +Why? + +```js + +``` +```js +Javascript arrays can work as objects, dictionaries, when you are using as key any value that can not be handled by Array objects. +``` +```js +assert(true); +``` +--- + +## Snippet 5 + +``` +var arr = []; +arr[Number.MIN_VALUE] = 'mary'; +console.log(arr[Number.MIN_VALUE]); +``` + +--- +What is the result of execute "Snippet 5" code? + +```js +var result = ; +``` +```js +var result = "mary"; +``` +```js +assert(result === "mary"); +``` +--- + +--- +Why? + +```js + +``` +```js +Javascript arrays can work as objects, dictionaries, when you are using as key any value that can not be handled by Array objects. +``` +```js +assert(true); +``` +--- \ No newline at end of file diff --git a/hoisting1/README.md b/hoisting1/README.md index 7565574..5f40ad2 100644 --- a/hoisting1/README.md +++ b/hoisting1/README.md @@ -25,7 +25,7 @@ Why this is happening? ``` ```js -This is happening because the hoisting problem. Remember that in Javascript there are no block variables. +'This is happening because the hoisting problem. Remember that in Javascript there are no block variables.' ``` ```js diff --git a/input_search/README.md b/input_search/README.md new file mode 100644 index 0000000..6881825 --- /dev/null +++ b/input_search/README.md @@ -0,0 +1,102 @@ +# Input Search + +Reviewing the code of your colleague you have found this snipped of code: + +``` +$( document ).ready( function() { + $( '#inputSearch' ).keypress( function() { + $.ajax( { + url: 'http://www.domain.com/search', + data: this.value, + success: function ( data ) + { + var results = data.results; + $( '#list' ).empty(); + $.each( data, function ( item ) { + $( '#list' ).append( '