diff --git a/coffeescript/README b/coffeescript/README index 6a2b345..9ffea2b 100644 --- a/coffeescript/README +++ b/coffeescript/README @@ -12,3 +12,23 @@ TODO: * The Max/Min trick is great, but will fail for really large arrays, which is worth mentioning. (Functions can only take so many arguments in certain browsers). + +Extras: + +JavaScript to CoffeeScript convertor +Cakefiles +Shims +Embedding Raw JavaScript +Everything is an expression in CoffeeScript - look at 'returns' and chaining? +Hacking on the compiler. https://github.com/jashkenas/coffee-script/wiki/%5BHowto%5D-Hacking-on-the-CoffeeScript-Compiler +Type checking: http://coffeescriptcookbook.com/chapters/classes_and_objects/type-function +Semicolons discussion +Reserved words discussion +How browsers are updating to support CS debugging +parseInt radix +Advanced inheritance +hasOwnProperty +getters/setters +The function Statement Versus the function Expression +Strict checking +Spine? \ No newline at end of file diff --git a/coffeescript/chapters/01_introduction.md b/coffeescript/chapters/01_introduction.md index a4d7357..edfb8ab 100644 --- a/coffeescript/chapters/01_introduction.md +++ b/coffeescript/chapters/01_introduction.md @@ -10,7 +10,7 @@ If you have any errata or suggestions, please don't hesitate to open a ticket on So let's dive right into it; why is CoffeeScript better than writing pure JavaScript? Well for a start, there's less code to write - CoffeeScript is very succinct, and takes white-space into account. In my experience this reduces code by a third to a half of the original pure JavaScript. In addition, CoffeeScript has some neat features, such as array comprehensions, prototype aliases and classes that further reduce the amount of typing you need to do. -More importantly though, JavaScript has a lot of [skeletons in its closet](http://bonsaiden.github.com/JavaScript-Garden/) which can often trip up inexperienced developers. CoffeeScript neatly sidesteps these, by only exposing a curated selection of JavaScript features, fixing many of the language's oddities. +More importantly though, JavaScript has a lot of [skeletons in its closet](http://bonsaiden.github.com/JavaScript-Garden/) which can often trip up inexperienced developers. CoffeeScript neatly sidesteps these by only exposing a curated selection of JavaScript features, fixing many of the language's oddities. CoffeeScript is *not* a superset of JavaScript, so although you can use external JavaScript libraries from inside CoffeeScript, you'll get syntax errors if you compile JavaScript as-is, without converting it. The compiler converts CoffeeScript code into its counterpart JavaScript, there's no interpretation at runtime. diff --git a/coffeescript/chapters/03_classes.md b/coffeescript/chapters/03_classes.md index e33dc5b..acc2dbe 100644 --- a/coffeescript/chapters/03_classes.md +++ b/coffeescript/chapters/03_classes.md @@ -195,6 +195,8 @@ The little dance around the `moduleKeywords` variable is to ensure we have callb As you can see, we've added some static properties, `find()` and `create()` to the `User` class, as well as some instance properties, `save()`. Since we've got callbacks whenever modules are extended, we can shortcut the process of applying both static and instance properties: + + ORM = find: (id) -> create: (attrs) -> diff --git a/coffeescript/chapters/04_idioms.md b/coffeescript/chapters/04_idioms.md index c26e403..d641f34 100644 --- a/coffeescript/chapters/04_idioms.md +++ b/coffeescript/chapters/04_idioms.md @@ -130,8 +130,7 @@ In the `Math.max` example above, we're using `...` to de-structure the array an Log = log: -> - return if typeof console is "undefined" - console.log(arguments...) + console?.log(arguments...) Or you can alter the arguments before they're passed onwards: @@ -141,9 +140,8 @@ Or you can alter the arguments before they're passed onwards: logPrefix: "(App)" log: (args...) -> - return if typeof console is "undefined" - if @logPrefix then args.unshift(@logPrefix) - console.log(args...) + args.unshift(@logPrefix) if @logPrefix + console?.log(args...) Bear in mind though, that CoffeeScript will automatically set the function invocation context to the object the function is being invoked on. In the example above, that would be `console`. If you want to set the context specifically, then you'll need to call `apply()` manually. diff --git a/coffeescript/chapters/06_the_bad_parts.md b/coffeescript/chapters/06_the_bad_parts.md new file mode 100644 index 0000000..1c35379 --- /dev/null +++ b/coffeescript/chapters/06_the_bad_parts.md @@ -0,0 +1,71 @@ +
« Back to all chapters
+ +#The Bad Parts + +JavaScript is a tricky beast, and knowing the parts that you should avoid is just as important as known about the good parts. As Sun Tzu says, know your enemy, and that's exactly what we're going to do in the chapter, exploring the dark side of JavaScript and revealing all the ugly monsters lurking ready to pounce on the unsuspecting developer. + +As I touched on in the introduction, CoffeeScript's awesomeness lies not only in it's syntax, but in it's ability to fix some of JavaScript's warts. However, due to the fact CoffeeScript uses static analysis and has no runtime type checking, it's not a silver bullet to all of JavaScript's bugbears and there's still some issues you need to be aware about. + +Let's first talk about what things the language does solve. + +##Subset + +CoffeeScript's syntax is already a subset of JavaScript's, so already there's less to fix. Let's take the `with` statement for example. This statement has for a long time been "considered harmful", and should be avoided. `with` was intended to provide a shorthand for writing recurring property lookups on objects. For example, instead of writing: + + dataObj.users.alex.email = "info@eribium.org"; + +You could write: + + with(dataObj.users.alex) { + email = "info@eribium.org" + } + +Setting aside the fact that we shouldn't have such a deep object in the first place, the syntax is quite cleaner. Except for one thing. It's damn confusing to the JavaScript interpreter - it doesn't know exactly what you're going to do in the `with` context, and forces the specified object to be searched first for all name lookups. + +This really hurts performance and means the interpreter has to turn off all sorts of JIT optimizations. Additionally `with` statements can't be minified using tools like [uglify-js](https://github.com/mishoo/UglifyJS). All things considered, it's much better just to avoid using them, and CoffeeScript takes this a step further by eliminating them from it's syntax. In other words, using `with` in CoffeeScript will throw a syntax error. + +##Global variables + + + +##Semicolons + +JavaScript does not enforce the use of semicolons in source code, so it's possible to omit them. However, behind the scenes the JavaScript compiler still needs them, so the parser automatically inserts them whenever it encounters a parse error due to a missing semicolon. In other words, it'll try to evaluate a statement without semicolons and, if that fails, try again using semicolons. + +Unfortunately this is a tremendously bad idea, and can actually change the behavior of your code. + + +## eval + +Whilst CoffeeScript removes some of JavaScript's foibles, other features are a necessary evil, you just need to be aware of their shortcomings. A case in point, is the `eval()` function. Whilst undoubtedly it has its uses, you should know about its drawbacks, and avoid it if possible. The `eval()` function will execute a string of JavaScript code in the local scope, and functions like `setTimeout()` and `setInterval()` can also both take a string as their first argument to be evaluated. + +However, like `with`, `eval()` throws the compiler off track, and is a major performance hog. As the compiler has no idea what's inside until runtime, it can't perform any optimizations. Any concern is with security. If you give it dirty input, `eval` can easily open up your code for injection attacks. 99% of the time when you're using `eval`, there are better & safer alternatives (such as square brackets). + +## delete + + +## parseInt + + + 2.toString() + +##Strict checking + + "use strict" + + + +== +global variables (and overwriting issue) +parseInt +typeof +instanceof +hasOwnProperty +The function Statement Versus the function Expression +shimming +Strict checking +Semicolons +reserved words +jslint + +"use strict" \ No newline at end of file