Tải bản đầy đủ (.pdf) (240 trang)

Lập trình hướng đối tượng trong javascript và các kiểu mẫu thiết kế

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (3.46 MB, 240 trang )

Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 1

MC LC
LI NÓI U 6
I.Hàm function 7
1.1.Kin thc nn v hàm function 7
1.1.1.Cách ti thiu hóa s bin toàn cc 8
1.2.nh ngha thut ng 13
1.3.So sánh gia vic khai báo vi biu thc : tên names và s leo thang hoisting 15
1.4.Thuc tính name ca hàm function 16
1.5.S leo thanh ca hàm function - Function Hoisting 17
1.6.Kiu mu callback 19
1.6.1.Mt ví d mu v callback 19
1.6.2.Hàm callback và phm vi tn ti ca bin trong hàm callback 22
1.6.3.Lng nghe s kin không đng b 24
1.6.4. tr Timeouts 25
1.6.5.Hàm callbacks trong các th vin 25
1.6.6.Cách tr v trong hàm functions 25
1.6.7.Các hàm functions t đnh ngha 27
1.6.8.Các hàm functions tc thi 29
1.6.8.1.Các tham s ca 1 hàm tc thi 30
1.6.8.2.Các giá tr đc tr v t các hàm tc thi 31
1.6.8.3.Cách s dng và u đim 33
1.6.9.Cách khi to các đi tng tc thi 34
1.6.10.Phân nhánh thi gian khi to - Init-Time Branching 35
1.6.11.Các thuc tính ca functions – kiu mu ti u hóa b nh Memoization Pattern 37
1.6.12.Các đi tng cu hình - Configuration Objects 39
1.6.13.Curry 41
1.6.14.Function Application 41
1.6.15.Partial Application 42


1.6.16.Currying 44
1.6.17.khi nào ta s dng Currying 47
II.T mng arrays cho ti các đi tng objects 48
2.1.Các phn t, các thuc tính, các phng thc 50
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 2

2.2.Các mng arrays kt hp 50
2.3.Các truy cp vào các thuc tính ca đi tng 51
2.4.Cách gi các phng thc ca 1 đi tng 53
2.5.Cách bin đi các thuc tính / phng thc 54
2.6.Các s dng t khóa this 55
2.7.Các hàm to constructor 55
2.8.i tng toàn cc Global Object 57
2.9.Thuc tính to 58
2.10.Toán t instanceof 59
2.11.Các hàm functions mà tr v các đi tng objects 59
2.12.Các chuyn tip các đi tng 61
2.13.Cách so sánh các đi tng objects 62
III.Các đi tng đc xây dng sn 63
3.1.i tng object 63
3.2.i tng Mng array 64
3.3.i tng Function 67
3.3.1.Các thuc tính ca đi tng function 68
3.3.2.Các phng thc trong các đi tng objects function 71
IV.Biu thc chính quy 74
4.1.Các thuc tính ca các đi tng Objects 74
4.2.Các phng thc ca các đi tng regexp 76
4.3.Các phng thc string mà nhn các biu thc chính quy nh các tham s 76
4.3.1.search() và match() 77

4.3.2.replace() 77
4.3.3.Các hàm Replace callbacks 78
4.3.4.split() 80
4.3.5.Cách chuyn tip 1 chui string khi 1 regexp đc nh kì vng 80
4.4.Quy tc mu trong biu thc quan h 81
V.Prototype 88
5.1.Thuc tính prototype 88
5.2.Cách thêm các phng thc và thuc tính bng cách s dng Prototype 88
5.3.Cách s dng các thuc tính và phng thc ca Prototype 90
5.4.Các thuc tính chính gc so vi các thuc tính đc thêm vào qua prototype 91
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 3

5.5.Ghi đè thuc tính ca prototype vi thuc tính chính gc 93
5.6.Các lit kê các thuc tính 94
5.7.isPrototypeOf() 97
5.8.Bí mt v __proto__ Link 98
5.9.Cách làm gia tng các đi tng đc xây dng sn 100
5.10.Mt vài ghi chú v Prototype 101
VI.S k tha 106
6.1.Các chui móc ni prototype 106
6.2.Ví d v chui móc ni prototype 107
6.3.Cách chuyn các thuc tính đc chia s vào bên trong prototype 111
6.4.Cách tha k ch t prototype 113
6.5.Hàm to Constructor tm thi - new F() 115
6.6.Uber – truy cp đi tng cha t đi tng con 117
6.7.Cách phân tách phn k tha vào trong 1 hàm function 119
VII.Các kiu mu to đi tng object 120
7.1.Các phng thc và thuc tính riêng t 120
7.1.2.Các thành viên riêng t 120

