AirJD 焦点
AirJD

没有录音文件
00:00/00:00
加收藏

JavaScript Best Practices(JS最佳实践) by Christian Heilmann@Yahoo(2009)

发布者 jser
发布于 1442538242822  浏览 5980 关键词 JavaScript, English 
分享到

第1页

JavaScript “Best Practices”

Christian Heilmann | http://wait-till-i.com | http://scriptingenabled.org Bangalore, India, Yahoo internal training, February 2009



第2页

“Best Practice” presentations are hard to do.



第3页

Trying to tell developers to change their ways and follow your example is a tough call.



第4页

I also consider it a flawed process.



第5页

I am bored of discussions of syntax details.



第6页

This is not about forcing you to believe what I believe.



第7页

This is about telling you what worked for me and might as

well work for you.



第8页

I’ve collected a lot of ideas and tips over time how to be

more effective.



第9页

Make it understandable

Avoid globals

Stick to a strict coding style

Comment as much as needed but not more

Avoid mixing with other technologies

Use shortcut notations

Modularize

Enhance progressively

Allow for configuration and translation



Avoid heavy nesting

Optimize loops

Keep DOM access to a minimum

Don't yield to browser whims

Don't trust any data

Add functionality with JavaScript, not content

Build on the shoulders of giants

Development code is not live code



第10页

Make it understandable!



第11页

Choose easy to understand and short names for variables

and functions.



第12页

Bad variable names:

x1 fe2 xbqne



第13页

Also bad variable names:

incrementorForMainLoopWhichSpansFromTenToTwenty createNewMemberIfAgeOverTwentyOneAndMoonIsFull



第14页

Avoid describing a value with your variable or function name.



第15页

For example isOverEighteen()

might not make sense in some countries,

isLegalAge() however works everywhere.



第16页

Think of your code as a story – if readers get stuck because of an unpronounceable character in your story that isn’t part of the main story line, give it another, easier name.



第17页

Avoid globals



第18页

Global variables are a terribly bad idea.



第19页

You run the danger of your code being overwritten by any other JavaScript added to

the page after yours.



第20页

The workaround is to use closures and the module

pattern.



第21页

var current = null; var labels = [

‘home’:’home’, ‘articles’:’articles’, ‘contact’:’contact’ ]; function init(){ }; function show(){ }; function hide(){ };



第22页

var current = null; var labels = [

‘home’:’home’, ‘articles’:’articles’, ‘contact’:’contact’ ]; function init(){ }; function show(){ current = 1; }; function hide(){ show(); };



Everything is global and can be accessed



第23页

Problem: access is not contained, anything in the page can overwrite what you

do.



第24页

demo = { current:null, labels:[



Object Literal: Everything is



‘home’:’home’,



contained but can be



‘articles’:’articles’, ‘contact’:’contact’ ],



accessed via the object name.



init:function(){



},



show:function(){



demo.current = 1;



},



hide:function(){



demo.show();



}



}



第25页

Problem: Repetition of module name leads to huge

code and is annoying.



第26页

(function(){ var current = null; var labels = [



Anonymous Module: Nothing is global.



‘home’:’home’,



‘articles’:’articles’,



‘contact’:’contact’



];



function init(){



};



function show(){



current = 1;



};



function hide(){



show();



};



})();



第27页

Problem: No access from the outside at all (callbacks, event handlers)



第28页

module = function(){ var labels = [ ‘home’:’home’,



Module Pattern: You need to specify



‘articles’:’articles’, ‘contact’:’contact’ ];



what is global and what isn’t – switching



return {



syntax in between.



current:null,



init:function(){



},



show:function(){



module.current = 1;



},



hide:function(){



module.show();



}



}



}();



第29页

Problem: Repetition of module name, different syntax for inner functions.



第30页

