Mẹo vặt JavaScript
Chủ đề này tập hợp một số mẹo vặt đúc kết từ kinh nghiệm thực tế sử dụng
JavaScript (JS). Để hiểu và sử dụng được những mẹo này, người đọc cần có
kiến thức trung bình khá trở lên về JS, nghĩa là ít nhất cũng đã đọc qua Nhập
môn JS, JS nâng cao và Tài liệu hướng dẫn về prototype.js.
Để làm việc hiệu quả, các thành viên trong cùng project cần tuân theo qui ước chung. JS và Ruby
có rất nhiều điểm tương đồng. Qui ước sau lấy chút tinh thần của Ruby.
var CONST = 10; // hằng số
var $global; // biến toàn cục
var i; // biến cục bộ
var Klass; // class
Trong JS không có hằng số, nên viết hoa tên biến để tự nhắc nhở đừng thay đổi giá trị của chúng.
JS không bắt phải thêm var khi khai báo biến. Nhưng khi khai báo biến, nên thêm var để nhìn là
biết ngay (1) biến được khai báo ở chỗ nào và (2) giới hạn hoạt động của nó. Ví dụ:
function f() {
total = 0;
for (i = 1; i document.write("");
}
}
Khi chạy, f sẽ chạy vô hạn, vì biến i trong block thứ hai có tác dụng cả ở ngoài block, tác động
đến biến i trong block thứ nhất.
JS không cần dấu chấm phẩy (;) để ngăn cách. Nhưng nên dùng, chương trình sẽ dễ đọc hơn và
tương thích với các chương trình làm gọn/mã hóa JS (cruncher, obfuscator).
Hàm cũng chỉ là biến
Đoạn mã 1 Đoạn mã 2
// cách khai báo 1 // cách khai báo 2
function f() { var f = function() {
alert('f'); alert('f');
} }
f(); f();
alert(f); alert(f);
f = 5; f = 5;
alert(f); alert(f);
Hai đoạn mã trên cho thấy 2 điều:
• Hàm cũng chỉ là biến, giá trị có thể thay đổi.
• Có thề khai báo hàm theo kiểu của khai báo biến. Kiểu khai báo này hay hơn, vì nó cho
thấy bản chất của hàm trong JS.
Tóm lại, trong JS mọi thứ đều là biến, đều có thể thay đổi.
onload của window và onready của DOM
window.onload được gọi sau khi trang web được load xong. Do đó, nên dùng window.onload
làm điểm bắt đầu của chương trình, tương tự như dùng hàm main trong ngôn ngữ C hoặc Java.
Như khái niệm resource của chương trình desktop, trang HTML có thể coi là resource của
chương trình web. Trình duyệt nạp trang web theo từng dòng từ trên xuống dưới, mà đoạn JS
thường được đặt trước đoạn HTML, nên lỗi lập trình viên hay gặp phải là khởi tạo biến phụ
thuộc đoạn HTML trong khi đoạn HTML chưa được nạp.
Nếu dùng prototype.js, thì nên dùng Event.observe, nó cho phép nhiều hàm cùng bắt
window.onload.
Ví dụ:
Event.observe(window, 'load', f1, false);
Event.observe(window, 'load', f2, false);
var f1 = function() {
alert('f1');
}
var f2 = function() {
alert('f2');
}
Cập nhật: nên dùng onready của DOM thay cho onload của window
Tham khảo:
• http://www.geekdaily.net/2007/07/27/javascript-windowonload-is-bad-mkay/
• http://clientside.cnet.com/code-snippets/event-scripting/a-dom-ready-extension-for-
prototype/
Dùng class
JS hỗ trợ lập trình hướng đối tượng khá tốt. Không dùng tính năng này mà để biến và hàm tóe
loe, thì lúc chương trình phức tạp sẽ rất khó kiểm soát. Để hiểu rõ lập trình hướng đối tượng
trong JS, nên đọc quyển Professional JavaScript for Web Developers
Việc khai báo và sử dụng class rất đơn giản nếu dùng prototype.js, xin xem thêm hướng dẫn của
bạn lebinh.
Tách HTML và JS
Nên viết (1) các đoạn và (2) xử lí sự kiện (như onclick, onchange, ...) thành tập tin
riêng, tách khỏi tập tin HTML, sao cho trong tập tin HTML, không còn bất kì đoạn mã JS nào.
Việc tách này mang lại một số lợi điểm:
• Tập tin HTML không còn vướng đống spaghetti JS, nên dễ thiết kế và chỉnh sửa giao
diện.
• Các đoạn JS liên quan đến nhau được tập hợp lại thành một hoặc nhiều tập tin, nên dễ
viết và sửa lỗi.
Ví dụ:
• choices.html
• choices.js
Submit
Khi dùng JavaScript để submit form thông qua iframe (ví dụ khi muốn upload file), chú ý là
form và các thành phần cần submit nằm trong form không được đặt là disabled.
Cross-domain Ajax
Cross-domain Ajax không phải là một vấn đề mới. Ngay khi có Ajax người ta đã muốn giải
quyết vấn đề này vì cả Firefox và IE đều không cho phép bạn gửi 1 request đến một domain khác
với domain hiện hành.
Sẽ rất tuyệt với nếu có thể lấy dữ liệu từ trang từ điển Fast Dictionary để dùng ở mọi trang web
khác.
Có 4 giải pháp:
• Dùng 1 proxy. Gửi request tới một trang trên máy chủ của mình và trang này forward tới
trang ở domain khác, nhận dữ liệu trả lời và chuyển lại cho trang ban đầu. Nhược điểm
của phương pháp này là phải thực hiện từ phía server-side và do đó tốn tài nguyên/băng
thông của server.
• Dùng JS. Tương tự như cách Google Analytics dùng khi nhúng một đoạn Javascript để
theo dõi những ai truy cập vào trang web. Nhược điểm là dữ liệu chuyển qua lại phải là
dạng JSON.
• Dùng Flash. Đây là một kỹ thuật tấn công DOS phổ biến bằng cách cài flash vào trang
web và request sang trang khác. Nhược điểm là phụ thuộc vào flash và bị một số nguy cơ
bảo mật khác
• Dùng IFrame. Đây là một kỹ thuật khá phức tạp. Tuy nhiên, Dojo đã cho phép bạn thực
hiện điều này bằng cách khá đơn giản. Đây là giải pháp tương đối toàn vẹn. Nhược điểm
chính là IFrame sẽ tiêu tốn bộ nhớ của browser nhưng có lẽ không đáng kể.
Frame busting
Để tránh trang của mình chạy trong frame của người khác, có thể dùng:
if (top != self) {
top.location.href = location.href;
}
Thu nhỏ ảnh
Thỉnh thoảng ảnh nhúng vào diễn đàn, blog... to quá khổ, cần thu nhỏ cho vừa khít thành phần
HTML bao quanh ảnh. Nếu dùng prototype.js thì chỉ đoạn mã ngắn sau, nhìn mã chắc các bạn
đoán được thuật toán.
function resizeBigImages() {
var images = $$('img');
for (var i = 0; i < images.length; i++) {
var p = $(images[i].parentNode);
if (p != null) {
var w = p.getWidth();
if (images[i].width > w) {
images[i].width = w;
}
}
}
}
new PeriodicalExecuter(resizeBigImages, 3);
Nén
Đối với file JS to, nhất là khi dùng các thư viện như Dojo hay “YUI”:
http://developer.yahoo.com/yui/, có thể dùng JavaScript Compressor để nén lại. Tỉ lệ nén thường
đạt trở lên 50%.
Nguyên tắc nén là loại bỏ khoảng trắng và các dấu xuống dòng. Do đó khi viết chương trình, nên
cẩn thận các dấu ; { }. Có thể dùng chương trình JSLint để kiểm tra xem source code không
“chuẩn” chỗ nào, sau đó sửa lại cho tương thích với chương trình nén.