7.1.3.Các phng thc đc u tiên 121
7.1.4.Các thiu sót quyn riêng t 122
7.1.5.Object Literals và quyn riêng t 123
7.1.6.Các Prototypes v quyn riêng t 125
7.1.7.Cách phát hin các hàm riêng nh các phng thc public 126
7.2.Cách thành viên c đnh static 127
7.2.1.Các thanh viên Public Static 128
7.2.2.Các thành viên Private Static 130
7.3.Các hng s đi tng 133
7.4.Kiu mu chui hóa - Chaining Pattern 135
7.4.1.u đim và nhc đim ca kiu mu chui hóa - Chaining Pattern 136
7.5.Phng thc method() 137
VIII.Các kiu mu có kh nng tái s dng - Code Reuse Patterns 139
8.1.Kiu mu hng class so vi các kiu mu phân cp hin đi 139
8.2.Kt qu nh mong mun khi s dng s k tha theo hng classical 140
8.3.Vic k tip chui prototype 141
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 4

8.4.Nhc đim khi s dng kiu mu #1 144
8.5.Kiu mu Classical Pattern #2 - Rent-a-Constructor – kiu mu vay mn hàm to . 145
8.5.1.Chui prototype 147
8.5.2.S đa k tha bng các hàm to vay mn 148
8.5.3.u đim và nhc đim ca kiu mu hàm khi to vay mn 149
8.6.Kiu mu Classical Pattern #3 - Rent and Set Prototype – kiu mu vay mn và thit
lp prototype 149
8.7.Kiu mu Classical Pattern #4 – chia s prototype 151
8.8.Kiu mu Classical Pattern #5 – 1 hàm to tm thi 152
8.8.1.Cách lu tr Superclass 154
8.8.2.Cách cài đt li con tr hàm khi to 154

8.9.Klass 156
8.10.S k tha hng Prototypal 159
8.10.1.Tho lun 160
8.10.2.Vic b sung ECMAScript 5 162
8.10.3.S k tha bng cách sao chép các thuc tính 162
8.10.4.Mix-ins 165
8.10.5.Vay mn các phng thc Methods 166
8.10.6.Ví d : vay mn t 1 mng array 167
8.10.7.Vay mn và ràng buc 168
8.10.8.Function.prototype.bind() 170
IX.Kiu mu thit k 172
9.1.Singleton – kiu mu duy nht 172
9.1.1.Cách s dng new 173
9.1.2.Thc th trong 1 thuc tính static 174
9.1.3.Thc th trong 1 bao đóng 174
9.2.Factory – kiu mu sn xut đi tng 178
9.2.1.i tng Object Factory đc xây dng sn 181
9.3.Iterator – kiu mu bin lp 182
9.4.Façade 185
9.5.Proxy 188
9.5.1.Mt ví d mu 190
9.6.Composite 199
9.6.1.Vn đ đt ra 199
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 5

9.6.2.Cu trúc ca kiu mu composite pattern 202
9.6.3.Các mu ví d v kiu mu Composite Pattern 203
9.6.4.Mu ví d trong JS s dng kiu mu Composite Pattern 203
9.6.5.u đim và nhc đim ca kiu mu Composite Pattern 208

9.7.Observer – ngi quan sát 210
9.7.1.Mu ví d #1: vic đt mua tp chí 211
X.Asynchronous patterns - Kiu mu không đng b 216
10.1.Li ích và thách thc vi lp trình không đng b 216
10.2.Promises 218
10.3.Khám phá Promises trong b công c JQuery 222
XI.ASYNCH JS : sc mnh ca đi tng $.DEFERRED 225
11.1.Các hàm APIS không đng b ca trình duyt 225
11.2.Cách to các ng dng 1 cách không đng b 227
11.3.Cách hiu chnh s tht bi 228
11.4.$.DEFERRED 228
11.5.Các trng hp mu 232
11.6.JQuery.Deferred và Promise 233
11.6.1.$.Deferred 234
11.6.2.Phng thc deferred.resolve() 235
11.6.3.Phng thc deferred.reject() 235
11.6.4.Phng thc Promise() 236




Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 6

LI NÓI U
Tài liu đc vit ging nh 1 bn ghi chép, ghi li nhng th mà mình đư đc đc t các
ebook ting anh, do vy b cc sp xp ca nó có th cha chính xác, cách trình bày không
theo chun 1 ebook nào c và nhiu ch vit cha rõ ngha và không mch lc do hn ch v
ngoi ng ca bn thân mình. Tài liu mang đm tính cht cá nhân do vy bn s bt gp
trong tài liu này nhiu đon kí t in đm, in màu, c ch ln bt thng và đc tô màu

khác nhau - đó là các đon có liên quan đn nhau hay là nhng ghi chú quan trng mà bn
cn phi đc k.
Ni dung trong tài liu này đc da trên các cun ebook: “JavaScript Patterns - Stoyan
Stefanov”, “Object-Oriented JavaScript - Stoyan Stefanov”, “JavaScript: The Good Parts
- Douglas Crockford”, và 1 s bài vit ca các tác gi mà mình không còn nh rõ na.
Trc khi đc tài liu này, bn phi xác đnh mình nm rõ nhng gì thuc v c bn nht ca
Javascript nh các cách khai báo, các kiu d liu c bn, các phép toán s hc, các mnh đ
điu kin, ầ(nu bn có kin thc v 1 ngôn ng lp trình c bn nào đó, thì bn s làm quen
vi nhng gì tài liu này b qua trong Javascript 1 cách rt nhanh chóng). Tài liu này ch
tp trung vào nhng gì đc coi là đc bit nht ca Javascript so vi các ngôn ng lp trình
thông dng khác, không phi dành cho nhng ngi mi bt đu hc Javascript. 1 đim na
bn cn lu ý là trong tài liu này lc b phn tng tác gia Javascript vi DOM &
Browser bi vì bn thân mình dùng Jquery đ thay th.
Nu bn s dng Javascript kt hp vi Phonegap đ to ra các ng dng cho các nn tng
mobile, thì các tài liu sau có th bn s quan tâm ti :
 “Phonegap cho ngi mi hc”:

 “Cách ti u hóa môi trng lp trình ng dng cho Android”:
