So you think you know JavaScript
Upcoming SlideShare
Loading in...5
×
 

So you think you know JavaScript

on

  • 2,166 views

 

Statistics

Views

Total Views
2,166
Views on SlideShare
1,741
Embed Views
425

Actions

Likes
2
Downloads
21
Comments
0

4 Embeds 425

http://eventifier.co 269
https://twitter.com 147
http://eventifier.com 8
http://getpocket.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • JS is the source of many Ti app issues
  • Hi, my name is Matt Apperson, some of you might know me from my time as an Engineer with Appcelerator. Back then I used to be the point of contact for the titans program and created or helped create many of the example apps still in use today, including one of the first physics based games using Titanium called TiBall on iOS. I have sense moved on, and now own a development and consulting company specializing in Javascript based tech like Titanium Mobile and NodeJS. So lets dive in!
  • First off I will just come out and say... I LOVE javascript! I have used it increasingly throughout my career, and come to love it more and more every day. The flexibility of the language is such that you can do almost anything with it. The result is that it lets you build mobile apps like with Titanium, add usability and design to web pages, power back end servers using nodejs, even fly robot helicopters and... the list of what JS can do seems to just never stop growing!... in fact, in the iobridge talk later today that list will grow a little more. :)
  • But regardless of the power and flexibility of the language, more often then not what we see online is crap code, outdated code, and people trying to shoehorn JS to look and act like other languages, or even entirely new languages. Why is this?
  • Almost every developer, in some phase of her professional life, was required to use JavaScript . Due to lack of time, or lack of interest, our beloved developer finds out that it is super easy to do something with JavaScript by searching for code snippets as there are so many, what few seem to realize though is that most of these examples and snippets are outdated and junk that use really bad JavaScript code. Thus, most devs never seem to really truly learn true modern JS
  • A lot of times as part of a search for a how-to of Javascript, people go to this site.... don’t. I’m not saying that w3school does not have some good info, but it is not a reliable place to find information.
  • Go here instead (talk about it)
  • Now as the owner of a development shop I constantly talk with clients, and devs who are looking for a job, and again, most think they know JavaScript... what most really know 90% of the time is a framework... now for web developers that framework is jQuery, on mobile and in node that is often coffeescript. Now I don’t truly hate frameworks, but the popularity and ease of use of them cause developer laziness, and they have really no clue how the language itself works. It gets so bad that often, developers get confused and think jQuery and Javascript are interchangeable terms. The result is, most JS code ends up looking like this...
  • WHY?
  • For years, JS was ignored because developers did things like animated fireworks and well... need I say more than geo-cities?
  • Because of it’s legacy, and age, a lot of “example” code exists on the web, and most of it is garbage, or just not useful in the application layer on servers or in mobile apps.
  • Due to the flexibility of the language, it’s easy to pickup and use, but hard to master. So, if you walk into developing using JS and dont have a good understanding of the language, your application will quickly turn into a pile of unmaintainable… spaghetti code So we are going to try and go over, not tools, tricks and tips for rapid development. Rather we are going to try and learn the core language better to help us write better quality apps.
  • For the sake of time, we wont be able to cover everything you will need to know to write good javascript. My goal today is to set you on the correct path to learn and use JS and Titanium yourself.
  • Everything in JavaScript acts like an object, with the only two exceptions being null and unde fined .
  • A common misconception however is that numbers cannot be used as objects. That is because a flaw in JavaScript's parser tries to parse the dot notation on a number as a floating point literal. But there are a couple of workarounds that can be used to make number literals act as objects too.
  • So now you have objects and properties... how do you delete them? Well setting the property to undefined or null is a common way to do this, however this only removes the value associated with the property, but not the key . The only way to remove a property from an object is to use the delete operator; This code outputs both bar as undefined and foo as null - only baz was removed and is therefore missing from the output.
  • JavaScript does not feature a classical inheritance model; instead, it uses a prototypal one. While this is often considered to be one of JavaScript's weaknesses, the prototypal inheritance model is in fact more powerful than the classic model. It is, for example, fairly trivial to build a classic model on top of a prototypal model, while the other way around is a far more difficult task. JavaScript is the only widely used language that features prototypal inheritance, so it can take time to adjust to the differences between the two models. The first major difference is that inheritance in JavaScript uses prototype chains. In this code, the object test will inherit from both Bar.prototype and Foo.prototype; hence, it will have access to the function method that was defined on Foo. It will also have access to the property value of the one Foo instance that is its prototype. It is important to note that new Bar() does not create a new Foo instance, but reuses the one assigned to its prototype; thus, all Bar instances will share the same value property. Als o, Do not use Bar.prototype = Foo , since it will not point to the prototype of Foo, but rather to the function object Foo . So the prototype chain will go over Function.prototype and not Foo.prototype ; therefore, the method `fun` will not be on the prototype chain, thus not accessible from the Bar method.
  • Now simply using Bar.prototype = Foo.prototype might seem to be the correct way to inherit from another prototype, but will result in both objects sharing the same prototype. Therefore, changes to either object's prototype will affect the prototype of the other as well, which in most cases is not the desired effect. One mis-feature that is often used is to extend Object.prototype or one of the other built in prototypes. This technique is called monkey patching and breaks encapsulation . While used by popular frameworks such as Prototype , ther e is stil l no good reason for cluttering built-in types with additional non-standard functionality. This also makes it much harder to on-board new developers to the project. The only constantly good reason for extending a built-in proto type in my opinion is to back-port the features of newer JavaScript engines; for example, Array.forEach . (talk abo ut why)
  • Now because in Javascript, everything is an object, lets break out to functions as they are the most glaring place (in my opinion at least) that things are not what you first expect.
  • Now in JavaScript, there are 2 ways to declare a method or function, that are both displayed here. and both are correct... but what many don’t know is that although they are both correct, they are not the same...
  • You see, this first example assigns the unnamed and anonymous function to the variable foo . The second example function gets hoisted before the execution of the program starts; thus, it is available everywhere in the scope it was defined in, even if called before the actual definition in the source.
  • One of JavaScript's most powerful features is the availability of closures . With closures, scopes always keep access to the outer scope, in which they were defined. Since the only scoping that JavaScript has is function scope , all functions, by default, act as closures. Here, Counter returns two closures: the function increment as well as the function get. Both of these functions keep a reference to the scope of Counter and, therefore, always keep access to the count variable that was defined in that scope. Since it is not possible to reference or assign scopes in JavaScript, there is no way of accessing the variable count from the outside. The only way to interact with it is via the two closures.
  • One often made mistake is to use closures inside of loops, as if they were copying the value of the loop's index variable. This code will not output the numbers 0 through 9 , but will simply print the number 10 ten times. The anonymous function keeps a reference to i . At the time console.log gets called, the for loop has already finished, and the value of i as been set to 10 . In order to get the desired behavior, it is necessary to create a copy of the value of i .
  • In order to copy the value of the loop's index variable, it is best to use an anonymous wrapper . The anonymous outer function gets called immediately with i as its first argument and will receive a copy of the value of i as its parameter e . The anonymous function that gets passed to setTimeout now has a reference to e , whose value does not get changed by the loop.
  • Constructors in JavaScript are yet again different from many other languages. Any function call that is preceded by the new keyword acts as a constructor. Inside the constructor - the called function - the value of this refers to a newly created object. The prototype of this new object is set to the prototype of the function object that was invoked as the constructor. If the function that was called has no explicit return statement, then it implicitly returns the value of this - the new object. For example, in the first code sample Foo is called as constructor and sets the prototype of the newly created object to Foo.prototype . In case of an explicit return statement like in our second snippit, the function returns the value specified by that statement, but only if the return value is an Object .
  • In order to be able to omit the new keyword, the constructor function has to explicitly return a value. Both calls to Bar return the same thing, a newly create object that has a property called method , which is a Closure . It should also be noted that the call new Bar() does not affect the prototype of the returned object. While the prototype will be set on the newly created object, Bar never returns that new object. In this example, there is no functional difference between using and not using the new keyword.
  • It is often recommended to not use new because forgetting its use may lead to bugs. In order to create a new object, one should rather use a factory and construct a new object inside of that factory. While this code is robust against a missing new keyword and certainly makes the use of private variables easier, it comes with some downsides.
  • It is often recommended to not use new because forgetting its use may lead to bugs. In order to create a new object, one should rather use a factory and construct a new object inside of that factory. While this code is robust against a missing new keyword and certainly makes the use of private variables easier, it comes with some downsides.
  • My first gotcha I will point out is setTimeout, the reason being that this is probably one of the most abused JS APIs by titanium developers. I one time worked on an app that had over 600 timeouts, this resulted in a really slow app due to how many contexts were being created. A really common thing I see is people using setTimeout in Titanium apps to align animations and things... this is a bad idea. If a timer is blocked from immediately executing it will be delayed (which will be longer than the desired delay) This means that you might waist a lot of time trying to get an animation to line up, and might get it to work on your device, but your users will most likely not see the correct result.
  • Now this is not so much a bug as a pet-pieve I have. So many times we see examples like the first code snippet here. ECMA 6 has introduced a new const statement. It lets your variable be read only. No more accidentally overwriting an important.variable. If you have more then one dev working on your app, you don't just WANT to know about this, you NEED to know about it. It will save more debugging time then you know.
  • OK now this is a fun one... So JavaScript has given us this fantastic little method that can turn a string into a number. Handy!
  • But until very recently on android, and still today on iOS you get this... and this one might have you stumped for a while. So what causes this?
  • You see, until the most recent version of the v8, and JScore JS engines, parseInt’s second parameter for radix was dynamic based on the users input. If the string begins with "0x", the radix is 16 (hexadecimal) If the string begins with "0", the radix is 8 (octal). This feature is deprecated If the string begins with any other value, the radix is 10 (decimal) setting this to 10 is the default in newer engines, and most likely what you will need. Again though, iOS and until the most recent builds on android, do not have these newer engines and thus you must set the default value
  • With CommonJS being used in Titanium now, this is less of an issue then in times past. But still it is a big one. Forgetting to use var can lead to access of the global variable as we can see in the example above. At times this can be useful, but it is also messy and should thus be used sparingly
  • This would be a much safer way to do this, now if you needed to, you could pass in bar as an argument as well so as to manipulate the global variable without changing it.
  • You could also do something like this...
  • Now as we get more advanced with javascript we start doing things with prototypes, but that can cause issues if our app is not designed to work with them... Note in this example we are looping through the food argument and adding each element to an array... the issue here is if food is a prototyped array, then it’s prototyped properties and methods will ALSO be added to the stomach array in this example.
  • To check whether an object has a property defined on itself and not somewhere on its prototype chain , it is necessary to use the hasOwnProperty method which all objects inherit from Object.prototype. Note: It is not enough to check whether a property is undefined. The property might very well exist, but its value just happens to be set to undefined. hasOwnProperty is the only thing in JavaScript which deals with properties and does not traverse the prototype chain. Only hasOwnProperty will give the correct and expected result; this is essential when iterating over the properties of any object. There is no other way to exclude properties that are not defined on the object itself, but somewhere on its prototype chain. It is recommended that hasOwnProperty is used in every for in loop to avoid error s from extended native prototypes .

