High Performance Web Sites [javaScript]
http://stevesouders.com/examples/rules.php
Edward. K
메멘토적 기억능력을 소유한 개발자 노트.
Authors: Gregory Baker, Software Engineer on GMail & Erik Arvidsson, Software Engineer on Google Chrome
Recommended experience: Working knowledge of JavaScript
Client-side scripting can make your application dynamic and active, but the browser's interpretation of this code can itself introduce inefficiencies, and the performance of different constructs varies from client to client. Here we discuss a few tips and best practices to optimize your JavaScript code.
String concatenation causes major problems with Internet Explorer 6 and 7 garbage collection performance. Although these issues have been addressed in Internet Explorer 8 -- concatenating is actually slightly more efficient on IE8 and other non-IE browsers such as Chrome -- if a significant portion of your user population uses Internet Explorer 6 or 7, you should pay serious attention to the way you build your strings.
Consider this example:
var veryLongMessage =
'This is a long string that due to our strict line length limit of' +
maxCharsPerLine +
' characters per line must be wrapped. ' +
percentWhoDislike +
'% of engineers dislike this rule. The line length limit is for ' +
' style purposes, but we don't want it to have a performance impact.' +
' So the question is how should we do the wrapping?';
Instead of concatenation, try using a join:
var veryLongMessage =
['This is a long string that due to our strict line length limit of',
maxCharsPerLine,
' characters per line must be wrapped. ',
percentWhoDislike,
'% of engineers dislike this rule. The line length limit is for ',
' style purposes, but we don't want it to have a performance impact.',
' So the question is how should we do the wrapping?'
].join();
Similarly, building up a string across conditional statements and/or loops by using concatenation can be very inefficient.
The wrong way:
var fibonacciStr = 'First 20 Fibonacci Numbers
';
for (var i = 0; i < 20; i++) {
fibonacciStr += i + ' = ' + fibonacci(i) + '
';
}
The right way:
var strBuilder = ['First 20 fibonacci numbers:'];
for (var i = 0; i < 20; i++) {
strBuilder.push(i, ' = ', fibonacci(i));
}
var fibonacciStr = strBuilder.join('');
Build up long strings by passing string builders (either an array or a helper class) into functions, to avoid temporary result strings.
For example, assuming buildMenuItemHtml_
needs to build up a string from literals and variables and would use a string builder internally,
instead of using:
var strBuilder = [];
for (var i = 0; i < menuItems.length; i++) {
strBuilder.push(this.buildMenuItemHtml_(menuItems[i]));
}
var menuHtml = strBuilder.join();
Use:
var strBuilder = [];
for (var i = 0; i < menuItems.length; i++) {
this.buildMenuItem_(menuItems[i], strBuilder);
}
var menuHtml = strBuilder.join();
The following is inefficient, as each time a instance of baz.Bar
is constructed, a new function and closure is created for foo:
baz.Bar = function() {
// constructor body
this.foo = function() {
// method body
};
}
The preferred approach is:
baz.Bar = function() {
// constructor body
};
baz.Bar.prototype.foo = function() {
// method body
};
With this approach, no matter how many instances of baz.Bar
are constructed, only a single function is ever created for foo
, and no closures are created.
Place instance variable declaration/initialization on the prototype for instance variables with value type (rather than reference type) initialization values (i.e. values of type number, Boolean, null, undefined, or string). This avoids unnecessarily running the initialization code each time the constructor is called. (This can't be done for instance variables whose initial value is dependent on arguments to the constructor, or some other state at time of construction.)
For example, instead of:
foo.Bar = function() {
this.prop1_ = 4;
this.prop2_ = true;
this.prop3_ = [];
this.prop4_ = 'blah';
};
Use:
foo.Bar = function() {
this.prop3_ = [];
};
foo.Bar.prototype.prop1_ = 4;
foo.Bar.prototype.prop2_ = true;
foo.Bar.prototype.prop4_ = 'blah';
Closures are a powerful and useful feature of JavaScript; however, they have several drawbacks, including:
Creating a closure is significantly slower then creating an inner function without a closure, and much slower than reusing a static function. For example:
function setupAlertTimeout() {
var msg = 'Message to alert';
window.setTimeout(function() { alert(msg); }, 100);
}
is slower than:
function setupAlertTimeout() {
window.setTimeout(function() {
var msg = 'Message to alert';
alert(msg);
}, 100);
}
which is slower than:
function alertMsg() {
var msg = 'Message to alert';
alert(msg);
}
function setupAlertTimeout() {
window.setTimeout(alertMsg, 100);
}
They add a level to the scope chain. When the browser resolves properties, each level of the scope chain must be checked. In the following example:
var a = 'a';
function createFunctionWithClosure() {
var b = 'b';
return function () {
var c = 'c';
a;
b;
c;
};
}
var f = createFunctionWithClosure();
f();
when f
is invoked, referencing a
is slower than referencing b
, which is slower than referencing c
.
See IE+JScript Performance Recommendations Part 3: JavaScript Code inefficiencies for information on when to use closures with IE.
LightBox2로 만드는 이미지 게시판
- 원문 : http://www.ibm.com/developerworks/kr/library/wa-ltbox/
게시판을 만들때 유용하겠네요.( 현재 나와있는 이미지 갤러리도 많아용~)
JavaScript utilizes two different kinds of equality operators: === | !== and == | != It is considered best practice to always use the former set when comparing.
"If two operands are of the same type and value, then === produces true and !== produces false." - JavaScript: The Good Parts
However, when working with == and !=, you'll run into issues when working with different types. In these cases, they'll try to coerce the values, unsuccessfully.
For those unfamiliar, the "eval" function gives us access to JavaScript's compiler. Essentially, we can execute a string's result by passing it as a parameter of "eval".
Not only will this decrease your script's performance substantially, but it also poses a huge security risk because it grants far too much power to the passed in text. Avoid it!
Technically, you can get away with omitting most curly braces and semi-colons. Most browsers will correctly interpret the following:
if(someVariableExists) x = false
However, consider this:
if(someVariableExists) x = false anotherFunctionCall();
One might think that the code above would be equivalent to:
if(someVariableExists) { x = false; anotherFunctionCall(); }
Unfortunately, he'd be wrong. In reality, it means:
if(someVariableExists) { x = false; } anotherFunctionCall();
As you'll notice, the indentation mimics the functionality of the curly brace. Needless to say, this is a terrible practice that should be avoided at all costs. The only time that curly braces should be omitted is with one-liners, and even this is a highly debated topic.
if(2 + 2 === 4) return 'nicely done';
What if, at a later date, you need to add more commands to this if statement. In order to do so, you would need to rewrite this block of code. Bottom line - tread with caution when omitting.
JSLint is a debugger written by Douglas Crockford. Simply paste in your script, and it'll quickly scan for any noticeable issues and errors in your code.
"JSLint takes a JavaScript source and scans it. If it finds a problem, it returns a message describing the problem and an approximate location within the source. The problem is not necessarily a syntax error, although it often is. JSLint looks at some style conventions as well as structural problems. It does not prove that your program is correct. It just provides another set of eyes to help spot problems."
- JSLint Documentation
Before signing off on a script, run it through JSLint just to be sure that you haven't made any mindless mistakes.
This tip has already been recommended in the previous article in this series. As it's highly appropriate though, I'll paste in the information.
Remember -- the primary goal is to make the page load as quickly as possible for the user. When loading a script, the browser can't continue on until the entire file has been loaded. Thus, the user will have to wait longer before noticing any progress.
If you have JS files whose only purpose is to add functionality -- for example, after a button is clicked -- go ahead and place those files at the bottom, just before the closing body tag. This is absolutely a best practice.
<p>And now you know my favorite kinds of corn. </p> <script type="text/javascript" src="path/to/file.js"></script> <script type="text/javascript" src="path/to/anotherFile.js"></script> </body> </html>
When executing lengthy "for" statements, don't make the engine work any harder than it must. For example:
for(var i = 0; i < someArray.length; i++) { var container = document.getElementById('container'); container.innerHtml += 'my number: ' + i; console.log(i); }
Notice how we must determine the length of the array for each iteration, and how we traverse the dom to find the "container" element each time -- highly inefficient!
var container = document.getElementById('container'); for(var i = 0, len = someArray.length; i < len; i++) { container.innerHtml += 'my number: ' + i; console.log(i); }
Bonus points to the person who leaves a comment showing us how we can further improve the code block above.
Don't always reach for your handy-dandy "for" statement when you need to loop through an array or object. Be creative and find the quickest solution for the job at hand.
var arr = ['item 1', 'item 2', 'item 3', ...]; var list = '<ul><li>' + arr.join('</li><li>') + '</li></ul>';
I won’t bore you with benchmarks; you’ll just have to believe me (or test for yourself) - this is by far the fastest method!
Using native methods (like join()), regardless of what’s going on behind the abstraction layer, is usually much faster than any non-native alternative.
- James Padolsey, james.padolsey.com
"By reducing your global footprint to a single name, you significantly reduce the chance of bad interactions with other applications, widgets, or libraries."
- Douglas Crockford
var name = 'Jeffrey'; var lastName = 'Way'; function doSomething() {...} console.log(name); // Jeffrey -- or window.name
var DudeNameSpace = { name : 'Jeffrey', lastName : 'Way', doSomething : function() {...} } console.log(DudeNameSpace.name); // Jeffrey
Notice how we've "reduced our footprint" to just the ridiculously named "DudeNameSpace" object.
It might seem unnecessary at first, but trust me, you WANT to comment your code as best as possible. What happens when you return to the project months later, only to find that you can't easily remember what your line of thinking was. Or, what if one of your colleagues needs to revise your code? Always, always comment important sections of your code.
// Cycle through array and echo out each name. for(var i = 0, len = array.length; i < len; i++) { console.log(array[i]); }
Always compensate for when JavaScript is disabled. It might be tempting to think, "The majority of my viewers have JavaScript enabled, so I won't worry about it." However, this would be a huge mistake.
Have you taken a moment to view your beautiful slider with JavaScript turned off? (Download the Web Developer Toolbar for an easy way to do so.) It might break your site completely. As a rule of thumb, design your site assuming that JavaScript will be disabled. Then, once you've done so, begin to progressively enhance your layout!
Consider the following code:
setInterval( "document.getElementById('container').innerHTML += 'My new number: ' + i", 3000 );
Not only is this code inefficient, but it also functions in the same way as the "eval" function would. Never pass a string to SetInterval and SetTimeOut. Instead, pass a function name.
setInterval(someFunction, 3000);
At first glance, "With" statements seem like a smart idea. The basic concept is that they can be used to provide a shorthand for accessing deeply nested objects. For example...
with (being.person.man.bodyparts) { arms = true; legs = true; }
-- instead of --
being.person.man.bodyparts.arms = true; being.person.man.bodyparts.legs= true;
Unfortunately, after some testing, it was found that they "behave very badly when setting new members." Instead, you should use var.
var o = being.person.man.bodyparts; o.arms = true; o.legs = true;
There are multiple ways to create objects in JavaScript. Perhaps the more traditional method is to use the "new" constructor, like so:
var o = new Object(); o.name = 'Jeffrey'; o.lastName = 'Way'; o.someFunction = function() { console.log(this.name); }
However, this method receives the "bad practice" stamp without actually being so. Instead, I recommend that you use the much more robust object literal method.
var o = { name: 'Jeffrey', lastName = 'Way', someFunction : function() { console.log(this.name); } };
Note that if you simply want to create an empty object, {} will do the trick.
var o = {};
"Objects literals enable us to write code that supports lots of features yet still make it a relatively straightforward for the implementers of our code. No need to invoke constructors directly or maintain the correct order of arguments passed to functions, etc." - dyn-web.com
The same applies for creating a new array.
var a = new Array(); a[0] = "Joe"; a[1] = 'Plumber';
var a = ['Joe','Plumber'];
"A common error in JavaScript programs is to use an object when an array is required or an array when an object is required. The rule is simple: when the property names are small sequential integers, you should use an array. Otherwise, use an object." - Douglas Crockford
var someItem = 'some string'; var anotherItem = 'another string'; var oneMoreItem = 'one more string';
var someItem = 'some string', anotherItem = 'another string', oneMoreItem = 'one more string';
...Should be rather self-explanatory. I doubt there's any real speed improvements here, but it cleans up your code a bit.
Technically, most browsers will allow you to get away with omitting semi-colons.
var someItem = 'some string' function doSomething() { return 'something' }
Having said that, this is a very bad practice that can potentially lead to much bigger, and harder to find, issues.
var someItem = 'some string'; function doSomething() { return 'something'; }
When looping through items in an object, you might find that you'll also retrieve method functions as well. In order to work around this, always wrap your code in an if statement which filters the information
for(key in object) { if(object.hasOwnProperty(key) { ...then do something... } }
As referenced from JavaScript: The Good Parts, by Douglas Crockford.
Need a quick and easy way to determine how long an operation takes? Use Firebug's "timer" feature to log the results.
function TimeTracker(){ console.time("MyTimer"); for(x=5000; x > 0; x--){} console.timeEnd("MyTimer"); }
While I'm a huge fan of web development blogs (like this one!), there really isn't a substitute for a book when grabbing some lunch, or just before you go to bed. Always keep a web development book on your bedside table. Here are some of my JavaScript favorites.
Read them...multiple times. I still do!
Rather than calling a function, it's quite simple to make a function run automatically when a page loads, or a parent function is called. Simply wrap your function in parenthesis, and then append an additional set, which essentially calls the function.
(function doSomething() { return { name: 'jeff', lastName: 'way' }; })();
JavaScript libraries, such as jQuery and Mootools, can save you an enormous amount of time when coding -- especially with AJAX operations. Having said that, always keep in mind that a library can never be as fast as raw JavaScript (assuming you code correctly).
jQuery's "each" method is great for looping, but using a native "for" statement will always be an ounce quicker.
Although JavaScript 2 should have a built-in JSON parser, as of this writing, we still need to implement our own. Douglas Crockford, the creator of JSON, has already created a parser that you can use. It can be downloaded HERE.
Simply by importing the script, you'll gain access to a new JSON global object, which can then be used to parse your .json file.
var response = JSON.parse(xhr.responseText); var container = document.getElementById('container'); for(var i = 0, len = response.length; i < len; i++) { container.innerHTML += '
Years ago, it wasn't uncommon to find the "language" attribute within script tags.
<script type="text/javascript" language="javascript"> ... </script>
However, this attribute has long since been deprecated; so leave it out.
[JS] 자바스크립트 암호화 및 복호화 [2004년 작성된 문서..]
http://blog.naver.com/devstory/120008203476
* 암호화, 복호화 ( encode, decode ) 파일 첨부
- 암호화 방법( Microsoft script Encoder 도움말 ) script Encoder는 스크립팅 코드만 인코딩합니다. 이때 파일에서 변경하지 않은 다른 내용들은 일반 텍스트로 Jscript®를 사용할 때 인코딩 표식은 다음과 같습니다. script Encoder를 실행하면 스크립트 블록 내의 시작 표식 앞에 있는 부분은 인코딩되지 않고 스크립트 볼록의 인코딩한 뒤에 <scRIPT> 태그에 들어 있는 언어 지시자가 변경되는 것에 유의하십시오. VBscript를 사용할 때 새 지시자는 다음과 같습니다. <scRIPT LANGUAGE="VBscript.Encode"> Jscript(또는 Javascript)를 사용할 때 새 지시자는 다음과 같습니다. script Encoder는 MS-DOS 명령줄이나 다음과 같이 실행 대화 상자에서 실행합니다. 이 유틸리티의 구문은 script Encoder 구문에 설명되어 있습니다.
나타납니다. script Encoder를 사용하려면 일반적인 방법으로 스크립트를 개발하고 디버그한 다음,
최종 스크립트를 인코딩하십시오. script Encoder는 원본 코드에 들어 있는 표식을 사용하여 인코딩 시작점을
식별합니다.
Visual Basic® scripting Edition(VBscript)을 사용할 때 다음 예제와 같이 인코딩 표식을 사용하여
일반 텍스트 저작권 정보를 표시할 수 있습니다.
<scRIPT LANGUAGE="VBscript">
'Copyrightⓒ 1998. XYZ Productions. All rights reserved.
'**Start Encode**
' 여기에 사용자 코드를 작성합니다.
</scRIPT>
<scRIPT LANGUAGE="Jscript">
//Copyrightⓒ 1998. ZYX Productions. All rights reserved.
//**Start Encode**
// 여기에 사용자 코드를 작성합니다.
</scRIPT>
나머지 부분은 모두 인코딩됩니다. 그러므로 시작 표식을 생략하면 전체 스크립트 블록이 인코딩되고,
스크립트 블록 끝에 시작 표식이 있으면 전혀 인코딩되지 않습니다.
<scRIPT LANGUAGE="Jscript.Encode">
SRCENC [switches] inputfile outputfile
쉽게 수정하거나 볼 수 없도록 스크립트 원본 코드를 인코딩합니다.
SCRENC [/s] [/f] [/xl] [/l defLanguage ] [/e defExtension] inputfile outputfile
요소
설명
/s
선택적인 요소. 이 스위치를 사용하면 script Encoder를 실행할 때 화면에 출력 메시지가 표시되지 않습니다. 생략하면 기본적으로 상세한 출력 메시지가 표시됩니다.
/f
선택적인 요소. 출력 파일이 입력 파일을 덮어씁니다. 이 요소를 사용하면 입력 원본 파일을 더 이상 사용할 수 없습니다. 생략하면 입력 원본 파일이 보존됩니다.
/xl
선택적인 요소. @language 지시어가 .ASP 파일의 맨 앞부분에 추가되지 않습니다. 생략하면 모든 .ASP 파일에 @language 지시어가 추가됩니다.
선택적인 요소. 인코딩할 때 사용할 기본 스크립트 언어(Jscript® 또는 VBscript)를 지정합니다. 인코딩하는 파일의 스크립트 블록(언어 특성이 없음)은 지정된 이 언어로 인코딩됩니다. 생략하면 HTML 페이지와 스크립트릿에서는 Jscript가 기본 스크립트 언어가 되고 .ASP 파일에서는 VBscript가 기본 스크립트 언어가 됩니다. 일반 텍스트 파일에서는 파일 확장명(.js 또는 .vbs)에 따라 기본 스크립트 언어가 정해집니다.
선택적인 요소. 입력 파일의 파일 형식을 지정합니다. 입력 파일의 확장명으로 파일 형식을 결정할 수 없을 때 즉, 입력 파일의 확장명이 인식 가능한 확장명은 아니지만 파일의 내용이 인식 가능한 형식일 때, 이 스위치를 사용하여 파일 형식을 지정합니다. 이 요소의 기본값은 없습니다. 파일 확장명으로 파일 형식을 알 수 없을 때 이 요소를 지정하지 않으면 script Encoder에서 해당 파일이 인코딩되지 않습니다. 인식 가능한 파일 확장명은 asa, asp, cdx, htm, html, js, sct, vbs 등입니다.
inputfile
필수적인 요소. 인코딩할 입력 파일의 이름입니다. 현재 디렉터리에 대한 상대 경로가 포함되어야 합니다.
outputfile
필수적인 요소. 출력 파일의 이름입니다. 현재 디렉터리에 대한 상대 경로가 포함되어야 합니다.
- 복호화 방법
Usage: scrdec14 <infile> <outfile> [-cp codepage] [-urldec]
Code pages can be 932 - Japanese
936 - Chinese (Simplified)
950 - Chinese (Traditional)
949 - Korean (Wansung)
1361 - Korean (Johab)
Any other code pages don't need to be specified.
Use -urldec to unescape %xx style encoding on the fly.
infile 은 암호화 되어 있는 파일 outfile 은 복호화 되어서 나오는 파일
예제>D:\GUNHO\JS\ENDEC>scrdec14 test.html result.html
위와 같이 실행한 후 나온 결과 파일의 자바 스크립트 내용은 16진수로 되어있으므로
unescape 로 다시 변경한 다음 alert 나 innerText 를 이용하여 소스를 확인하시면 됩니다.
스크립트(Script) 코드를 암호화 시켜보자(Encode/Decode) : 윗글과 동일하나..최근 작성된 문서
http://www.mungchung.com/xe/lecture/4137
스크립트 코드를 보안상 이유로 인코드를 하는 경우 있는데 아시는 분들은 다 아시겠지요 -_- 도움말 보면 왜 사용해야하는지 사용상 주의 사항들 그런것 잘 나와 있습니다. 그러니 자세한 내용은 도움말 참조하세요.
*) 스크립트 Encode
일단 encode 하는 프로그램 다운 받아야 합니다. http://www.microsoft.com/downloads/details.aspx?displaylang=ko&FamilyID=e7877f67-c447-4873-b1b0-21f0626a6329 여기 가서 받으면 됩니다. 다운 받아서 설치합니다. 그런후 아래 코드를 복사해서 test.html 파일로 만듭니다.
이 test.html 파일의 스크립트 부분을 encode 하면 도스창에서 아래와 같은 명령을 내리면 됩니다. (혹 SRCENC.exe를 못찾는 경우 Script Encoder가 설치된 디렉토리로 가서 실행시키면 됩니다.)
SRCENC "원본파일" "내보낼파일"
이렇게 해서 내보낸 파일의 소스를 보면 아래와 같습니다.
인코딩한 파일을 test1.html 이라했을때 이 파일을 다시 decode 하는 방법은 아래 유틸을 다운받아야 합니다. http://www.virtualconspiracy.com/index.php?page=scrdec/download 이 프로그램 다운 받은 후에 도스창에서 다음과같은 명령 실행하면 인코딩된 스크립트를 디코딩 해줍니다.
scrdec18.exe "인코딩된파일" "내보낼파일"