Gaya yang Anda pilih untuk proyek Anda harus menjadi kriteria tertinggi. Tempatkan sebagai deskripsi dalam proyek Anda dan tautkan ke dokumen ini sebagai jaminan konsistensi gaya kode, keterbacaan, dan pemeliharaan.
1. Kosong
1. Jangan pernah mencampur ruang dan tab.
2. Mulai proyek, pilih Soft Indent (Space) atau Tab (sebagai metode indentasi) sebelum menulis kode dan menggunakannya sebagai kriteria tertinggi.
A). Untuk keterbacaan, saya selalu merekomendasikan merancang 2 lekukan lebar huruf dalam pengeditan Anda - ini setara dengan dua spasi atau dua spasi, bukan tab.
3. Jika editor Anda mendukungnya, selalu nyalakan pengaturan "Tampilkan Karakter Tak Terlihat". Manfaatnya adalah:
A). Pastikan konsistensi
B). Lepaskan spasi di ujung garis
C). Hapus ruang kosong
D). Pengajuan dan perbandingan lebih mudah dibaca
2. Percantik tata bahasa
A. Kawat gigi, kawat gigi, istirahat garis
Salinan kode adalah sebagai berikut:
// if/else/for/while/try biasanya memiliki kawat gigi, kawat gigi keriting dan beberapa baris
// Ini membantu dapat dibaca
// 2.A.1.1
// Contoh sintaks yang sulit
if (kondisi) dosomething ();
sementara (kondisi) iterasi ++;
untuk (var i = 0; i <100; i ++) someiterativeFn ();
// 2.A.1.1
// Gunakan ruang untuk meningkatkan keterbacaan
if (kondisi) {
// Penyataan
}
while (kondisi) {
// Penyataan
}
untuk (var i = 0; i <100; i ++) {
// Penyataan
}
// Praktek yang Lebih Baik:
var i,
panjang = 100;
untuk (i = 0; i <panjang; i ++) {
// Penyataan
}
// atau...
var i = 0,
panjang = 100;
untuk (; i <panjang; i ++) {
// Penyataan
}
var prop;
untuk (prop di objek) {
// Penyataan
}
if (true) {
// Penyataan
} kalau tidak {
// Penyataan
}
B. Tetapkan, Deklarasi, Fungsi (Fungsi Dinamai, Ekspresi Fungsi, Fungsi Konstruktor)
Salinan kode adalah sebagai berikut:
// 2.B.1.1
// variabel
var foo = "bar",
num = 1,
undef;
// Identifikasi literal:
var array = [],
objek = {};
// 2.B.1.2
// Menggunakan hanya satu `var` dalam lingkup (fungsi) membantu meningkatkan keterbacaan
// dan buat daftar pernyataan Anda tertib (juga menyimpan beberapa pengetikan keyboard)
// tidak bagus
var foo = "";
var bar = "";
var qx;
// Bagus
var foo = "",
bar = "",
quux;
// atau..
var // Komentar tentang variabel -variabel ini
foo = "",
bar = "",
quux;
// 2.B.1.3
// Pernyataan `var` harus selalu berada di bagian atas setiap ruang lingkup (fungsi)
// juga cocok untuk konstanta dari ecmascript 6
// tidak bagus
fungsi foo () {
// ada pernyataan sebelum variabel
var bar = "",
QUX;
}
// Bagus
fungsi foo () {
var bar = "",
QUX;
// Semua pernyataan mengejar variabel
}
// 2.B.2.1
// Deklarasi fungsi bernama
fungsi foo (arg1, argn) {
}
// Cara menggunakan
foo (arg1, argn);
// 2.B.2.2
// Deklarasi fungsi bernama
function square (angka) {
nomor pengembalian * nomor;
}
// Cara menggunakan
persegi (10);
// Gaya passing kelanjutan yang sangat tidak wajar
function square (nomor, callback) {
callback (nomor * nomor);
}
persegi (10, fungsi (persegi) {
// konten panggilan balik
});
// 2.B.2.3
// Ekspresi fungsi
var square = function (angka) {
// Kembalikan konten yang berharga dan relevan
nomor pengembalian * nomor;
};
// ekspresi fungsi dengan pengidentifikasi
// Formulir yang disukai ini memiliki fungsi tambahan yang memungkinkannya untuk memanggil dirinya sendiri
// dan ada pengidentifikasi di tumpukan
var factororial = fungsi factororial (angka) {
if (angka <2) {
kembali 1;
}
nomor pengembalian * faktorial (angka-1);
};
// 2.B.2.4
// Deklarasi Konstruktor
fungsi foobar (opsi) {
this.options = opsi;
}
// Cara menggunakan
var foobar = foobar baru ({a: "alpha"});
foobar.Options;
// {a: "alpha"}
C. Pengecualian, detailnya
Salinan kode adalah sebagai berikut:
// 2.C.1.1
// berfungsi dengan panggilan balik
foo (function () {
// Catatan: Tidak ada spasi di kurung dan `fungsi` dari panggilan fungsi pertama
});
// Fungsi menerima `array` sebagai argumen, tanpa spasi
foo (["alpha", "beta"]);
// 2.C.1.2
// Fungsi menerima `objek` sebagai argumen, tanpa spasi
foo ({
A: "Alpha",
B: "Beta"
});
// Fungsi menerima `string` literal sebagai argumen, tanpa spasi
foo ("bar");
// Tidak ada spasi di dalam kurung yang digunakan untuk pengelompokan
if (! ("foo" di obj)) {
}
D. Konsistensi selalu menang
Dalam bagian 2.A-2.C, ruang kosong diusulkan sebagai metode rekomendasi, berdasarkan pada tujuan sederhana, lebih tinggi: penyatuan. Perlu dicatat bahwa memformat preferensi, seperti "ruang kosong internal" harus opsional, tetapi hanya ada satu jenis kode sumber dari seluruh proyek.
Salinan kode adalah sebagai berikut:
// 2.D.1.1
if (kondisi) {
// Penyataan
}
while (kondisi) {
// Penyataan
}
untuk (var i = 0; i <100; i ++) {
// Penyataan
}
if (true) {
// Penyataan
} kalau tidak {
// Penyataan
}
E. tanda kutip
Tidak masalah apakah Anda memilih kutipan tunggal atau ganda, mereka tidak membuat perbedaan parsing dalam javascript. Yang benar -benar perlu diamanatkan adalah konsistensi. Jangan pernah mencampur dua kutipan dalam proyek yang sama, pilih satu, dan tetap konsisten.
F. akhir garis dan garis kosong
Leaving Blank akan mematahkan perbedaan dan perubahan penggunaan tidak dapat dibaca. Pertimbangkan untuk memasukkan kait pra-komitmen yang secara otomatis menghapus ruang di ujung garis dan garis kosong.
3. Tipe Detection (dari JQuery Core Style Guidelines)
A. Tipe Langsung (Jenis Aktual, Jenis Aktual)
Rangkaian:
Salinan kode adalah sebagai berikut:
typeof variable === "string"
Nomor:
Salinan kode adalah sebagai berikut:
typeof variable === "nomor"
Boolean:
Salinan kode adalah sebagai berikut:
tipe variabel === "boolean"
Obyek:
Salinan kode adalah sebagai berikut:
typeof variable === "objek"
Array:
Salinan kode adalah sebagai berikut:
Array.isArray (array likeAbject)
(Jika memungkinkan)
Node:
Salinan kode adalah sebagai berikut:
elem.nodetype === 1
batal:
Salinan kode adalah sebagai berikut:
variabel === NULL
nol atau tidak terdefinisi:
Salinan kode adalah sebagai berikut:
variabel == null
belum diartikan:
Variabel global:
Salinan kode adalah sebagai berikut:
tipe variabel === "tidak ditentukan"
Variabel lokal:
Salinan kode adalah sebagai berikut:
variabel === tidak ditentukan
milik:
Salinan kode adalah sebagai berikut:
Object.prop === Tidak ditentukan
Object.hasownproperty (prop)
"Prop" di objek
B. Konversi tipe (tipe yang dipaksa, tipe yang dipaksa)
Pertimbangkan arti dari yang berikut ...
Diberikan html:
Salinan kode adalah sebagai berikut:
<input type = "text" id = "foo-input" value = "1">
// 3.B.1.1
// `foo` telah diberi nilai` 0`, ketik `angka`
var foo = 0;
// typeof foo;
// "nomor"
...
// Dalam kode berikutnya, Anda perlu memperbarui `foo` dan menetapkan nilai baru yang diperoleh di elemen input
foo = document.getElementById ("foo-input"). nilai;
// Jika Anda menguji `typeof foo` sekarang, hasilnya akan` string`
// Ini berarti Anda memiliki logika yang mirip dengan ini saat mendeteksi `foo` dalam pernyataan IF:
if (foo === 1) {
pentingTask ();
}
// `penting ()` tidak akan pernah dieksekusi, bahkan jika `foo` memiliki nilai" 1 "
// 3.B.1.2
// Anda dapat dengan cerdik menggunakan operator +/- unary untuk melemparkan tipe untuk menyelesaikan masalah:
foo = +document.getElementById ("foo-input"). nilai;
// ^ + operator unary mengubah objek operasi menjadi haknya menjadi `angka`
// typeof foo;
// "nomor"
if (foo === 1) {
pentingTask ();
}
// `penting ()` akan dipanggil
Berikut adalah beberapa contoh untuk casting:
Salinan kode adalah sebagai berikut:
// 3.B.2.1
var number = 1,
string = "1",
bool = false;
nomor;
// 1
angka + "";
// "1"
rangkaian;
// "1"
+string;
// 1
+string ++;
// 1
rangkaian;
// 2
bool;
// PALSU
+bool;
// 0
bool + "";
// "PALSU"
// 3.B.2.2
var number = 1,
string = "1",
bool = true;
string === angka;
// PALSU
string === Number + "";
// BENAR
+string === angka;
// BENAR
bool === angka;
// PALSU
+bool === Nomor;
// BENAR
bool === string;
// PALSU
bool === !! string;
// BENAR
// 3.B.2.3
var array = ["a", "b", "c"];
!! ~ array.indexof ("a");
// BENAR
!! ~ array.indexof ("b");
// BENAR
!! ~ array.indexof ("c");
// BENAR
!! ~ array.indexof ("d");
// PALSU
// Perlu dicatat bahwa di atas semua "tidak perlu pintar"
// Gunakan skema yang jelas untuk membandingkan nilai yang dikembalikan
// misalnya indeks dari:
if (array.indexof ("a")> = 0) {
// ...
}
// 3.B.2.3
var num = 2.5;
parseint (num, 10);
// setara dengan ...
~~ num;
num >> 0;
num >>> 0;
// hasilnya semuanya 2
// Selalu ingat, nilai -nilai negatif akan diperlakukan secara berbeda ...
var neg = -2.5;
parseint (neg, 10);
// setara dengan ...
~~ neg;
neg >> 0;
// hasilnya semua -2
// Tetapi...
neg >>> 0;
// Hasilnya adalah 4294967294
4. Operasi komparatif
Salinan kode adalah sebagai berikut:
// 4.1.1
// Saat menilai apakah array memiliki panjang, relatif menggunakan ini:
if (array.length> 0) ...
// ... untuk menentukan keasliannya, silakan gunakan ini:
if (array.length) ...
// 4.1.2
// Saat menilai apakah array kosong, relatif menggunakan ini:
if (array.length === 0) ...
// ... untuk menentukan keasliannya, silakan gunakan ini:
if (! array.length) ...
// 4.1.3
// Saat menilai apakah string kosong, relatif menggunakan ini:
if (string! == "") ...
// ... untuk menentukan keasliannya, silakan gunakan ini:
if (string) ...
// 4.1.4
// Saat menilai bahwa string kosong, relatif menggunakan ini:
if (string === "") ...
// ... untuk menentukan keasliannya, silakan gunakan ini:
if (! string) ...
// 4.1.5
// Saat menilai bahwa referensi itu benar, relatif menggunakan ini:
if (foo === true) ...
// ... Hakim seperti yang Anda pikirkan, nikmati manfaat fitur bawaan:
if (foo) ...
// 4.1.6
// Saat menilai bahwa referensi itu salah, relatif menggunakan ini:
if (foo === false) ...
// ... Konversikan ke true menggunakan tanda seru
if (! foo) ...
// ... Perlu dicatat bahwa ini akan cocok dengan 0, "", null, tidak terdefinisi, nan
// Jika Anda _must_ adalah tipe boolean false, silakan gunakan ini:
if (foo === false) ...
// 4.1.7
// Jika Anda ingin menghitung referensi, itu mungkin nol atau tidak terdefinisi, tetapi tidak salah, "" atau 0,
// relatif menggunakan ini:
if (foo === null || foo === tidak ditentukan) ...
// ... nikmati manfaat casting tipe ==, seperti ini:
if (foo == null) ...
// Ingatlah bahwa menggunakan == akan membuat `null` cocok` null` dan `tidak ditentukan`
// tapi tidak `false`," "atau 0
null == tidak terdefinisi
Selalu menilai nilai -nilai terbaik dan paling tepat, yang di atas adalah panduan daripada dogma.
Salinan kode adalah sebagai berikut:
// 4.2.1
// Instruksi untuk Konversi Jenis dan Operasi Perbandingan
// pertama kali `===`, `==` diikuti (kecuali dibutuhkan perbandingan tipe longgar)
// `===` tidak selalu melakukan konversi jenis, yang berarti:
"1" === 1;
// PALSU
// `==` mengubah jenisnya, yang berarti:
"1" == 1;
// BENAR
// 4.2.2
// boolean, benar & palsu
// Boolean:
Benar, salah
// nyata:
"foo", 1
// pseudo:
"", 0, null, tidak terdefinisi, nan, batal 0
5. Gaya praktis
Salinan kode adalah sebagai berikut:
// 5.1.1
// modul praktis
(function (global) {
var module = (function () {
var data = "rahasia";
kembali {
// ini adalah nilai boolean
BOOL: Benar,
// string
String: "A String",
// sebuah array
Array: [1, 2, 3, 4],
// Objek
Objek: {
Lang: "en-us"
},
getData: function () {
// Dapatkan nilai `data`
pengembalian data;
},
setData: function (value) {
// Kembalikan nilai `data` yang ditetapkan
return (data = value);
}
};
}) ();
// Beberapa lainnya akan muncul di sini
// Ubah modul Anda menjadi objek global
global.module = modul;
})( ini );
// 5.2.1
// fungsi pembuatan praktis
(function (global) {
function ctor (foo) {
this.foo = foo;
kembalikan ini;
}
Ctor.prototype.getFoo = function () {
kembalikan this.foo;
};
Ctor.prototype.setFoo = function (val) {
return (this.foo = val);
};
// Jangan gunakan `baru` untuk memanggil fungsi build, Anda mungkin melakukan ini:
var ctor = function (foo) {
mengembalikan ctor baru (foo);
};
// Ubah fungsi build kami menjadi objek global
global.ctor = ctor;
})( ini );
6. Penamaan
A. Anda bukan kompiler/kompresor manusia, jadi cobalah untuk berubah menjadi satu.
Kode berikut adalah contoh penamaan yang sangat buruk:
Salinan kode adalah sebagai berikut:
// 6.a.1.1
// kode contoh yang buruk
fungsi q (s) {
return document.queryselectorall (s);
}
var i, a = [], els = q ("#foo");
untuk (i = 0; i <els.length; i ++) {a.push (els [i]);}
Tidak ada keraguan bahwa Anda telah menulis kode tersebut - semoga tidak muncul lagi dari hari ini.
Berikut adalah kode dengan logika yang sama, tetapi dengan penamaan yang lebih kuat, tepat (dan struktur yang dapat dibaca):
Salinan kode adalah sebagai berikut:
// 6.a.2.1
// Kode contoh yang ditingkatkan bernama
Fungsi kueri (pemilih) {
return document.queryselectorall (pemilih);
}
var idx = 0,
elemen = [],
kecocokan = kueri ("#foo"),
panjang = cocok. Panjang;
untuk (; idx <length; idx ++) {
elemen.push (cocok [IDX]);
}
Beberapa Tip Penamaan Tambahan:
Salinan kode adalah sebagai berikut:
// 6.a.3.1
// String bernama
`Dog` adalah string
// 6.a.3.2
// Nama array
`['Dogs']` adalah array yang berisi `string anjing
// 6.a.3.3
// nama fungsi, objek, instance, dll.
Camlcase; fungsi dan deklarasi var
// 6.a.3.4
// Sebutkan pembangun, prototipe, dll.
Pascalcase; Bangun fungsi
// 6.a.3.5
// Sebutkan ekspresi reguler
rdesc = //;
// 6.a.3.6
// dari Panduan Gaya Perpustakaan Penutupan Google
functionNamesLikethis;
variablenameslikethis;
Constructornameslikethis;
Enumnameslikethis;
MethodNamesLikethis;
Symbolic_constants_ lose_this;
B. hadapi ini
Selain menggunakan panggilan terkenal dan terapkan,. BInd (ini) atau secara fungsional setara dengan itu selalu lebih disukai. Buat deklarasi fungsi batas untuk panggilan berikutnya, menggunakan alias ketika tidak ada opsi yang lebih baik.
Salinan kode adalah sebagai berikut:
// 6.B.1
perangkat fungsi (opts) {
this.value = null;
// Buat aliran asinkron baru, ini akan terus dipanggil
stream.read (opts.path, function (data) {
// Gunakan aliran untuk mengembalikan nilai data terbaru dan perbarui nilai instance
this.value = data;
} .bind (ini));
// Kontrol frekuensi pemicu peristiwa
setInterval (function () {
// Publikasikan acara terkontrol
this.emit ("event");
} .bind (ini), opts.freq || 100);
}
// Misalkan kita telah mewarisi Eventemitter;)
Ketika tidak dapat dijalankan, setara dengan .Bind tersedia di sebagian besar perpustakaan JavaScript modern.
Salinan kode adalah sebagai berikut:
// 6.B.2
// Contoh: Lodash/Underscore, _.bind ()
perangkat fungsi (opts) {
this.value = null;
stream.read (opts.path, _.bind (function (data) {
this.value = data;
}, ini) );
setInterval (_. bind (function () {
this.emit ("event");
}, ini), opts.freq || 100);
}
// Contoh: jQuery.proxy
perangkat fungsi (opts) {
this.value = null;
stream.read (opts.path, jQuery.proxy (function (data) {
this.value = data;
}, ini) );
setInterval (jQuery.proxy (function () {
this.emit ("event");
}, ini), opts.freq || 100);
}
// Contoh: dojo.hitch
perangkat fungsi (opts) {
this.value = null;
stream.read (opts.path, dojo.hitch (this, function (data) {
this.value = data;
}));
setInterval (dojo.hitch (this, function () {
this.emit ("event");
}), opts.freq || 100);
}
Berikan kandidat untuk membuat alias untuk ini, dengan diri sebagai pengidentifikasi. Ini sangat mungkin memiliki bug dan harus dihindari sebanyak mungkin.
Salinan kode adalah sebagai berikut:
// 6.B.3
perangkat fungsi (opts) {
var self = ini;
this.value = null;
stream.read (opts.path, function (data) {
self.value = data;
});
setInterval (function () {
self.emit ("acara");
}, opts.freq || 100);
}
C. Gunakan Thisarg
Beberapa metode prototipe dalam ES 5.1 memiliki tag Thisarg khusus yang dibangun, gunakan sebanyak mungkin
Salinan kode adalah sebagai berikut:
// 6.C.1
var obj;
obj = {f: "foo", b: "bar", q: "qox"};
Objek.keys (obj) .foreach (function (key) {
// | ini | Sekarang `obj`
console.log (ini [kunci]);
}, obj); // <- parameter terakhir adalah `thisarg`
// Cetak ...
// "foo"
// "batang"
// "QUX"
Thisarg dapat digunakan di array.prototype.every, array.prototype.foreach, array.prototype.some, array.prototype.map, dan array.prototype.filter.
7. Misc
Gagasan dan ide yang akan dijelaskan bagian ini tidak dogmatis. Sebaliknya, lebih dianjurkan untuk ingin tahu tentang praktik yang ada untuk mencoba memberikan solusi yang lebih baik untuk menyelesaikan tugas pemrograman JavaScript umum.
A. Hindari menggunakan sakelar. Penelusuran Metode Modern akan berfungsi daftar hitam dengan ekspresi sakelar.
Tampaknya Firefox dan Chrome telah membuat perbaikan yang signifikan untuk beralih. http://jsperf.com/switch-vs-Object-literal-vs-Module
Perlu dicatat bahwa perbaikan dapat dilihat di sini: https://github.com/rwldrn/idiomatic.js/issues/13
Salinan kode adalah sebagai berikut:
// 7.a.1.1
// Contoh Pernyataan Beralih
switch (foo) {
kasus "alpha":
alfa();
merusak;
kasus "beta":
beta ();
merusak;
bawaan:
// Cabang default
merusak;
}
// 7.a.1.2
// Metode yang dapat mendukung kombinasi dan penggunaan kembali adalah menggunakan objek untuk menyimpan "casing".
// Gunakan fungsi untuk melakukan delegasi:
VAR Case, Delegator;
// Nilai pengembalian hanya untuk penjelasan
case = {
alpha: function () {
// Penyataan
// nilai pengembalian
return ["alpha", argumen.length];
},
beta: function () {
// Penyataan
// nilai pengembalian
return ["beta", argumen.length];
},
_default: function () {
// Penyataan
// nilai pengembalian
return ["default", argumen.length];
}
};
delegator = function () {
var args, kunci, delegasi;
// Konversi `argumen` menjadi array
args = [] .slice.call (argumen);
// Ekstrak nilai terakhir dari `argumen`
key = args.shift ();
// panggil cabang default
delegate = case._default;
// mendelegasikan metode dari objek
if (case.hasownproperty (key)) {
delegasi = kasus [kunci];
}
// ruang lingkup arg dapat diatur ke nilai tertentu,
// Dalam hal ini, | NULL | baik -baik saja
return delegate.apply (null, args);
};
// 7.a.1.3
// Gunakan API di 7.A.1.2:
Delegator ("Alpha", 1, 2, 3, 4, 5);
// ["alpha", 5]
// Tentu saja, nilai kunci `case` dapat dengan mudah diubah ke nilai apa pun
var casey, someUserInput;
// Apakah ada input yang mungkin dari beberapa bentuk?
SomeUserInput = 9;
if (someUserInput> 10) {
casey = "alpha";
} kalau tidak {
casey = "beta";
}
// atau...
casey = someUserInput> 10? "Alpha": "beta";
// Kemudian...
Delegator (Casey, SomeUserInput);
// ["beta", 1]
// Tentu saja, ini bisa dilakukan ...
delegator ();
// ["default", 0]
B. Nilai mengembalikan terlebih dahulu untuk meningkatkan keterbacaan kode tanpa banyak perbedaan kinerja
Salinan kode adalah sebagai berikut:
// 7.b.1.1
// tidak bagus:
fungsi returnLate (foo) {
var ret;
if (foo) {
ret = "foo";
} kalau tidak {
ret = "quux";
}
kembali kembali;
}
// Bagus:
fungsi returnearly (foo) {
if (foo) {
mengembalikan "foo";
}
mengembalikan "quux";
}
8. Objek Asli & Host (Catatan: Saya selalu berpikir bahwa objek host tidak boleh diterjemahkan, jadi saya akan menerjemahkannya sesuai dengan metode penulisan umum)
Prinsip paling mendasar adalah:
Jangan lakukan hal bodoh, segalanya akan selalu menjadi lebih baik.
Untuk memperkuat konsep ini, silakan tonton demonstrasi ini:
"Semuanya Diizinkan: Ekstensi Asli" oleh Andrew Dupont (JSCONF2011, Portland, Oregon)
http://blip.tv/jsconf/jsconf2011-andrew-dupont-everything-is-permitted-extending-built-ins-5211542
9. Komentar
Komentar baris tunggal ditempatkan di atas kode sebagai pilihan pertama
Beberapa baris baik -baik saja
Komentar di akhir baris harus dihindari!
Metode JSDOC juga bagus, tetapi butuh lebih banyak waktu
10. Gunakan satu bahasa saja
Terlepas dari bahasa apa yang dikelola program (atau tim) menetapkan bahwa program digunakan, program harus ditulis hanya dalam bahasa yang sama.
lampiran
Koma pertama
Semua proyek yang menggunakan dokumen ini sebagai panduan gaya dasar tidak memungkinkan untuk format kode pra-Comma kecuali secara eksplisit ditentukan atau diharuskan oleh penulis.