/>cho-android-tng-tc-my-o-android
 Hoc đn gin truy cp vào th mc chia s sau:


Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 7

I.Hàm function
1.1.Kin thc nn v hàm function
Có 2 tính nng chính ca hàm functions trong JS làm cho chúng tr nên đc bit.điu đu tiên
là hàm functions cng ging nh các đi tng class objects và điu th 2 là chúng cung cp
1 phm vi tn ti ca các bin

Các hàm functions là các đi tng objects mà :
 Có th to ra 1 cách linh hot trong thi gian chy trong xut quá trình thc thi ca
chng trình
 Có th gán vào các bin và có th tham chiu đ sao chép giá tr sang các bin khác,
có th tham s hóa và trong 1 s trng hp nó có th b xóa
 Có th chuyn tip nh các tham s vào trong hàm functions khác và cng có th
đc tr v bi hàm functions khác
 Có th có thuc tính và các phng thc  bên trong
Do vy có th xy ra trng hp 1 hàm function A – là 1 đi tng object, đi tng này
cha các thuc tính và phng thc – 1 hàm B khác, hàm B nhn 1 hàm C là tham s và khi
thc thi nó có th tr v hàm D.
Thông thng khi ta ngh v 1 hàm function trong JS thì ta ngha v 1 đi tng object vi
tính nng đc bit duy nht là đi tng object này có kh nng gi đc, điu này có ngha
là nó có th đc thc thi x lý
Thc t thì hàm function là đi tng object và hin nhiên ta s thy hàm to new Function()
nh sau :
// antipattern
// for demo purposes only
var add = new Function('a, b', 'return a + b');
add(1, 2); // returns 3

 đon code này thì không có s ng vc gì v vic add() là 1 đi tng object. cách s dng
hàm to Function() constructor không phi là cách s dng hay vì nó s gây ra 1 vài bt tin
cho vic vit và đc hiu
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 8

tính nng quan trng th 2 là các hàm function cung cp 1 phm vi tn ti.bt c bin nào
đc đnh ngha vi var bên trong 1 hàm function thì là 1 bin đa phng và nó không tn
ti đc bên ngoài hàm function này.vic nói rng du ngoc {} không cung cp phm vi đa

phng có ngha là nu ta đnh ngha 1 bin vi var bên trong 1 mnh đ if hay bên trong 1
mnh đ for hay mnh đ while thì điu này không có ngha là bin này là đa phng vi if
hay for.nó ch là đa phng đi vi hàm function bao quanh nó và nu không có hàm
function nào bao quanh nó thì nó là 1 bin toàn cc.nh đư nói đn  chng trc thì vic
ti thiu hóa s bin toàn cc là 1 s thích tt bi vì các hàm functions là bt buc đ gi
các bin tn ti trong 1 phm vi có kim soát
1.1.1.Cách ti thiu hóa s bin toàn cc
Js s dng các hàm functions đ kim soát phm vi tn ti ca bin.1 bin đc khai báo
trong 1 hàm function là bin đa phng và nó không tn ti ngoài hàm function này.theo
cách khác, các bin toàn cc là các bin đc khai báo không  trong bt c hàm functions
nào
Mi môi trng trong JS đu là 1 đi tng toàn cc global object có th đc truy cp khi ta
s dng this  bên ngoài bt c hàm functions nào.mi bin toàn cc mà ta to ra tr thành 1
thuc tính ca đi tng toàn cc.di đây là 1 đon mư code nh ch ra cách to và truy cp
1 bin toàn cc trong môi trng trình duyt :
myglobal = "hello"; // antipattern
console.log(myglobal); // "hello"
console.log(window.myglobal); // "hello"
console.log(window["myglobal"]); // "hello"
console.log(this.myglobal); // "hello"

1.1.1.2.Các vn đ ny sinh vi các bin toàn cc
các vn đ ny sinh vi bin toàn cc là vic chúng đc chia s trong phm vi toàn b mư
code trong ng dng JS.chúng sng trong cùng 1 namespace toàn cc và s luôn luôn có 1
tình hung xy ra va chm trong cách đt tên – khi 2 phn tách riêng ca 1 ng dng đnh
ngha các bin toàn cc vi cùng 1 tên nhng có mc đích s dng khác nhau
đây cng là vn đ thng xy ra cho các web pages nhúng mư code không đc vit bi nhà
lp trình ca trang page đó ví d :
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 9


 1 th vin JS ca bên th 3
 Các mư Scripts t 1 đi tác qung cáo
 Mư code t 1 mư phân tích và lu vt ca ngi s dng bên th 3
 Các loi widgets, badges, và buttons khác nhau