module = function(){



var current = null;



Revealing Module



var labels = [ ‘home’:’home’, ‘articles’:’articles’,



Pattern: Keep consistent



‘contact’:’contact’



syntax and mix and



]; function init(){ };



match what to make global.



function show(){



current = 1;



};



function hide(){



show();



};



return{init:init,show:show,current:current}



}();



第31页

module = function(){



var current = null;



Revealing Module



var labels = [ ‘home’:’home’, ‘articles’:’articles’,



Pattern: Keep consistent



‘contact’:’contact’



syntax and mix and



]; function init(){ };



match what to make global.



function show(){



current = 1;



};



function hide(){



show();



};



return{init:init,show:show,current:current}



}();



module.init();



第32页

Stick to a strict coding style



第33页

Browsers are very forgiving JavaScript parsers.



第34页

However, lax coding style will hurt you when you shift to

another environment or hand over to another developer.



第35页

Valid code is good code.



第36页

Valid code is secure code.



第37页

Validate your code: http://www.jslint.com/



第38页

TextMate users: get Andrew’s JavaScript Bundle:

http://andrewdupont.net/ 2006/10/01/javascript-tools-

textmate-bundle/



第39页

Comment as much as needed but no more



第40页

Comments are messages from developer to developer.



第41页

“Good code explains itself” is an arrogant myth.



第42页

Comment what you consider needed – but don’t tell others

your life story.



第43页

Avoid using the line comment though. It is much safer to use /* */ as that doesn’t cause errors when the line break is removed.



第44页

If you debug using comments, there is a nice

little trick:



第45页

module = function(){ var current = null; function init(){ };

/* function show(){ current = 1; }; function hide(){ show(); };

*/ return{init:init,show:show,current:current}

}();



第46页

module = function(){ var current = null; function init(){ };

/* function show(){ current = 1; }; function hide(){ show(); };

// */ return{init:init,show:show,current:current}

}();



第47页

module = function(){ var current = null; function init(){ };

//* function show(){ current = 1; }; function hide(){ show(); };

// */ return{init:init,show:show,current:current}

}();



第48页

Comments can be used to write documentation – just

check the YUI doc:

http://yuiblog.com/blog/ 2008/12/08/yuidoc/



第49页

However, comments should never go out to the end user in plain HTML or JavaScript.



第50页

Back to that later :)



第51页

Avoid mixing with other technologies



第52页

JavaScript is good for calculation, conversion, access to outside sources (Ajax) and to define the behaviour of an interface

(event handling).



第53页

Anything else should be kept to the technology we have to

do that job.



第54页

For example:

Putaredborderaroundallfields withaclassof“mandatory”when theyareempty.



第55页

var f = document.getElementById('mainform'); var inputs = f.getElementsByTagName('input'); for(var i=0,j=inputs.length;i<j;i++){

if(inputs[i].className === 'mandatory' && inputs[i].value === ''){

inputs[i].style.borderColor = '#f00'; inputs[i].style.borderStyle = 'solid'; inputs[i].style.borderWidth = '1px'; } }



第56页

Two month down the line:

Allstyleshavetocomplywiththe newcompanystyleguide,no bordersareallowedanderrors shouldbeshownbyanalerticon nexttotheelement.



第57页

People shouldn’t have to change your JavaScript code to change the look and feel.



第58页

var f = document.getElementById('mainform'); var inputs = f.getElementsByTagName('input'); for(var i=0,j=inputs.length;i<j;i++){

if(inputs[i].className === 'mandatory' && inputs[i].value === ''){

inputs[i].className+=’ error’; } }



第59页

Using classes you keep the look and feel to the CSS designer.



第60页

Using CSS inheritance you can also avoid having to loop over a lot of elements.



第61页

Use shortcut notations



第62页

Shortcut notations keep your code snappy and easier to

read once you got used to it.



第63页

var cow = new Object(); cow.colour = ‘white and black’; cow.breed = ‘Holstein’; cow.legs = 4; cow.front = ‘moo’; cow.bottom = ‘milk’;

is the same as

