4.1 Bahasa JavaScript permulaan cepat

Penulis:Kebaikan, Dicipta: 2019-04-26 11:46:12, Dikemas kini: 2019-04-27 11:53:43

Latar Belakang

Bahagian ini memberikan sedikit latar belakang tentang JavaScript untuk membantu anda memahami mengapa ia adalah cara ia.

JavaScript Versus ECMAScript

ECMAScript adalah nama rasmi untuk JavaScript. Nama baru menjadi perlu kerana terdapat tanda dagangan pada JavaScript (yang dimiliki pada asalnya oleh Sun, kini oleh Oracle). Pada masa ini, Mozilla adalah salah satu daripada beberapa syarikat yang dibenarkan menggunakan nama JavaScript secara rasmi kerana ia menerima lesen lama yang lalu.

  • JavaScript bermaksud bahasa pengaturcaraan.
  • ECMAScript adalah nama yang digunakan oleh spesifikasi bahasa. Oleh itu, setiap kali merujuk kepada versi bahasa, orang berkata ECMAScript. Versi JavaScript semasa adalah ECMAScript 5; ECMAScript 6 sedang dibangunkan.

Pengaruh dan Sifat Bahasa

Pencipta JavaScript, Brendan Eich, tidak mempunyai pilihan selain membuat bahasa ini dengan sangat cepat (atau teknologi lain yang lebih buruk akan diterima pakai oleh Netscape). Dia meminjam dari beberapa bahasa pengaturcaraan: Java (sintaks, nilai primitif berbanding objek), Skema dan AWK (fungsi kelas pertama), Self (warisan prototaip), dan Perl dan Python (string, array, dan ungkapan tetap).

JavaScript tidak mempunyai pengendalian pengecualian sehingga ECMAScript 3, yang menjelaskan mengapa bahasa itu sering menukar nilai secara automatik dan sering gagal secara senyap: pada mulanya tidak dapat membuang pengecualian.

Di satu pihak, JavaScript mempunyai ciri-ciri dan tidak mempunyai sedikit fungsi (variabel ruang lingkup blok, modul, sokongan untuk subkelas, dan lain-lain). Di sisi lain, ia mempunyai beberapa ciri yang kuat yang membolehkan anda mengatasi masalah ini. Dalam bahasa lain, anda belajar ciri bahasa. Dalam JavaScript, anda sering belajar corak sebaliknya.

Memandangkan pengaruhnya, tidak menghairankan bahawa JavaScript membolehkan gaya pengaturcaraan yang merupakan campuran pengaturcaraan fungsional (fungsi peringkat tinggi; peta terbina dalam, mengurangkan, dll.) dan pengaturcaraan berorientasikan objek (objek, warisan).

Sintaks

Bahagian ini menerangkan prinsip sintaksis asas JavaScript.

Ringkasan Sintaks

Beberapa contoh sintaks:

// Two slashes start single-line comments

var x;  // declaring a variable

x = 3 + y;  // assigning a value to the variable `x`

foo(x, y);  // calling function `foo` with parameters `x` and `y`
obj.bar(3);  // calling method `bar` of object `obj`

// A conditional statement
if (x === 0) {  // Is `x` equal to zero?
    x = 123;
}

// Defining function `baz` with parameters `a` and `b`
function baz(a, b) {
    return a + b;
}

Perhatikan dua kegunaan berbeza tanda sama:

  • Satu tanda sama (=) digunakan untuk menetapkan nilai kepada pembolehubah.
  • Tanda tiga sama (===) digunakan untuk membandingkan dua nilai (lihat Operator Kesamaan).

Perkataan Berbeza dengan Ungkapan

Untuk memahami sintaks JavaScript, anda harus tahu bahawa ia mempunyai dua kategori sintaksis utama: pernyataan dan ungkapan:

  • Perkataan do things. Program adalah urutan pernyataan. Berikut adalah contoh pernyataan, yang mengisytiharkan (menciptakan) pembolehubah foo:
var foo;
  • Ungkapan menghasilkan nilai. Mereka adalah argumen fungsi, sisi kanan tugasan, dan lain-lain. Berikut adalah contoh ungkapan:
3 * 7

Perbezaan antara pernyataan dan ungkapan paling jelas dengan fakta bahawa JavaScript mempunyai dua cara yang berbeza untuk melakukan if-then-else sama ada sebagai pernyataan:

var x;
if (y >= 0) {
    x = y;
} else {
    x = -y;
}

atau sebagai ungkapan:

var x = y >= 0 ? y : -y;

Anda boleh menggunakan yang terakhir sebagai argumen fungsi (tetapi bukan yang pertama):

myFunction(y >= 0 ? y : -y)

Akhirnya, di mana sahaja JavaScript mengharapkan pernyataan, anda juga boleh menggunakan ungkapan; contohnya:

foo(7, 1);