Chúng ta nói rng 1 trong các mư scripts ca bên th 3 đnh ngha 1 bin toàn cc đc gi ví
d nh result.sau đó bên trong 1 trong các hàm functions ca ta đnh ngha 1 bin toàn cc
khác đc gi là result.kt qu ca điu này là bin result khai báo cui cùng s ghi đè lên
bin result trc đó và mư script ca bên th 3 rt có th không hot đng
Do vy điu quan trng đ làm 1 ngi hàng xóm thân thin vi các mư scripts khác là các
chin thut ti thiu hóa s bin toàn cc
Khá là ngc nhiên là rt d dàng to ra bin toàn cc 1 cách rt vô tình trong JS bi vì 2 tính
nng ca JS.điu đu tiên là ta s dng các bin mà không khai báo chúng.và điu th 2 là JS
luôn có ng ý là toàn cc vi bt kì bin nào mà ta không khai báo thì nó s tr thành 1 thuc
tính ca đi tng toàn cc global object.xét ví d sau :
function sum(x, y) {
// antipattern: implied global
result = x + y;
return result;
}

Trong mư code trên thì result đc s dng mà không khai báo.đon code vn hot đng tt
nhng sau khi hàm function này ta kt thúc vi 1 bin toàn cc result thì đây có th là ngun
gc ca nhiu vn đ
Theo kinh nghim thì luôn luôn khai báo các bin vi var, và ta sa li ví d trc nh sau :
function sum(x, y) {
var result = x + y;
return result;
}


Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 10

1 trong nhng li d dàng to ra các bin theo hng toàn cc khác chính là chui gán liên
tip các bin var.xét đon ví d sau, thì bin a là đa phng nhng bin b là toàn cc :
// antipattern, do not use
function foo() {
var a = b = 0;
//
}

Nu ta ngn nhiên là ti sao li nh vy thì đó là bi vì s đánh giá đi t phi sang trái.đu
tiên biu thc b = 0 đc đánh giá trc và ti đây thì b không đc khai báo.giá tr tr v
ca biu thc này là 0 và nó đc gán vào 1 bin đa phng mi đc khai báo vi var
a.theo cách khác ta có th vit li nh sau :
var a = (b = 0);
nu ta đư khai báo tt c các bin và thc hin chui gán thì đây là cách tt và ta không to ra
các bin toàn cc 1 cách vô tình na :
function foo() {
var a, b;
//
a = b = 0; // both local
}

1.1.1.3.Các hiu ng ph khi ta quên var
ây là 1 đim hi khác bit gia các bin ng ý toàn cc và s đnh ngha hoàn toàn là 1 bin
toàn cc – s khác bit là kh nng không xác đnh đc các bin này bng cách s dng
toán t delete :
 Các bin toàn cc đc to ra vi var ( các bin đc to ra bên ngoài bt c hàm
functions nào ) có th không b xóa

 Các bin ng ý toàn cc không đc to ra vi var ( bt chp nu nó đc to ra bên
trong hàm function ) có th xóa
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 11

iu này ch ra rng các bin toàn cc nói theo cách k thut không phi là các bin tht s
nhng chúng là các thuc tính ca đi tng toàn cc global object.các thuc tính có th b
xóa bi toán t delete trái li cng có bin không th b xóa :
// define three globals
var global_var = 1;
global_novar = 2; // antipattern
(function () {
global_fromfunc = 3; // antipattern
}());
// attempt to delete
delete global_var; // false
delete global_novar; // true
delete global_fromfunc; // true
// test the deletion
typeof global_var; // "number"
typeof global_novar; // "undefined"
typeof global_fromfunc; // "undefined"

trong ch đ nghiêm ngt ca ES5 thì vic gán các bin cha đc khai báo ( ging nh 2
bin antipatterns  đon mư trên ) s vng ra 1 li
1.1.1.4.Cách truy cp đi tng toàn cc
trong các trình duyt, đi tng toàn cc có th truy cp t bt c phn nào ca đon code
thông qua thuc tính window.nu ta cn truy cp bin toàn cc mà không gõ mư cng xác
đnh vi window thì ta có th làm nh sau t bt c cp nào ca các phm vi function lng
nhau :

var global = (function () {
return this;
}());

Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 12

Cách này ta có th luôn luôn ly v đi tng toàn cc bi vì bên trong các hàm functions thì
this luôn luôn ch ti 1 đi tng toàn cc.điu này thc s không còn trong ch đ nghiêm
ngt ca ECMAScript 5, vì vy ta phi chp nhn 1 kiu mu khác khi mư code ca ta  trong
ch đ nghiêm ngt.ví d nu ta đang phát trin 1 th vin thì ta có th đóng gói mư th vin
vào ngay 1 hàm function ( nh s nói  chng 4 ) và sau đó t phm vi toàn cc, thì chuyn
tip vào 1 tham chiu ti this nh 1 tham s trong hàm function
1.1.1.5.Kiu mu s dng var
Bng cách s dng cu trúc var  đu các hàm functions là 1 kiu mu rt hu dng và đc
chp nhn.nó có nhng u đim sau :
 Cung cp 1 đa đim cho vic xem xét toàn b các bin đa phng cn có ca