So you think you know JavaScript So you think you know JavaScript Presentation Transcript

  • So you think you know JavaScript? 1 Matt Apperson Founder / Owner
  • © 2013 Apperson Labs Matt Apperson matt@appersonlabs.com http://appersonlabs.com twitter: @appersonlabs
  • 3 © 2013 Apperson Labs JavaScript is a great language!
  • © 2013 Apperson Labs But do a quick Google search and you see that many have no clue how to use it correctly to build apps WHY?
  • © 2013 Apperson Labs Ask any developer who has ever touched a website, and he will say he knows JavaScript... WRONG?
  • © 2013 Apperson Labs Seen this page much?
  • © 2013 Apperson Labs Go here! http://goo.gl/cQgzw
  • © 2013 Apperson Labs DEATH TO CoffeeScript!! And all frameworks...
  • 9 © 2013 Apperson Labs
  • 10 © 2013 Apperson Labs • JS has been around for a while, but it has been the red headed step child
  • 11 © 2013 Apperson Labs • JS has been around for a while, but it has been the red headed step child • Most JS examples and tutorials are legacy, hacks, and based on use in web pages
  • 12 © 2013 Apperson Labs • JS has been around for a while, but it has been the red headed step child • Most JS examples and tutorials are legacy, hacks, and based on use in web pages • JS is NOT strongly typed, so it’s easy to turn it into spaghetti code
  • © 2013 Apperson Labs “Where are we going thunder?” - Brian Regan •How JavaScript works (from 10,000 feet) •Common mistakes •Titanium gotchas (aka “the dark corners”)
  • © 2013 Apperson Labs Objects
  • © 2013 Apperson Labs Object usage and properties false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' function Foo(){} Foo.bar = 1; Foo.bar; // 1
  • © 2013 Apperson Labs Object usage and properties 2.toString(); // raises SyntaxError 2..toString(); // the second point is correctly recognized 2 .toString(); // note the space left to the dot (2).toString(); // 2 is evaluated first
  • © 2013 Apperson Labs Object usage and properties var obj = {     bar: 1,     foo: 2,     baz: 3 }; obj.bar = undefined; obj.foo = null; delete obj.baz; for(var i in obj) {     if (obj.hasOwnProperty(i)) {         console.log(i, '' + obj[i]);     } }
  • © 2013 Apperson Labs function Foo() {     this.value = 42; } Foo.prototype = {     fun: function() {} }; function Bar() {} // Set Bar's prototype to a new instance of Foo Bar.prototype = new Foo(); Bar.prototype.foo = 'Hello World'; // Make sure to list Bar as the actual constructor Bar.prototype.constructor = Bar; var test = new Bar(); // create a new bar instance JS Prototype (correct):
  • © 2013 Apperson Labs Bar.prototype = Foo.prototype; JS Prototype (incorrect): String.prototype.yell() = function() { return this + 'yay!!!!'; } Not inheriting correctly... Prototyping native objects...
  • © 2013 Apperson Labs Functions
  • © 2013 Apperson Labs Function declaration: // Example 1 var test = function() { return "yay!"; } // Example 2 function TestTwo() { return "yay also!"; } console.log(test); // "yay" console.log(TestTwo); // "yay also!""
  • © 2013 Apperson Labs Function declaration: // Example 1 console.log(test); // Error var test = function() { return "yay!"; }; // Example 2 console.log(TestTwo); // “yay also!” function TestTwo() { return "yay also!"; }
  • © 2013 Apperson Labs Closures function Counter(start) {     var count = start;     return {         increment: function() {             count++;         },         get: function() {             return count;         }     } } var foo = Counter(4); foo.increment(); foo.get(); // 5
  • © 2013 Apperson Labs Closures (the reference issue) for(var i = 0; i < 10; i++) {     setTimeout(function() {         console.log(i);       }, 1000); }
  • © 2013 Apperson Labs Closures (the reference issue) for(var i = 0; i < 10; i++) {     (function(e) {         setTimeout(function() {             console.log(e);           }, 1000);     })(i); }
  • © 2013 Apperson Labs Constructors function Foo() {     this.bla = 1; } Foo.prototype.test = function() {     console.log(this.bla); }; var test = new Foo(); function Blob() {     return false; } new Blob(); // an empty object, not what’s expected function Test() {     this.value = 2;     return {         fun: 1     }; } new Test(); // the returned object
  • © 2013 Apperson Labs Constructors (factories) function Bar() {     var value = 1;     return {         method: function() {             return value;         }     } } Bar.prototype = {     foo: function() {} }; new Bar(); Bar();
  • © 2013 Apperson Labs Constructors (dropping “new”) function Foo() {     var obj = {};     obj.value = 'blub';     var private = 2;     obj.someMethod = function(value) {         this.value = value;     }     obj.getPrivate = function() {         return private;     }     return obj; }
  • © 2013 Apperson Labs Constructors (dropping “new”) •It uses more memory since the created objects do not share the methods on a prototype. •In order to inherit, the factory needs to copy all the methods from another object or put that object on the prototype of the new object. •Dropping the prototype chain just because of a left out `new` keyword is contrary to the spirit of the language.
  • © 2013 Apperson Labs Common Mistakes
  • © 2013 Apperson Labs setTimeout(); var timer = setTimeout(function() { // more code here }, 100); This might not do what you think... •It is expensive as it creates a new context •The timer is not accurate as JS engines only have a single thread, forcing asynchronous events to queue waiting for execution.
  • © 2013 Apperson Labs USING_CAPS_FOR_CONSTANTS var DELAY = 20; // This is a constant, don’€šÃ„ôt change For a long time we had to do this... That is messy and dangerous... we have better options now! const DELAY = 20; // This is a real constant
  • © 2013 Apperson Labs parseInt(); var testONE = parseInt('20'); // This returns 20
  • © 2013 Apperson Labs parseInt(); var testONE = parseInt('20'); // This returns 20 var testTWO = parseInt('08'); // This returns 0
  • © 2013 Apperson Labs parseInt(); var testONE = parseInt('20'); // This returns 20 var testTWO = parseInt('08'); // This returns 0 var testTHREE = parseInt('08', 10); // This returns 08
  • © 2013 Apperson Labs Global Variables var bar = 'JavaScript can be fun!'; function foo() { bar = 'with a few exceptions'; return bar; } console.log(foo()); // 'with a few exceptions' console.log(bar); // 'with a few exceptions'
  • © 2013 Apperson Labs Global Variables var bar = 'JavaScript can be fun!'; function foo() { var bar = 'with a few exceptions'; return bar; } console.log(foo()); // 'with a few exceptions' console.log(bar); // 'JavaScript can be fun!'
  • © 2013 Apperson Labs Global Variables var bar = 'JavaScript can be fun!'; function foo() { var cat = bar cat = cat + ' yay!'; return bar; } console.log(foo()); // 'Javascript can be fun! yay!' console.log(bar); // 'Javascript can be fun!'
  • © 2013 Apperson Labs Not using hasOwnProperty(); function Cat() { // some code } Cat.prototype.stomach = [ ]; Cat.prototype.eat = function(food) { for( var i in food ) { this.stomach.push(food[i]); } };
  • © 2013 Apperson Labs Not using hasOwnProperty(); function Cat() { // some code } Cat.prototype.stomach = [ ]; Cat.prototype.eat = function(food) { for( var i in food ) { if(food.hasOwnProperty(i)) { this.stomach.push(food[i]); } } };
  • © 2013 Apperson Labs Using fake getters and setters... function Foo(){ var _value; this.getValue = function(){ return _value; }; this.setValue = function(val){ _value = val; }; } Foo.prototype.test = function() { console.log('The value is:' + this.value); // nope console.log('The value is:' + this.getValue()); // OK... }
  • © 2013 Apperson Labs True getter and setters! function Foo(){ var _value; Object.defineProperty(this, "value", { get : function(){ return _value; }, set : function(newValue){ _value = newValue; }, enumerable : true }); } Foo.prototype.test = function() { console.log('The value is:' + this.value); // Yep! } Reference - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
  • © 2013 Apperson Labs Not returning `this` on non-getters function test() { } test.prototype.run = function() { console.log('Doing something...'); }; test.prototype.sayHi = function() { console.log('Doing something else...'); }; var bar = new test(); bar.run(); bar.sayHi();
  • © 2013 Apperson Labs Not returning `this` on non-getters function test() { } test.prototype.run = function() { console.log('Doing something...'); return this; }; test.prototype.sayHi = function() { console.log('Doing something else...'); return this; }; var bar = new test().run().sayHi();
  • © 2013 Apperson Labs Try / Catch - A good idea? function test() { try { // do stuff here } catch(e) { //this will blow up sometimes and I don’t know why... } }
  • © 2013 Apperson Labs Try / Catch... function test() { try { // do stuff here } catch() { // this might work, and it might blow up. // I have no idea why it blows up sometimes } }
  • © 2013 Apperson Labs Try / Catch... function test() { try { // do stuff here } catch(e) { // this works console.log(e); } } // There is a performance hit, yet it is responsible. So weigh the choice to use it carefully
  • © 2013 Apperson Labs Titanium gotchas... Reference - http://developer.appcelerator.com/blog/2012/02/what-is-a-titanium-proxy-object.html •Objects returned by the Titanium API are not true JS objects [TIMOB-5818] •Common JS does not work the same on both platforms [TIMOB-8082] •Multiple JS engines to consider
  • © 2013 Apperson Labs BETA
  • © 2013 Apperson Labs Q & A
  • © 2013 Apperson Labs Matt Apperson matt@appersonlabs.com http://appersonlabs.com twitter: @appersonlabs