var cow = { colour:‘white and black’, breed:‘Holstein’, legs:4, front:‘moo’, bottom = ‘milk’

};



第64页

var lunch = new Array(); lunch[0]=’Dosa’; lunch[1]=’Roti’; lunch[2]=’Rice’; lunch[3]=’what the heck is this?’;

is the same as

var lunch = [ ‘Dosa’, ‘Roti’, ‘Rice’, ‘what the heck is this?’

];



第65页

if(v){ var x = v;

} else { var x = 10;

} is the same as

var x = v || 10;



第66页

var direction; if(x > 100){

direction = 1; } else {

direction = -1;

} is the same as

var direction = (x > 100) ? 1 : -1;

/* Avoid nesting these! */



第67页

Modularize



第68页

Keep your code modularized and specialized.



第69页

It is very tempting and easy to write one function that does everything.



第70页

As you extend the functionality you will however find that you do the same things in several

functions.



第71页

To prevent that, make sure to write smaller, generic helper

functions that fulfill one specific task rather than

catch-all methods.



第72页

At a later stage you can also expose these when using the revealing module pattern to create an API to extend the

main functionality.



第73页

Good code should be easy to build upon without re-writing

the core.



第74页

Enhance progressively



第75页

There are things that work on the web.



第76页

Use these rather than creating a lot of JavaScript

dependent code.



第77页

DOM generation is slow and expensive.



第78页

Elements that are dependent on JavaScript but are

available when JavaScript is turned off are a broken promise to our users.



第79页

Example: TV tabs.



第80页

Tab Interface



第81页

Tab Interface



第82页

Allow for configuration and translation.



第83页

Everything that is likely to change in your code should not be scattered throughout

the code.



第84页

This includes labels, CSS classes, IDs and presets.



第85页

By putting these into a configuration object and making this one public we make maintenance very easy and allow for customization.



第86页

carousel = function(){ var config = { CSS:{ classes:{ current:’current’, scrollContainer:’scroll’ }, IDs:{ maincontainer:’carousel’ } } labels:{ previous:’back’, next:’next’, auto:’play’ } settings:{ amount:5,



第87页

skin:’blue’, autoplay:false } }; function init(){ }; function scroll(){ }; function highlight(){ }; return {config:config,init:init} }();



第88页

Avoid heavy nesting



第89页

Code gets unreadable after a certain level of nesting –

when is up to your personal preference and pain threshold.



第90页

A really bad idea is to nest loops inside loops as that also means taking care of several iterator variables (i,j,k,l,m...).



第91页

You can avoid heavy nesting and loops inside loops with specialized tool methods.



第92页

function renderProfiles(o){ var out = document.getElementById(‘profiles’);

for(var i=0;i<o.members.length;i++){ var ul = document.createElement(‘ul’);

var li = document.createElement(‘li’); li.appendChild(document.createTextNode(o.members[i].name));

var nestedul = document.createElement(‘ul’); for(var j=0;j<o.members[i].data.length;j++){

var datali = document.createElement(‘li’); datali.appendChild(

document.createTextNode( o.members[i].data[j].label + ‘ ‘ +

o.members[i].data[j].value )

); nestedul.appendChild(datali);

} li.appendChild(nestedul);

} out.appendChild(ul);

}



第93页

function renderProfiles(o){ var out = document.getElementById(‘profiles’);

for(var i=0;i<o.members.length;i++){ var ul = document.createElement(‘ul’);

var li = document.createElement(‘li’); li.appendChild(document.createTextNode(data.members[i].name));

li.appendChild(addMemberData(o.members[i])); }

out.appendChild(ul); }

function addMemberData(member){ var ul = document.createElement(‘ul’);

for(var i=0;i<member.data.length;i++){ var li = document.createElement(‘li’);

li.appendChild( document.createTextNode(

member.data[i].label + ‘ ‘ + member.data[i].value

) );

} ul.appendChild(li);

return ul; }



第94页