function
 Ngn chn các li v logic khi 1 bin đc s dng trc khi nó đc đnh ngha
 Giúp ta nh đư khai báo các bin nào và do đó ti thiu hóa các bin toàn cc
 Phi gõ ít mư code hn
1 kiu mu vi var nhìn nh sau :
function func() {
var a = 1,
b = 2,
sum = a + b,
myobject = {},
i,
j;
// function body

}

Ta s dng 1 cu trúc var và khai báo nhiu bin đc phân tách bi du phy.nó là 1 cách
thc hành tt.điu này có th ngn chc các li v logic và cng khin đon mư code d đc
hn.ta cng có th làm điu tng t vi DOM :
function updateElement() {
var el = document.getElementById("result"),
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 13

style = el.style;
// do something with el and style
}

1.1.1.6.S leo thang : 1 vn đ vi các bin phân tán
JS cho phép ta có nhiu cu trúc var  bt c đâu trong hàm function và tt c chúng đu
ging vi các bin đc khai báo trên đu hàm function.trng thái x lý này đc gi là s
leo thang hoisting.điu này có th hng ti các li v logic khi ta s dng 1 bin và sau đó
gán nó ln na  trong hàm function.vi JS thì min là 1 bin nm trong cùng 1 phm vi (
cùng trong 1 hàm function ) thì nó đc coi là đư khai báo và ngay khi nó đc s dng trc
khi khai báo var, ví d nh sau :
// antipattern
myname = "global"; // global variable
function func() {
alert(myname); // "undefined"
var myname = "local";
alert(myname); // "local"
}
func();


1.2.nh ngha thut ng
ta xét đon mư code sau :
// named function expression
var add = function add(a, b) {
return a + b;
};

Don mư code này ch ra 1 hàm function bng cách s dng biu thc đt tên hàm named
function expression.
S khai báo này dù xy ra trc
hay sau thì nó cng xóa đi s khai
báo toàn cc trc đó – leo thang
cn tr li s khai báo toàn cc
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 14

Nu ta b qua tên ( tên hàm chính là add ) trong biu thc trên thì ta s có 1 biu thc
hàm vô danh unnamed function expression hay đn gin đc gi là function expression hay
thông dung nht là anonymous function.nh ví d sau :
// function expression, a.k.a. anonymous function
var add = function (a, b) {
return a + b;
};

Khi ta b qua tên ca hàm function là add thì chính là ta đang s dng biu thc unnamed
function expression, điu này không gây nh hng gi ti đnh ngha và s gi ra ca hàm
function.ch có 1 s khác bit là thuc tính name ca đi tng function object s là 1 chui
rng.thuc tính name này là 1 phn m rng ca ngôn ng ( nó không phi là 1 phn trong
chun ECMA ) nhng nó li sn sàng có trong nhiu môi trng.nu ta gi li tên hàm là add
thì thuc tính add.name s cha chui add.và thuc tính name rt hu dng khi s dng 1

công c debug ging nh Firebug hay khi ta gi cùng 1 hàm function 1 cách đ quy ngay
trong thân ca nó hay theo mt khác ta cng có th b qua nó
Cui cùng, ta có các khai báo hàm.nó cng ging nh cách khai báo hàm function trong
nhng ngôn ng khác :
function foo() {
// function body goes here
}

Trong các điu l v ng pháp thì biu thc named function expressions và function
declarations là tng t nhau.v bn cht nu ta không gán kt qu ca biu thc function
expression là 1 bin, thnh thong cng không tìm ra s khác nhau gia 1 khai báo hàm
function declaration và 1 biu thc function expression
Có s khác nhau gia 2 cái là du chm phy.du chm phy là không cn thit trong khai
báo hàm function declarations nhng nó li là bt buc trong biu thc function expressions
và ta nên luôn luôn s dng nó mc dù c ch t đin du chm phy có th t làm cho ta
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 15

1.3.So sánh gia vic khai báo vi biu thc : tên names và s leo thang
hoisting
Vy ta nên s dng khai báo hàm function declarations hay s dng biu thc hàm function
expressions?
Trong nhiu trng hp theo cú pháp thì ta không th s dng 1 khai báo.ví d nhúng
chuyn tip 1 đi tng function object ging nh 1 tham s hay đnh ngha các phng thc
trong chui miêu t đi tng :
// this is a function expression,
// pased as an argument to the function `callMe`
callMe(function () {
// I am an unnamed function expression
// also known as an anonymous function

});

// this is a named function expression
callMe(function me() {
// I am a named function expression
// and my name is "me"
});

// another function expression
var myobject = {
say: function () {
// I am a function expression
}
};

Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 16