Seluruh baris adalah pernyataan (yang dipanggil pernyataan ungkapan), tetapi panggilan fungsi foo ((7, 1) adalah ungkapan.

Semikolon

Semikolon adalah pilihan dalam JavaScript. Walau bagaimanapun, saya mengesyorkan sentiasa memasukkannya, kerana jika tidak JavaScript boleh menebak salah mengenai akhir pernyataan. butiran dijelaskan dalam Automatic Semicolon Insertion.

Semikolon menamatkan pernyataan, tetapi bukan blok. Terdapat satu kes di mana anda akan melihat semikolon selepas blok: ungkapan fungsi adalah ungkapan yang berakhir dengan blok. Jika ungkapan sedemikian datang terakhir dalam pernyataan, ia diikuti dengan semikolon:

// Pattern: var _ = ___;
var x = 3 * 7;
var f = function () { };  // function expr. inside var decl.

Maklumat

JavaScript mempunyai dua jenis komen: komen satu baris dan komen berbilang baris. Komen satu baris bermula dengan // dan diakhiri pada akhir baris:

x++; // single-line comment

Komen berbilang baris dibatasi oleh /* dan */:

/* This is
   a multiline
   comment.
 */

Variabel dan Tugas

Pemboleh ubah dalam JavaScript diisytiharkan sebelum digunakan:

var foo;  // declare variable `foo`

Tugas

Anda boleh mengisytiharkan pembolehubah dan menetapkan nilai pada masa yang sama:

var foo = 6;

Anda juga boleh menetapkan nilai kepada pembolehubah sedia ada:

foo = 4;  // change variable `foo`

Pengendali Penugasan Kompaun

Terdapat pengendali penugasan gabungan seperti +=. Dua penugasan berikut adalah bersamaan:

x += 1;
x = x + 1;

Pengiktirafan dan nama pembolehubah

Pengiktirafan adalah nama yang memainkan pelbagai peranan sintaksis dalam JavaScript. Sebagai contoh, nama pembolehubah adalah pengiktirafan.

Secara kasar, aksara pertama pengenal boleh menjadi sebarang huruf Unicode, tanda dolar ($), atau tanda bawah (_).

arg0
_tmp
$elem
π

Pengiktirafan berikut adalah perkataan yang dikhaskanmereka adalah sebahagian daripada sintaks dan tidak bolehdigunakan sebagai nama pembolehubah (termasuk nama fungsi dan nama parameter):

img

Tiga pengenal berikut bukan perkataan yang disediakan, tetapi anda harus memperlakukan mereka seolah-olah mereka:

img

Akhirnya, anda juga harus menjauhkan diri dari nama-nama pembolehubah global standard. anda boleh menggunakannya untuk pembolehubah tempatan tanpa memecahkan apa-apa, tetapi kod anda masih menjadi mengelirukan.

Nilai

JavaScript mempunyai banyak nilai yang kita harapkan dari bahasa pengaturcaraan: boolean, nombor, rentetan, array, dan sebagainya. Semua nilai dalam JavaScript mempunyai sifat. Setiap sifat mempunyai kunci (atau nama) dan nilai. Anda boleh memikirkan sifat seperti medan rekod. Anda menggunakan operator titik (.) untuk membaca sifat:

value.propKey

Sebagai contoh, rentetan abc mempunyai panjang sifat:

> var str = 'abc';
> str.length
3

Yang terdahulu juga boleh ditulis sebagai:

> 'abc'.length
3
The dot operator is also used to assign a value to a property:

> var obj = {};  // empty object
> obj.foo = 123; // create property `foo`, set it to 123
123
> obj.foo
123

Dan anda boleh menggunakannya untuk memanggil kaedah:

> 'hello'.toUpperCase()
'HELLO'

Dalam contoh sebelumnya, kita telah memanggil kaedah toUpperCase() pada nilai hello.

Nilai-Nilai Primitif Melawan Objek

JavaScript membuat perbezaan agak sewenang-wenang antara nilai:

  • Nilai primitif adalah boolean, nombor, rentetan, sifar, dan tidak ditakrifkan.
  • Semua nilai lain adalah objek. Perbezaan utama antara kedua-duanya adalah bagaimana mereka dibandingkan; setiap objek mempunyai identiti yang unik dan hanya (tepatnya sama dengan dirinya sendiri):
> var obj1 = {};  // an empty object
> var obj2 = {};  // another empty object
> obj1 === obj2
false
> obj1 === obj1
true

Sebaliknya, semua nilai primitif yang mengkodkan nilai yang sama dianggap sama:

> var prim1 = 123;
> var prim2 = 123;
> prim1 === prim2
true

Dua bahagian seterusnya menerangkan nilai dan objek primitif dengan lebih terperinci.

Nilai-Nilai Primitif

Berikut adalah semua nilai primitif (atau primitif untuk pendek):

  • Boolean: benar, palsu (lihat Boolean)
  • Bilangan: 1736, 1.351 (lihat Bilangan)
  • Senar: abc, abc (lihat Senar)
  • Dua nonvalues: tidak ditakrifkan, null (lihat tidak ditakrifkan dan null)

Primitif mempunyai ciri-ciri berikut:

Dibandingkan mengikut nilai

kandungan adalah dibandingkan:

> 3 === 3
true
> 'abc' === 'abc'
true

### Selalu tidak berubah Ciri-ciri tidak boleh diubah, ditambah, atau dikeluarkan:

> var str = 'abc';

> str.length = 1; // try to change property `length`
> str.length      // ⇒ no effect
3

> str.foo = 3; // try to create property `foo`
> str.foo      // ⇒ no effect, unknown property
undefined

(Membaca sifat yang tidak diketahui sentiasa mengembalikan tidak ditakrifkan.)

Objek

Semua nilai bukan primitif adalah objek. Jenis objek yang paling biasa ialah:

  • Objek biasa, yang boleh dicipta oleh objek literal (lihat Objek Tunggal):
{
    firstName: 'Jane',
    lastName: 'Doe'
}

Objek sebelumnya mempunyai dua sifat: nilai sifat firstName adalah Jane dan nilai sifat lastName adalah Doe.

  • Array, yang boleh dicipta oleh array literals (lihat Arrays):
[ 'apple', 'banana', 'cherry' ]

Array sebelumnya mempunyai tiga elemen yang boleh diakses melalui indeks nombor. Sebagai contoh, indeks apple adalah 0.

  • Ungkapan biasa, yang boleh dicipta oleh literal ungkapan biasa (lihat Ungkapan biasa):
/^a+b+$/

Objek mempunyai ciri-ciri berikut:

Dibandingkan dengan rujukan

Identiti dibandingkan; setiap nilai mempunyai identiti sendiri:

> ({} === {})  // two different empty objects
false

> var obj1 = {};
> var obj2 = obj1;
> obj1 === obj2
true

Boleh diubah secara lalai

Anda biasanya boleh bebas mengubah, menambah, dan membuang sifat (lihat Objek Tunggal):

> var obj = {};
> obj.foo = 123; // add property `foo`
> obj.foo
123

tidak ditakrifkan dan sifar

Kebanyakan bahasa pengaturcaraan mempunyai nilai yang menunjukkan maklumat yang hilang. JavaScript mempunyai dua jenis nonvalues, undefined dan null:

  • undefined bermaksud tiada nilai. Variabel yang tidak dimulakan tidak ditakrifkan:
> var foo;
> foo
undefined

Parameter yang hilang tidak ditakrifkan:

> function f(x) { return x }
> f()
undefined

Jika anda membaca harta yang tidak wujud, anda mendapat tidak ditakrifkan:

> var obj = {}; // empty object
> obj.foo
undefined
  • null bermaksud tidak ada objek. Ia digunakan sebagai nonvalue apabila objek dijangkakan (parameter, terakhir dalam rantaian objek, dan lain-lain).

Peringatan

undefined dan null tidak mempunyai sifat, bahkan kaedah standard seperti toString().

Memeriksa untuk tidak ditakrifkan atau sifar

Fungsi biasanya membolehkan anda untuk menunjukkan nilai yang hilang melalui sama ada tidak ditakrifkan atau sifar.

if (x === undefined || x === null) {
    ...
}

Anda juga boleh mengeksploitasi hakikat bahawa kedua-dua tidak ditakrifkan dan sifar dianggap salah:

if (!x) {
    ...
}

Peringatan

false, 0, NaN, dan juga dianggap palsu (lihat Benar dan Palsu).

Mengkategorikan Nilai Menggunakan jenis dan contoh

Terdapat dua pengendali untuk mengkategorikan nilai: typeof digunakan terutamanya untuk nilai primitif, manakala instanceof digunakan untuk objek. jenis ini kelihatan seperti ini:

typeof value

Ia mengembalikan rentetan yang menggambarkan type nilai. Berikut adalah beberapa contoh:

> typeof true
'boolean'
> typeof 'abc'
'string'
> typeof {} // empty object literal
'object'
> typeof [] // empty array literal
'object'

Jadual berikut menyenaraikan semua hasil jenis:

img

object adalah bug yang tidak boleh diperbaiki, kerana ia akan memecahkan kod yang sedia ada.

Contoh ini kelihatan seperti ini:

value instanceof Constr

Ia mengembalikan benar jika nilai adalah objek yang telah dicipta oleh pembina Constr (lihat pembina: kilang untuk objek). Berikut adalah beberapa contoh:

> var b = new Bar();  // object created by constructor Bar
> b instanceof Bar
true

> {} instanceof Object
true
> [] instanceof Array
true
> [] instanceof Object  // Array is a subconstructor of Object
true

> undefined instanceof Object
false
> null instanceof Object
false

Boolean

Jenis boolean primitif terdiri daripada nilai benar dan palsu. Operator berikut menghasilkan boolean:

  • Operator logik binari: && (Dan),
  • Operator logik awalan:! (Tidak)
  • Operator perbandingan:Operator kesamaan: ===,!==, ==,!=
  • Operator pemesanan (untuk rentetan dan nombor): >, >=, <, <=

Benar dan Palsu

Setiap kali JavaScript mengharapkan nilai boolean (contohnya, untuk syarat pernyataan if), mana-mana nilai boleh digunakan. Ia akan ditafsirkan sebagai benar atau salah. Nilai berikut ditafsirkan sebagai salah:

  • tidak ditakrifkan, kosong
  • Boolean: false
  • Bilangan: 0, NaN
  • String:

Semua nilai lain (termasuk semua objek!) dianggap benar. Nilai yang ditafsirkan sebagai palsu dipanggil palsu, dan nilai yang ditafsirkan sebagai benar dipanggil benar. Boolean ((), dipanggil sebagai fungsi, menukar parameternya kepada boolean. Anda boleh menggunakannya untuk menguji bagaimana nilai ditafsirkan:

> Boolean(undefined)
false
> Boolean(0)
false
> Boolean(3)
true
> Boolean({}) // empty object
true
> Boolean([]) // empty array
true

Operator Logik Binari

Operator logik binari dalam JavaScript adalah litar pendek. iaitu, jika operand pertama mencukupi untuk menentukan hasilnya, operand kedua tidak dinilai. Sebagai contoh, dalam ungkapan berikut, fungsi foo() tidak pernah dipanggil:

false && foo()
true  || foo()

Selain itu, pengendali logik binari mengembalikan salah satu operand merekayang mungkin atau mungkin bukan boolean.

Dan (&&)

Jika operand pertama adalah salah, kembalikan. Jika tidak, kembalikan operand kedua:

> NaN && 'abc'
NaN
> 123 && 'abc'
'abc'

Atau (kamu)

Jika operand pertama adalah benar, kembalikan. Jika tidak, kembalikan operand kedua:

> 'abc' || 123
'abc'
> '' || 123
123

Pengendali Kesamaan

JavaScript mempunyai dua jenis kesamaan:

  • Normal, atau merendahkan, (tidak sama): == dan!=
  • Ketat (tidak) sama: === dan!==

Kesamaan normal menganggap (terlalu) banyak nilai sama (perinciannya dijelaskan dalam Kesamaan Normal (==,!=)), yang boleh menyembunyikan bug. Oleh itu, selalu menggunakan kesamaan yang ketat disyorkan.

Bilangan

Semua nombor dalam JavaScript adalah titik terapung:

> 1 === 1.0
true

Nombor khas termasuk yang berikut:

NaN (bukan nombor) Nilai ralat:

> Number('xyz')  // 'xyz' can’t be converted to a number
NaN

Tak terhingga Juga kebanyakannya nilai ralat:

> 3 / 0
Infinity
> Math.pow(2, 1024)  // number too large
Infinity

Infinity lebih besar daripada nombor lain (kecuali NaN). Begitu juga, -Infinity lebih kecil daripada nombor lain (kecuali NaN). Itu menjadikan nombor ini berguna sebagai nilai lalai (contohnya, apabila anda mencari minimum atau maksimum).

Pengendali

JavaScript mempunyai pengendali aritmatika berikut (lihat Operator Aritmatika):

  • Penambahan: nombor1 + nombor2
  • Pengurangan: nombor1 - nombor2
  • Kali: nombor1 * nombor2
  • Bahagian: nombor1 / nombor2
  • Selebihnya: nombor1 % nombor2
  • Peningkatan: ++berubah, berubah++
  • Decrement: berubah, berubah-ubah
  • Negatif: -nilai
  • Tukar kepada nombor: +nilai

Objek global Matematika (lihat Matematika) menyediakan lebih banyak operasi aritmatika, melalui fungsi.

JavaScript juga mempunyai operator untuk operasi bitwise (contohnya, bitwise And; lihat Operator Bitwise).

String

String boleh dicipta secara langsung melalui literals string. literals tersebut dibatasi oleh tanda petikan tunggal atau berganda. backslash () melepaskan aksara dan menghasilkan beberapa aksara kawalan. Berikut adalah beberapa contoh:

'abc'
"abc"

'Did she say "Hello"?'
"Did she say \"Hello\"?"

'That\'s nice!'
"That's nice!"

'Line 1\nLine 2'  // newline
'Backlash: \\'

Tanda tunggal diakses melalui kurung persegi:

> var str = 'abc';
> str[1]
'b'

Panjang sifat mengira bilangan aksara dalam rentetan:

> 'abc'.length
3

Seperti semua primitif, rentetan tidak berubah; anda perlu membuat rentetan baru jika anda ingin mengubah yang sedia ada.

Operator Senar

Senar disatukan melalui operator tambah (+), yang menukar operand lain kepada senar jika salah satu operand adalah senar:

> var messageCount = 3;
> 'You have ' + messageCount + ' messages'
'You have 3 messages'

Untuk mengikat rentetan dalam beberapa langkah, gunakan operator +=:

> var str = '';
> str += 'Multiple ';
> str += 'pieces ';
> str += 'are concatenated.';
> str
'Multiple pieces are concatenated.'

Kaedah String

String mempunyai banyak kaedah yang berguna (lihat String Prototype Methods). Berikut adalah beberapa contoh:

> 'abc'.slice(1)  // copy a substring
'bc'
> 'abc'.slice(1, 2)
'b'

> '\t xyz  '.trim()  // trim whitespace
'xyz'

> 'mjölnir'.toUpperCase()
'MJÖLNIR'

> 'abc'.indexOf('b')  // find a string
1
> 'abc'.indexOf('x')
-1

Pernyataan

Syarat dan gelung dalam JavaScript diperkenalkan dalam bahagian berikut.

Syarat

Perkataan if mempunyai klausa then dan klausa else pilihan yang dilaksanakan bergantung pada keadaan boolean:

if (myvar === 0) {
    // then
}

if (myvar === 0) {
    // then
} else {
    // else
}

if (myvar === 0) {
    // then
} else if (myvar === 1) {
    // else-if
} else if (myvar === 2) {
    // else-if
} else {
    // else
}

Saya mengesyorkan sentiasa menggunakan kurung (mereka menunjukkan blok sifar atau lebih pernyataan). tetapi anda tidak perlu melakukannya jika klausa hanya satu pernyataan (sama berlaku untuk control flow pernyataan untuk dan sementara):

if (x < 0) return -x;

Nilai buah menentukan kes mana yang akan dilaksanakan:

switch (fruit) {
    case 'banana':
        // ...
        break;
    case 'apple':
        // ...
        break;
    default:  // all other cases
        // ...
}

operand selepas kes boleh menjadi apa-apa ungkapan; ia dibandingkan melalui === dengan parameter suis.

Lemparan

Garis pusingan for mempunyai format berikut:

for (⟦«init»⟧; ⟦«condition»⟧; ⟦«post_iteration»⟧)
    «statement»

init dijalankan pada permulaan gelung. keadaan diperiksa sebelum setiap pengulangan gelung; jika menjadi salah, maka gelung diakhiri. post_iteration dijalankan selepas setiap pengulangan gelung.

Contoh ini mencetak semua elemen array arr pada konsol:

for (var i=0; i < arr.length; i++) {
    console.log(arr[i]);
}

Lemparan sementara terus mengelilingi tubuhnya selagi kondisinya berlaku:

// Same as for loop above:
var i = 0;
while (i < arr.length) {
    console.log(arr[i]);
    i++;
}

Lutung do-while terus berlusuk di atas tubuhnya sementara kondisinya bertahan.

do {
    // ...
} while (condition);

Dalam semua gelung:

  • putus meninggalkan gelung.
  • teruskan memulakan pengulangan gelung baru.

Fungsi

Salah satu cara untuk menentukan fungsi adalah melalui pengisytiharan fungsi:

function add(param1, param2) {
    return param1 + param2;
}

Kod sebelum ini menentukan fungsi, tambah, yang mempunyai dua parameter, param1 dan param2, dan mengembalikan jumlah kedua-dua parameter.

> add(6, 1)
7
> add('a', 'b')
'ab'

Cara lain untuk menentukan add (() adalah dengan menetapkan ungkapan fungsi kepada pembolehubah add:

var add = function (param1, param2) {
    return param1 + param2;
};

Ungkapan fungsi menghasilkan nilai dan dengan itu boleh digunakan untuk terus menyampaikan fungsi sebagai argumen kepada fungsi lain:

someOtherFunction(function (p1, p2) { ... });

Pengisytiharan Fungsi Diunggah

Perisytiharan fungsi diangkatdipindahkan secara keseluruhan ke awal skop semasa.

function foo() {
    bar();  // OK, bar is hoisted
    function bar() {
        ...
    }
}

Perhatikan bahawa walaupun pengisytiharan var juga diangkat (lihat Peralihan Diangkat), tugasan yang dilakukan oleh mereka tidak:

function foo() {
    bar();  // Not OK, bar is still undefined
    var bar = function () {
        // ...
    };
}

Argumen pembolehubah khas

Anda boleh memanggil mana-mana fungsi dalam JavaScript dengan jumlah argumen yang sewenang-wenang; bahasa tidak akan pernah mengadu.

> function f() { return arguments }
> var args = f('a', 'b', 'c');
> args.length
3
> args[0]  // read element at index 0
'a'

Terlalu Banyak atau Terlalu Sedikit Perdebatan

Mari kita gunakan fungsi berikut untuk meneroka bagaimana terlalu banyak atau terlalu sedikit parameter ditangani dalam JavaScript (fungsi toArray( ditunjukkan dalam Mengubah argumen ke Array):

function f(x, y) {
    console.log(x, y);
    return toArray(arguments);
}

Parameter tambahan akan diabaikan (kecuali oleh argumen):

> f('a', 'b', 'c')
a b
[ 'a', 'b', 'c' ]

Parameter yang hilang akan mendapatkan nilai tidak ditakrifkan:

> f('a')
a undefined
[ 'a' ]
> f()
undefined undefined
[]

Parameter pilihan

Berikut adalah corak biasa untuk menetapkan nilai lalai kepada parameter:

function pair(x, y) {
    x = x || 0;  // (1)
    y = y || 0;
    return [ x, y ];
}

Dalam baris (1), pengendali bersambung mengembalikan x jika ia adalah benar (bukan sifar, tidak ditakrifkan, dan lain-lain).

> pair()
[ 0, 0 ]
> pair(3)
[ 3, 0 ]
> pair(3, 5)
[ 3, 5 ]

Memaksa Kesetiaan

Jika anda ingin menguatkuasakan arity (sebilangan tertentu parameter), anda boleh memeriksa arguments.length:

function pair(x, y) {
    if (arguments.length !== 2) {
        throw new Error('Need exactly 2 arguments');
    }
    ...
}

Mengubah argumen ke Array

arguments bukanlah array, ia hanya seperti array (lihat Array-Like Objects and Generic Methods). Ia mempunyai panjang sifat, dan anda boleh mengakses elemen-elemennya melalui indeks dalam kurungan persegi. Anda tidak boleh, bagaimanapun, membuang elemen atau memanggil mana-mana kaedah array di atasnya. Oleh itu, kadang-kadang anda perlu menukar argumen ke array, yang merupakan fungsi berikut (dijelaskan dalam Array-Like Objects and Generic Methods):

function toArray(arrayLikeObject) {
    return Array.prototype.slice.call(arrayLikeObject);
}

Pengendalian pengecualian

Cara yang paling biasa untuk menangani pengecualian (lihat Bab 14) adalah seperti berikut:

function getPerson(id) {
    if (id < 0) {
        throw new Error('ID must not be negative: '+id);
    }
    return { id: id }; // normally: retrieved from database
}

function getPersons(ids) {
    var result = [];
    ids.forEach(function (id) {
        try {
            var person = getPerson(id);
            result.push(person);
        } catch (exception) {
            console.log(exception);
        }
    });
    return result;
}

Klausa cuba mengelilingi kod kritikal, dan klausa menangkap dilaksanakan jika pengecualian dilemparkan di dalam klausa cuba.

> getPersons([2, -5, 137])
[Error: ID must not be negative: -5]
[ { id: 2 }, { id: 137 } ]

Mod ketat

Mod ketat (lihat Mod ketat) membolehkan lebih banyak amaran dan menjadikan JavaScript bahasa yang lebih bersih (mod tidak ketat kadang-kadang dipanggil sloppy mode).

'use strict';

Anda juga boleh mengaktifkan mod ketat setiap fungsi:

function functionInStrictMode() {
    'use strict';
}

Lingkup dan Penutupan Berubah

Dalam JavaScript, anda mengisytiharkan pembolehubah melalui var sebelum menggunakannya:

> var x;
> x
undefined
> y
ReferenceError: y is not defined

Anda boleh mengisytiharkan dan memulakan beberapa pembolehubah dengan satu pernyataan var:

var x = 1, y = 2, z = 3;

Tetapi saya mengesyorkan menggunakan satu pernyataan bagi setiap pembolehubah (alasan dijelaskan dalam sintaks).

var x = 1;
var y = 2;
var z = 3;

Oleh kerana pengangkatan (lihat Variables Are Hoisted), biasanya lebih baik untuk mengisytiharkan pembolehubah pada permulaan fungsi.

Variabel Berfungsi

Lingkup pembolehubah sentiasa fungsi lengkap (berbeza dengan blok semasa).

function foo() {
    var x = -512;
    if (x < 0) {  // (1)
        var tmp = -x;
        ...
    }
    console.log(tmp);  // 512
}

Kita dapat melihat bahawa pembolehubah tmp tidak terhad kepada blok yang bermula dalam baris (1); ia wujud sehingga akhir fungsi.

Variabel Diangkat

Setiap pengisytiharan pembolehubah diangkat: pengisytiharan dipindahkan ke awal fungsi, tetapi tugasan yang dibuatnya tetap diletakkan.

function foo() {
    console.log(tmp); // undefined
    if (false) {
        var tmp = 3;  // (1)
    }
}

Secara dalaman, fungsi sebelumnya dilaksanakan seperti ini:

function foo() {
    var tmp;  // hoisted declaration
    console.log(tmp);
    if (false) {
        tmp = 3;  // assignment stays put
    }
}

Penutupan

Setiap fungsi kekal berkaitan dengan pembolehubah fungsi yang mengelilinginya, walaupun selepas ia meninggalkan skop di mana ia dicipta.

function createIncrementor(start) {
    return function () {  // (1)
        start++;
        return start;
    }
}

Fungsi yang bermula di baris (1) meninggalkan konteks di mana ia dicipta, tetapi kekal disambungkan ke versi hidup permulaan:

> var inc = createIncrementor(5);
> inc()
6
> inc()
7
> inc()
8

Penutupan adalah fungsi ditambah sambungan kepada pembolehubah skop sekitarnya.

Model IIFE: Memperkenalkan skop baru

Kadang-kadang anda ingin memperkenalkan skop pembolehubah barumisalnya, untuk mengelakkan pembolehubah menjadi global. Dalam JavaScript, anda tidak bolehmenggunakan blok untuk melakukannya; anda mesti menggunakan fungsi. Tetapi terdapat corak untuk menggunakan fungsi dengan cara seperti blok. Ia dipanggil IIFE (ekspresi fungsi yang dipanggil dengan segera, diucapkan iffy):

(function () {  // open IIFE
    var tmp = ...;  // not a global variable
}());  // close IIFE

Pastikan anda menaip contoh sebelumnya seperti yang ditunjukkan (selain komen). IIFE adalah ungkapan fungsi yang dipanggil segera selepas anda tentukan. Di dalam fungsi, skop baru wujud, menghalang tmp daripada menjadi global. Sila rujuk Memperkenalkan skop baru melalui IIFE untuk butiran mengenai IIFEs.

Kes penggunaan IIFE: perkongsian tidak sengaja melalui penutupan

Penutupan menyimpan sambungan mereka kepada pembolehubah luar, yang kadang-kadang tidak apa yang anda mahu:

var result = [];
for (var i=0; i < 5; i++) {
    result.push(function () { return i });  // (1)
}
console.log(result[1]()); // 5 (not 1)
console.log(result[3]()); // 5 (not 3)

Nilai yang dikembalikan dalam baris (1) adalah sentiasa nilai semasa i, bukan nilai yang ada ketika fungsi dicipta. Selepas gelung selesai, i mempunyai nilai 5, itulah sebabnya semua fungsi dalam array mengembalikan nilai itu. Jika anda mahu fungsi dalam baris (1) untuk menerima snapshot nilai semasa i, anda boleh menggunakan IIFE:

for (var i=0; i < 5; i++) {
    (function () {
        var i2 = i; // copy current i
        result.push(function () { return i2 });
    }());
}

Objek dan Pembina

Bahagian ini merangkumi dua mekanisme berorientasikan objek asas JavaScript: objek tunggal dan pembina (yang merupakan kilang untuk objek, serupa dengan kelas dalam bahasa lain).

Objektif Tunggal

Seperti semua nilai, objek mempunyai sifat. anda boleh, sebenarnya, menganggap objek sebagai satu set sifat, di mana setiap sifat adalah pasangan (kunci, nilai). kunci adalah rentetan, dan nilai adalah mana-mana nilai JavaScript.

Dalam JavaScript, anda boleh membuat objek biasa secara langsung, melalui literal objek:

'use strict';
var jane = {
    name: 'Jane',

    describe: function () {
        return 'Person named '+this.name;
    }
};

Objek sebelumnya mempunyai sifat nama dan menerangkan. Anda boleh membaca (get) dan menulis (set) sifat:

> jane.name  // get
'Jane'
> jane.name = 'John';  // set
> jane.newProperty = 'abc';  // property created automatically

Ciri-ciri bernilai fungsi seperti describe dipanggil kaedah. Mereka menggunakan ini untuk merujuk kepada objek yang digunakan untuk memanggilnya:

> jane.describe()  // call method
'Person named John'
> jane.name = 'Jane';
> jane.describe()
'Person named Jane'

Operator dalam memeriksa sama ada harta wujud:

> 'newProperty' in jane
true
> 'foo' in jane
false

Jika anda membaca sifat yang tidak wujud, anda mendapat nilai undefined. Oleh itu dua pemeriksaan sebelumnya juga boleh dilakukan seperti ini:

> jane.newProperty !== undefined
true
> jane.foo !== undefined
false

Operator delete memadamkan sifat:

> delete jane.newProperty
true
> 'newProperty' in jane
false

Kunci Harta Sewenang-Wenang

Kunci sifat boleh menjadi mana-mana rentetan. Setakat ini, kita telah melihat kunci sifat dalam literal objek dan selepas pengendali titik. Walau bagaimanapun, anda hanya boleh menggunakannya dengan cara itu jika mereka adalah pengenal (lihat pengenal dan nama pembolehubah). Jika anda ingin menggunakan rentetan lain sebagai kunci, anda perlu mengutip mereka dalam literal objek dan menggunakan kurungan persegi untuk mendapatkan dan menetapkan sifat:

> var obj = { 'not an identifier': 123 };
> obj['not an identifier']
123
> obj['not an identifier'] = 456;

Perangkai persegi juga membolehkan anda mengira kunci harta:

> var obj = { hello: 'world' };
> var x = 'hello';

> obj[x]
'world'
> obj['hel'+'lo']
'world'

Kaedah Pengekstrakan

Jika anda mengekstrak kaedah, ia kehilangan hubungannya dengan objek. dengan sendirinya, fungsi itu bukan lagi kaedah, dan ini mempunyai nilai tidak ditakrifkan (dalam mod ketat).

Sebagai contoh, mari kita kembali ke objek Jane sebelumnya:

'use strict';
var jane = {
    name: 'Jane',

    describe: function () {
        return 'Person named '+this.name;
    }
};

Kami ingin mengekstrak kaedah describe dari jane, meletakkannya ke dalam pembolehubah fungsi, dan memanggilnya.

> var func = jane.describe;
> func()
TypeError: Cannot read property 'name' of undefined

Penyelesaian adalah menggunakan kaedah bind() yang dimiliki semua fungsi. Ia mewujudkan fungsi baru yang selalu mempunyai nilai yang diberikan:

> var func2 = jane.describe.bind(jane);
> func2()
'Person named Jane'

Fungsi Dalam Satu Kaedah

Setiap fungsi mempunyai pembolehubah khas sendiri ini. Ini tidak selesa jika anda menyarang fungsi di dalam kaedah, kerana anda tidak boleh mengakses kaedah ini dari fungsi. Berikut adalah contoh di mana kita memanggil forEach dengan fungsi untuk berulang di atas array:

var jane = {
    name: 'Jane',
    friends: [ 'Tarzan', 'Cheeta' ],
    logHiToFriends: function () {
        'use strict';
        this.friends.forEach(function (friend) {
            // `this` is undefined here
            console.log(this.name+' says hi to '+friend);
        });
    }
}

Panggilan logHiToFriends menghasilkan ralat:

> jane.logHiToFriends()
TypeError: Cannot read property 'name' of undefined

Mari kita lihat dua cara untuk memperbaiki ini. pertama, kita boleh menyimpan ini dalam pembolehubah yang berbeza:

logHiToFriends: function () {
    'use strict';
    var that = this;
    this.friends.forEach(function (friend) {
        console.log(that.name+' says hi to '+friend);
    });
}

Atau, forEach mempunyai parameter kedua yang membolehkan anda memberikan nilai untuk ini:

logHiToFriends: function () {
    'use strict';
    this.friends.forEach(function (friend) {
        console.log(this.name+' says hi to '+friend);
    }, this);
}

Ungkapan fungsi sering digunakan sebagai argumen dalam panggilan fungsi dalam JavaScript. Sentiasa berhati-hati apabila anda merujuk ini dari salah satu ungkapan fungsi tersebut.

Pembina: Kilang untuk Objek

Hingga kini, anda mungkin berfikir bahawa objek JavaScript hanya peta dari rentetan kepada nilai, sebuah konsep yang dicadangkan oleh literal objek JavaScript, yang kelihatan seperti peta / literal kamus bahasa lain. Walau bagaimanapun, objek JavaScript juga menyokong ciri yang benar-benar berorientasikan objek: warisan. Bahagian ini tidak sepenuhnya menerangkan bagaimana warisan JavaScript berfungsi, tetapi menunjukkan corak mudah untuk memulakan. Lihat Bab 17 jika anda ingin mengetahui lebih lanjut.

Sebagai tambahan kepada fungsi dan kaedah real, fungsi memainkan peranan lain dalam JavaScript: mereka menjadi pembinakilang untuk objekjika dipanggil melalui operator baru.

// Set up instance data
function Point(x, y) {
    this.x = x;
    this.y = y;
}
// Methods
Point.prototype.dist = function () {
    return Math.sqrt(this.x*this.x + this.y*this.y);
};

Kita dapat melihat bahawa pembina mempunyai dua bahagian. Pertama, fungsi Point menetapkan data contoh. Kedua, sifat Point.prototype mengandungi objek dengan kaedah. Data yang pertama adalah khusus untuk setiap contoh, sementara data terakhir dikongsi di antara semua contoh.

Untuk menggunakan Point, kita memanggilnya melalui operator baru:

> var p = new Point(3, 5);
> p.x
3
> p.dist()
5.830951894845301

p adalah satu contoh Point:

> p instanceof Point
true

Array

Array adalah urutan elemen yang boleh diakses melalui indeks bilangan bulat bermula dari sifar.

Array Literal

Array literals berguna untuk mencipta array:

> var arr = [ 'a', 'b', 'c' ];

Array sebelumnya mempunyai tiga elemen: rentetan a, b, dan c. Anda boleh mengaksesnya melalui indeks bilangan bulat:

> arr[0]
'a'
> arr[0] = 'x';
> arr
[ 'x', 'b', 'c' ]

Sifat panjang menunjukkan berapa banyak elemen array mempunyai. Anda boleh menggunakannya untuk menambah unsur dan untuk membuang unsur:

> var arr = ['a', 'b'];
> arr.length
2

> arr[arr.length] = 'c';
> arr
[ 'a', 'b', 'c' ]
> arr.length
3

> arr.length = 1;
> arr
[ 'a' ]

Operator dalam berfungsi untuk array, juga:

> var arr = [ 'a', 'b', 'c' ];
> 1 in arr // is there an element at index 1?
true
> 5 in arr // is there an element at index 5?
false

Perhatikan bahawa array adalah objek dan dengan itu boleh mempunyai sifat objek:

> var arr = [];
> arr.foo = 123;
> arr.foo
123

Kaedah Array

Array mempunyai banyak kaedah (lihat Array Prototype Methods). Berikut beberapa contoh:

> var arr = [ 'a', 'b', 'c' ];

> arr.slice(1, 2)  // copy elements
[ 'b' ]
> arr.slice(1)
[ 'b', 'c' ]

> arr.push('x')  // append an element
4
> arr
[ 'a', 'b', 'c', 'x' ]

> arr.pop()  // remove last element
'x'
> arr
[ 'a', 'b', 'c' ]

> arr.shift()  // remove first element
'a'
> arr
[ 'b', 'c' ]

> arr.unshift('x')  // prepend an element
3
> arr
[ 'x', 'b', 'c' ]

> arr.indexOf('b')  // find the index of an element
1
> arr.indexOf('y')
-1

> arr.join('-')  // all elements in a single string
'x-b-c'
> arr.join('')
'xbc'
> arr.join()
'x,b,c'

Iterasi di atas Arrays

Terdapat beberapa kaedah array untuk mengulangi elemen (lihat Iterasi (Tidak merosakkan)). Dua yang paling penting adalah forEach dan peta.

forEach mengulangi array dan menyerahkan elemen semasa dan indeksnya kepada fungsi:

[ 'a', 'b', 'c' ].forEach(
    function (elem, index) {  // (1)
        console.log(index + '. ' + elem);
    });

Kod sebelumnya menghasilkan output berikut:

0. a
1. b
2. c

Perhatikan bahawa fungsi dalam baris (1) bebas mengabaikan argumen. Ia boleh, sebagai contoh, hanya mempunyai parameter elem.

peta mencipta array baru dengan menggunakan fungsi untuk setiap elemen array yang sedia ada:

> [1,2,3].map(function (x) { return x*x })
[ 1, 4, 9 ]

Ungkapan Biasa

JavaScript mempunyai sokongan terbina dalam untuk ungkapan biasa.

/^abc$/
/[A-Za-z0-9]+/

Ujian kaedah: Adakah terdapat perlawanan?

> /^a+b+$/.test('aaab')
true
> /^a+b+$/.test('aaa')
false

Kaedah exec ((): Pasangan dan Kumpulan Tangkapan

> /a(b+)a/.exec('_abbba_aba_')
[ 'abbba', 'bbb' ]

Array yang dikembalikan mengandungi pencocokan lengkap pada indeks 0, tangkapan kumpulan pertama pada indeks 1, dan sebagainya. Terdapat cara (dibahas dalam RegExp.prototype.exec: Capture Groups) untuk memanggil kaedah ini berulang kali untuk mendapatkan semua perlawanan.

Kaedah menggantikan ((): Cari dan Ganti

> '<a> <bbb>'.replace(/<(.*?)>/g, '[$1]')
'[a] [bbb]'

Parameter pertama penggantian mestilah ungkapan biasa dengan bendera /g; jika tidak, hanya kejadian pertama yang diganti.

Matematika

Matematik adalah objek dengan fungsi aritmatika. Berikut adalah beberapa contoh:

> Math.abs(-2)
2

> Math.pow(3, 2)  // 3 to the power of 2
9

> Math.max(2, -1, 5)
5

> Math.round(1.9)
2

> Math.PI  // pre-defined constant for π
3.141592653589793

> Math.cos(Math.PI)  // compute the cosine for 180°
-1

Lebih lanjut