Think of bad editors and small screens.



第95页

Optimize loops



第96页

Loops can get terribly slow in JavaScript.



第97页

Most of the time it is because you’re doing things in them

that don’t make sense.



第98页

var names = ['George','Ringo','Paul','John']; for(var i=0;i<names.length;i++){

doSomeThingWith(names[i]); }



第99页

This means that every time the loop runs, JavaScript

needs to read the length of the array.



第100页

You can avoid that by storing the length value in a different

variable:



第101页

var names = ['George','Ringo','Paul','John']; var all = names.length; for(var i=0;i<all;i++){

doSomeThingWith(names[i]); }



第102页

An even shorter way of achieving this is to create a second variable in the pre-

loop condition.



第103页

var names = ['George','Ringo','Paul','John']; for(var i=0,j=names.length;i<j;i++){

doSomeThingWith(names[i]); }



第104页

Keep computation-heavy code outside of loops.



第105页

This includes regular expressions but first and foremost DOM manipulation.



第106页

You can create the DOM nodes in the loop but avoid

inserting them to the document.



第107页

Keep DOM access to a minimum



第108页

If you can avoid it, don’t access the DOM.



第109页

The reason is that it is slow and there are all kind of

browser issues with constant access to and changes in the

DOM.



第110页

Write or use a helper method that batch-converts a dataset

to HTML.



第111页

Seed the dataset with as much as you can and then call the method to render all

out in one go.



第112页

Don't yield to browser whims!



第113页

What works in browsers today might not tomorrow.



第114页

Instead of relying on flaky browser behaviour and

hoping it works across the board...



第115页

...avoid hacking around and analyze the problem in detail

instead.



第116页

Most of the time you’ll find the extra functionality you

need is because of bad planning of your interface.



第117页

Don't trust any data



第118页

The most important thing about good code is that you cannot trust any data that

comes in.



第119页

Don’t believe the HTML document – any user can meddle with it for example in

Firebug.



第120页

Don’t trust that data that gets into your function is the right format – test with typeof and

then do something with it.



第121页

Don’t expect elements in the DOM to be available – test for

them and that they indeed are what you expect them to

be before altering them.



第122页

And never ever use JavaScript to protect something – it is as easy to crack as it is to code :)



第123页

Add functionality with JavaScript, don't create

content.



第124页

If you find yourself creating lots and lots of HTML in JavaScript, you might be doing something wrong.



第125页

It is not convenient to create using the DOM...



第126页

...flaky to use innerHTML (IE’s Operation Aborted error)...



第127页

...and it is hard to keep track of the quality of the HTML you

produce.



第128页

If you really have a massive interface that only should be available when JavaScript is

turned on...



第129页

...load the interface as a static HTML document via Ajax.



第130页

That way you keep maintenance in HTML and allow for customization.



第131页

Build on the shoulders of giants



第132页

JavaScript is fun, but writing JavaScript for browsers is less

so.



第133页

JavaScript libraries are specifically built to make browsers behave and your code more predictable by plugging browser holes.



第134页

Therefore if you want to write code that works without keeping the maintenance overhead...



第135页

... of supporting current browsers and those to come

to yourself...



第136页

... start with a good library. (YUI)



第137页

Development code is not live code.



第138页

Last but not least I want you to remember that some things that work in other languages are good in JavaScript, too.



第139页

Live code is done for machines.



第140页

Development code is done for humans.



第141页

Collate, minify and optimize your code in a build process.



第142页

Don’t optimize prematurely and punish your developers and those who have to take

over from them.



第143页

If we cut down on the time spent coding we have more

time to perfect the conversion to machine code.



第145页

THANKS!

Keep in touch: Christian Heilmann http://wait-till-i.com http://scriptingenabled.org http://twitter.com/codepo8

http://delicious.com/codepo8/jscodetips



支持文件格式:*.pdf
上传最后阶段需要进行在线转换,可能需要1~2分钟,请耐心等待。