S khai báo hàm Function declarations ch có th xut hin trong các mư hng th tc, điu
này có ngha là bên trong thân ca các hàm functions khác hay nó  phm vi toàn cc.đnh
ngha ca chúng có th không đc gán vào trong các bin hay các thuc tính hay xut hin
trong li gi hàm nh là tham s.đây là 1 ví d cho phép dùng các đnh ngha hàm Function
declarations vi tt c các hàm foo(), bar(), và local() đu đc đnh ngha s dng kiu mu
khai báo function declaration pattern:
// global scope
function foo() {}
function local() {
// local scope
function bar() {}
return bar;

}

1.4.Thuc tính name ca hàm function
Nhng th khác dùng đ xét đn khi ta chn 1 đnh ngha hàm function ch là có s xut hin
ca thuc tính ch có th đc name ca hàm function hay không.nhc li 1 ln na, thuc tính
này không phi là tiêu chun nhng nó li có trong rt nhiu môi trng.trong các đnh ngha
hàm function declarations và biu thc named function expressions thì thuc tính name đc
đnh ngha.trong biu thc anonymous function expressions thì nó ph thuc vào cách thc
thi; nó có th không đc đnh ngha undefined (IE) hoc đc đnh ngha vi 1 chui rng
empty string (Firefox,WebKit):
function foo() {} // declaration
var bar = function () {}; // expression
var baz = function baz() {}; // named expression
foo.name; // "foo"
bar.name; // ""
baz.name; // "baz"

thuc tính name là rt hu dng trong công c debug nh firebug.khi debugger cn hin th
cho ta thy 1 li trong 1 hàm function thì nó kim tra s có mt ca thuc tính name và s
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 17

dng nó nh là 1 vt đánh du.thuc tính name cng có th đc s dng đ gi ti cùng hàm
function 1 cách đ quy t trong chính thân ca nó.nu ta không thy thú v  trong 2 trng
hp  trên thì biu thc anonymous function expressions s tr nên d dàng hn và ít dài
dòng hn
lí do mà ta thích biu thc function expressions là vì biu thc này làm ni bt các hàm
functions cng là các đi tng objects và không có s khi to đc bit nào
chú ý : theo 1 cách k thut thì ta có th s dng 1 biu thc named function expression
và gán nó vào trong 1 bin có tên khác vi tên ca hàm function nh sau :

var foo = function bar() {};
tuy nhiên, cách thc thc thi này không đc thc thi 1 cách đúng đn tron 1 vài trình duyt
(IE) vì vy ta không nên s dng nh vy
1.5.S leo thanh ca hàm function - Function Hoisting
t nhng tho lun trc đó, ta có th kt lun rng cách thc thc thi ca các khai báo
function là rt tuyt tng đng vi cách dùng 1 biu thc named function expression.điu
này không thc s chính xác và có 1 s khác bit nm trong s leo thang hoisting
nh ta đư bit, tt c các bin và không có th gi nm trong hàm function đư đc khai báo có
th leo thang lên đu hàm function .nhng ng dng ging vy đc áp dng cho hàm bi vì
chúng ch là các đi tng đc gán vào trong các bin.
// antipattern
// for illustration only
// global functions
function
foo() {
alert('global foo');
}
function bar() {
alert('global bar');
}
function hoistMe() {
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 18

console.log(typeof foo); // "function"
console.log(typeof bar); //
"undefined"
foo(); // "local foo"
bar(); //
TypeError: bar is not a function

// function declaration:
// variable 'foo' and its implementation both get hoisted
function
foo() {
alert('local foo');
}
// function expression:
// only variable 'bar' gets hoisted
// not the implementation
var bar = function () {
alert('local bar');
};
}
hoistMe();

trong ví d trên ta thy rng, ging vi các bin thông thng, thì s hin din ca foo và bar
 bt c đâu trong hàm hoistMe() function thì đu chuyn chúng lên trên đu và ghi đè vào
foo và bar toàn cc.đim khác bit là đnh ngha đa phng ca foo() đc leo thang lên đu
và hot đng bình thng còn đnh ngha ca bar() không đc leo thang và ch có đnh
ngha ca nó.đây là lí do ti sao cho ti khi đon mư code thc thi đn đnh ngha ca bar()
thì nó không xác đnh và không đc s dng nh 1 hàm function (trong khi nó vn cn tr
li bar() toàn cc)

S leo thang, s leo
thang không có tác
dng khi đc gán
trong 1 bin và ngc
li khi xy ra s leo
thang thì nó s ghi đè
lên giá tr bin toàn cc

Leo thang tht bi
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 19

1.6.Kiu mu callback
hàm function là các đi tng objects, điu này có ngha là chúng có th đc chuyn tip
qua hàm functions khác.khi ta chuyn tip hàm function introduceBugs() nh là 1 tham s
trong hàm writeCode(), sau đó  vài đim thì hàm writeCode() có th thc thi ( hay gi ) hàm
introduceBugs().trong trng hp này thì introduceBugs() đc gi là hàm callback :
function writeCode(callback) {
// do something
callback();
//
}
function
introduceBugs() {
// make bugs
}
writeCode(
introduceBugs);
chú ý ti cách mà hàm introduceBugs() đc chuyn tip nh 1 tham s ti hàm writeCode()
mà không có du ngoc.du ngoc thc thi 1 hàm function trái vi trng hp ta mun
chuyn tip ch 1 tham chiu ti hàm function và đ writeCode() thc thi nó ( hay cách khác
là gi li nó )
1.6.1.Mt ví d mu v callback
Chúng ta cn 1 ví d và bt đu không vi 1 hàm callback đu tiên và sau đó ta bàn ti nó
sau.đ hình dung ra, ta có 1 hàm theo mc đích thông thng mà làm 1 vài công vic biên
dch và tr v 1 tp các d liu ln nh 1 kt qu.hàm function thông thng này đc gi là
findNodes(), và tác v ca nó là bò trn lên cây DOM tree ca 1 trang page và tr v 1
mng các phn t ca trang page mà nó s cun hút ta :

var
findNodes = function () {
var i = 100000, // big, heavy loop
nodes = [], // stores the result
found; // the next node found
while (i) {
i -= 1;
// complex logic here
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 20

nodes.push(found);
}
return nodes;
};

ây là 1 ý tng hay nhm gi hàm function này 1 cách chung nht và nó đn gin tr v 1
mng array ca DOM nodes mà không làm bt c gì khác vi các đi tng thc t.s logic
trong vic hiu chnh các nodes có th trong 1 hàm function khác ví d 1 hàm function gi là
hide() nh nhng gì tên nó gi ý thì nó dùng đ n các nodes trên page :
var
hide = function (nodes) {
var i = 0, max = nodes.length;
for (; i < max; i += 1) {
nodes[i].style.display = "none";
}
};
// executing the functions
hide(findNodes());


cách thc thi này là không có hiu nng x lý tt bi vì hide() phi lp li 1 ln na thông
qua các phn t trong mng nodes đc tr v bi hàm findNodes().nó s tr nên hiu qu
hn nu ta có th tránh vòng lp này và n đi các nodes ging nh vic ta chn ra chúng
trong hàm findNodes().nhng nu ta thc thi điu kin logic đ n trong findNodes(), thì nó
s không còn là 1 hàm function thông thng bi vì có s ghép cp ca điu kin logic nhn
v và điu kin logic hiu chnh.
Ta áp dng mu callback – ta chuyn tip điu kin logic đ n node nh 1 hàm callback và
y thác cho nó thc thi :
// refactored findNodes() to accept a callback
var findNodes = function (
callback) {
var i = 100000,
Hiu nng x lý không cao bi vì
ta phi duyt 2 ln mng nodes,
tc là thc hin vòng lp tn 2 ln
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 21

nodes = [],
found;
// check if callback is callable
if (typeof callback !== "function") {
callback = false;
}
while (i) {
i -= 1;
// complex logic here
// now callback:
if (callback) {
callback(found);

}
nodes.push(found);
}
return nodes;
};

S thc thi này là hin nhiên, ch có 1 tác v b sung là findNodes() thc thi kim tra tham s
callback có đc thêm vào đúng hay không, nu đúng nó s thc thi.hàm callback là không
bt buc do vy hàm findNodes() vn có th đc s dng ging nh lúc trc mà không phá
v mư code c
Thc thi hide() s đc đn gin hóa hn bi vì nó không cn ti vòng lp thông qua các
nodes :
// a callback function
var hide = function (node) {
node.style.display = "none";
};
// find the nodes and hide them as you go
findNodes(hide);

Hiu nng x lý đc ci thin,
c 2 công vic đu đc thc hin
thông qua 1 vòng lp, ta va
duyt phn t trong mng nodes
và đng thi ngay sau đó n đi
các phn t đc duyt đó
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 22

hàm callback có th là 1 hàm đư tn ti nh đư ch ra trong ví d trc hay nó có th là hàm
vô danh.ví d, ti đây cách mà ta có th ch ra các nodes bng cách s dng cùng hàm

findNodes() thông thng :
// passing an anonymous callback
findNodes(function (node) {
node.style.display = "block";
});

1.6.2.Hàm callback và phm vi tn ti ca bin trong hàm callback
Trong ví d trc, phn ni mà hàm callback đc thc thi là :
callback(parameters);
mc dù điu này khá là đn gin và s đ tt trong nhiu trng hp, đây thng là nhng
kch bn ni mà hàm callback không là 1 hàm vô danh hay là 1 hàm toàn cc, nhng nó là 1
phng thc ca 1 đi tng object.phng thc callback s dng this đ tham chiu ti đi
tng mà nó thuc v do vy điu này có th ny sinh ra cách thc thc thi không mong
mun
ví d hàm callback là hàm paint() là 1 phng thc ca đi tng có tên là myapp :
var
myapp = {};
myapp.color = "green";
myapp.paint = function (node) {
node.style.color = this.color;
};
The function findNodes() does something like this:
var findNodes = function (callback) {
//
if (typeof callback === "function") {
callback(found);
}
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 23


//
};

Nu ta gi
findNodes(myapp.paint) thì nó s không hot đng nh mong đi bi vì
this.color s không đc đnh ngha.đi tng this s tham chiu ti đi tng toàn cc
global object bi vì findNodes() là 1 hàm toàn cc.nu findNodes() là 1 phng thc ca 1
đi tng gi là dom (dom.findNodes() ) thì this bên trong hàm callback s tham chiu ti
đi tng dom thay cho đi tng mà ta mun là myapp.
 gii quyt vn đ này thì ta chuyn tip hàm callback và b sung chuyn tip đi tng
object mà hàm callback này thuc v nh sau :
findNodes(myapp.paint, myapp);
sau đó ta cng cn hiu chnh li findNodes() cho hàm này liên kt vi đi tng mà ta
chuyn tip vào :
var findNodes = function (callback, callback_obj) {
//
if (typeof callback === "function") {
callback.call(callback_obj, found);
}
//
};

1 la chn khác cho vic chuyn tip 1 đi tng và 1 phng thc đc s dng nh 1 hàm
callback là chuyn tip phng thc ging nh 1 chui string và do đó ta không phi vit lp
li đi tng 2 ln :
findNodes(myapp.paint, myapp);
chuyn thành :
findNodes("paint", myapp);
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 24


hàm findNodes() cng phi sa li nh sau :
var findNodes = function (callback, callback_obj) {
if (typeof callback === "string") {
callback = callback_obj[callback];
}
//
if (typeof callback === "function") {
callback.call(callback_obj, found);
}
//
};

1.6.3.Lng nghe s kin không đng b
Kiu mu hàm callback đc s dng hàng ngày ví d khi ta đính thêm 1 đng ký s kin
event listener vào 1 phn t trên 1 trang page thì thc cht ta cung cp 1 con tr ch ti 1 hàm
callback mà s đc gi khi s kin xy ra.đây là 1 ví d đn gin v cách mà console.log()
đc chuyn tip nh 1 hàm callback khi lng nghe s kin click :
document.addEventListener("click", console.log, false);
hu ht cách lp trình hng client đu theo hng thc thi theo s kin.khi trang page đc
ti xong thì nó kích hot 1 s kin load.sau đó ngi dùng tng tác vi trang page và gây ra
1 vài s kin khác nhau ging nh click, keypress, mouseover, mousemove, ầJS v bn
cht là thích hp vi lp trình theo hng s kin bi vì kiu mu callback – cho phép
chng trình ca ta làm vic 1 cách không đng b
câu khu hiu ni ting  Hollywood là “ đng gi cho chúng tôi mà chúng tôi s gi cho bn
“.có 1 điu không th cho nhóm tuyn chn là tr li tt c các cuc gi t tt c các ng viên
trong toàn thi gian.JS điu khin theo hng s kin k đng b và nó tng t nh vy.ch
bng cách thay th vic đa ra s đin thoi ca ta thì ta cung cp 1 hàm callback có th
đc gi khi đúng thi đim.ta cng có th cung cp nhiu hn các hàm callback nu cn.bi
vì rt có th có s kin nào đó không bao gi xy ra.ví d nu ngi dùng không bao gi

click vào “Buy now!” thì hàm function ca ta mà dùng đ kim tra tính hp l ca th thanh
toán s không bao gi đc gi
Lp trình hng đi tng trong Javascript và các kiu mu thit k
Ngô Quang Trung – email: / www.phonegap.vn/forum 25

1.6.4. tr Timeouts
1 ví d khác cho kiu mu callback là khi ta s dng phng thc timeout đc cung cp bi
windowobject: setTimeout() và setInterval().thì các phng thc này cng nhn và thc thi
các hàm callbacks :
var thePlotThickens = function () {
console.log('500ms later ');
};
setTimeout(thePlotThickens, 500);

chú ý li cách mà hàm thePlotThickens đc chuyn tip nh 1 bin mà không có du ngoc
bi vì ta không mun nó thc thi ngay lp tc nhng đn gin ch mun ch ti nó sau khi s
dng setTimeout().chuyn tip chui "thePlotThickens()" thay th cho 1 con tr hàm
function là 1 cách không kiu mu tng t vi eval().
1.6.5.Hàm callbacks trong các th vin
Hàm callback là kiu mu đn gin và rt mnh m, nó có th rt đ đ kim soát khi ta thit
k 1 th vin.mư code có trong th vin s tr nên khái quát và tái s dng li nhiu nht có
th và các hàm callbacks tr giúp vic khái quát hóa này.ta không cn d đoán và thc th
mi tính nng mà ta có th ngh ra bi vì nó s làm th vin ca ta phình to lên và hu ht
ngi s dng s không bao gi cn 1 lng ln các tính nng đó.đ thay th, ta tp trung
vào các chc nng chính và cung cp các “hooks” trong dng hàm callback mà cho phép các
phng thc ca th vin d dàng đc xây dng, m rng và tùy chnh
1.6.6.Cách tr v trong hàm functions
Các hàm functions là các đi tng objects vì vy chúng có th đc s dng và tr li các
giá tr.điu này có ngha là 1 hàm function không cn tr v 1 vài dng d liu hay 1 mng d
liu nh là kt qu ca quá trình thc thi ca nó.1 hàm function có th tr v hàm function c

th nào đó hay nó có th to ra 1 hàm function khác theo yêu cu ging nh sau :




×