diff options
| author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:42:17 -0500 |
|---|---|---|
| committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:42:17 -0500 |
| commit | da78a9e329e272dedb2400b79a3bdeebff387d47 (patch) | |
| tree | e6ef8aa7c43556f55ddfe031a01cf0a8fa271bfe /files/id/web/javascript/a_re-introduction_to_javascript | |
| parent | 1109132f09d75da9a28b649c7677bb6ce07c40c0 (diff) | |
| download | translated-content-da78a9e329e272dedb2400b79a3bdeebff387d47.tar.gz translated-content-da78a9e329e272dedb2400b79a3bdeebff387d47.tar.bz2 translated-content-da78a9e329e272dedb2400b79a3bdeebff387d47.zip | |
initial commit
Diffstat (limited to 'files/id/web/javascript/a_re-introduction_to_javascript')
| -rw-r--r-- | files/id/web/javascript/a_re-introduction_to_javascript/index.html | 862 |
1 files changed, 862 insertions, 0 deletions
diff --git a/files/id/web/javascript/a_re-introduction_to_javascript/index.html b/files/id/web/javascript/a_re-introduction_to_javascript/index.html new file mode 100644 index 0000000000..5b7ef3b14e --- /dev/null +++ b/files/id/web/javascript/a_re-introduction_to_javascript/index.html @@ -0,0 +1,862 @@ +--- +title: Sebuah pengenalan ulang pada bahasa JavaScript (tutorial JS) +slug: Web/JavaScript/A_re-introduction_to_JavaScript +translation_of: Web/JavaScript/A_re-introduction_to_JavaScript +--- +<div>{{jsSidebar}}</div> + +<h2 id="Pengantar">Pengantar</h2> + +<p>Mengapa melakukan pengenalan ulang? Karena bahasa {{Glossary("JavaScript")}} terkenal dengan cap buruk sebagai <a href="http://javascript.crockford.com/javascript.html">bahasa pemprograman yang paling sering membuat kesalahpahaman di dunia</a>. Sering kali JavaScript diejek sebagai sebuah mainan (layaknya mobil-mobilan) karena terlihat sederhana, tetapi dibalik kesederhanaannya tersebut, terdapat beberapa fitur yang sangat andal. Saat ini JavaScript digunakan oleh aplikasi-aplikasi terkenal dalam jumlah<em> </em>yang luar biasa banyaknya, memiliki pengetahuan yang mendalam tentang teknologi ini adalah salah satu skill penting bagi para pengembang <em>web </em>atau <em>mobile</em>.</p> + +<p>Ada baiknya kita memulai pengenalan ini dengan mengetahui sekilas gambaran sejarah dari bahasa pemograman ini. JavaScript dibuat pada tahun 1995 oleh Brendan Eich ketika dia menjadi seorang insinyur perangkat lunak di Netscape. JavaScript dirilis bersamaan dengan Netscape 2 di permulaan tahun 1996. Awalnya JavaScript dinamakan LiveScript, tetapi diganti menjadi JavaScript karena memanfaatkan ketenaran bahasa pemograman Java dari Sun Microsystem, walaupun keduanya memiliki sedikit sekali kesamaan. Hal inilah yang menjadi sumber kebingungan sejak saat itu.</p> + +<p>Beberapa bulan kemudian, Microsoft merilis JScript yang tertanam di dalam Internet Explore 3. Sebagian besar JScript kompatible dan mirip dengan JavaScript. Beberapa bulan setelahnya Netscape mengajukan JavaScript ke <a href="http://www.ecma-international.org/">Ecma International, </a>Organisasi Eropa yang melakukan standarisasi sistem informasi dan komunikasi, yang kemudian menghasilkan edisi pertama dari standar {{Glossary("ECMAScript")}} pada tahun itu. Standar ini memperoleh pembaharuan yang signifikan pada <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript edisi ke-3 </a>pada tahun 1999, dan sejak saat itu standar tersebut tidak terlalu banyak mengalami perubahan. Edisi ke-4 ECMAScript diabaikan dengan alasan perbedaan pandangan terhadap kompleksitas bahasa. Beberapa bagian dari edisi ECMAScript ke-4 membentuk dasar ECMAScript edisi ke-5, yang dipublikasi pada tahun 2009 and edisi ECMAScript ke-6 dirilis pada bulan Juni tahun 2015.</p> + +<div class="note"> +<p>Karena lebih familiar, mulai dari sini kita akan mengacu ECMAScript sebagai "JavaScript".</p> +</div> + +<p>Tidak seperti kebanyakan bahasa pemograman, JavaScript tidak mempunyai konsep input atau output (I/O). Didesain untuk dapat dieksekusi sebagai bahasa <em>scripting </em>pada lingkungan pengguna dan mekanisme komunikasi dengan dunia luar diserahkan kepada lingkungan pengguna. Browser adalah lingkungan pengguna yang sangat umum, tetapi Interpreter JavaScript dapat juga ditemukan ditempat lain, termasuk Adobe Acrobat, Adobe Photshop, SVG images, Yahoo Widget engine, lingkungan server seperti <a href="http://nodejs.org/">Node.js</a>, database NoSQL seperti <a href="http://couchdb.apache.org/">Apache CouchDB</a>, komputer tertanam, lingkungan desktop seperti GNOME (salah satu antarmuka yang paling terkenal pada sustem operasi GNU/Linux), dan masih banyak lagi yang lainnya.<br> + </p> + +<h2 id="Ikhtisar"><span class="short_text" id="result_box" lang="id"><span>Ikhtisar</span></span></h2> + +<p>JavaScript adalah bahasa pemograman dinamis berorientasi objek dengan types dan operator, objek bawaan standar (objek literal), dan methods. Syntax JavaScript dipengaruhi oleh bahasa Java dan C - sangat banyak struktur dalam bahasa tersebut yang digunakan dalam JavaScript. Perbedaan yang paling mendasar adalah JavaScript tidak mempunyai kelas, melainkan fungsionalitas kelas yang dicapai dengan obyek prototipe (Lebih lanjut tentang ES6 {{jsxref("Classes")}}). Perbedaan utama lainnya adalah fungsi sebagai objek, yaitu fungsi mempunyai kapasitas untuk menahan kode yang dapat dieksekusi dan dilewatkan seperti objek yang lain.</p> + +<p>Mari mulai dengan melihat blok pembangun dari bahasa pemograman: types (tipe-tipe data). Program pada JavaScript memanipulasi nilai dan nilai tersebut termasuk ke dalam sebuah tipe. Beberapa tipe dalam JavaScript adalah:<br> + </p> + +<ul> + <li>{{jsxref("Number")}}</li> + <li>{{jsxref("String")}}</li> + <li>{{jsxref("Boolean")}}</li> + <li>{{jsxref("Function")}}</li> + <li>{{jsxref("objek")}}</li> + <li>{{jsxref("Symbol")}} (Baru ditambahkan pada ES6)</li> +</ul> + +<p>...ooo, ada lagi {{jsxref("undefined")}} and {{jsxref("null")}} keduanya mempunyai karakteristik yang sedikit ganjil, {{jsxref("Array")}} merupakan objek spesial, {{jsxref("Date")}} dan {{jsxref("RegExp")}} merupakan objek yang dapat digunakan langsung dan untuk lebih tepatnya, fungsi termasuk dalam objek spesial. Jadi, diagramnya kira-kira seperti ini:</p> + +<ul> + <li>{{jsxref("Number")}}</li> + <li>{{jsxref("String")}}</li> + <li>{{jsxref("Boolean")}}</li> + <li>{{jsxref("Symbol")}} (new in Edition 6)</li> + <li>{{jsxref("objek")}} + <ul> + <li>{{jsxref("Function")}}</li> + <li>{{jsxref("Array")}}</li> + <li>{{jsxref("Date")}}</li> + <li>{{jsxref("RegExp")}}</li> + </ul> + </li> + <li>{{jsxref("null")}}</li> + <li>{{jsxref("undefined")}}</li> +</ul> + +<p>Ada beberapa tipe {{jsxref("Error")}} bawaan juga, akan lebih memudahkan jika kita mempelajari terlebih dahulu diagram pertama, bagaimanapun juga kita akan membahas tipe - tipe yang telah dituliskan diatas.</p> + +<h2 id="Numbers">Numbers</h2> + +<p>Menurut spesifikasi, tipe nomer pada JavaScript menggunakan "format IEEE 754 64-bit double-presisi". Hal ini menyebabkan beberapa konsekuensi, diantaranya tidak adanya tipe integer pada JavaScript. Jadi programmer harus agak teliti dengan operasi aritmatika jika sebelumnya berangkat dari C atau Java.<br> + <br> + Perlu juga memperhatikan kasus seperti berikut:</p> + +<pre class="brush: js notranslate">0.1 + 0.2 == 0.30000000000000004 +</pre> + +<p>Dalam praktiknya, nilai integer diperlakukan sebagai int 32-bit, dan beberapa implementasi bahkan menyimpannya demikian (dalam int 32-bit) kecuali diinstruksikan agar nilai tersebut valid sebagai tipe Number namun tidak dalam integer 32-bit. Hal ini mungkin saja penting untuk operasi yang mementingkan ukuran bit.</p> + +<p>Standar<a href="/en-US/docs/Web/JavaScript/Reference/Operators#Arithmetic_operators"> operasi aritmatika</a> tersedia, seperti penjumlahan, pengurangan, modulus, dan lain-lain. Ada juga Object bawaan yang kami lupa menyebutkannya di awal disebut {{jsxref("Math")}} yang menyediakan fungsi matematika dan konstan:</p> + +<pre class="brush: js notranslate">Math.sin(3.5); +var circumference = Math.PI * (r + r); +</pre> + +<p>Anda dapat mengonversi sebuah string ke integer dengan menggunakan fungsi bawaan {{jsxref("Global_objeks/parseInt", "parseInt()")}}. Basis konversi dapat ditambahkan sebagai argumen kedua (tidak wajib), namun sebaiknya ditambahkan:</p> + +<pre class="brush: js notranslate">parseInt("123", 10); // 123 +parseInt("010", 10); // 10 +</pre> + +<p>Pada peramban kuno, string yang diawali dengan "0" diasumsikan sebagai octal (radix 8), namun hal ini tidak lagi menjadi masalah sejak 2013 dan seterusnya. Kecuali Anda sudah yakin mengenai format string-nya, Anda akan mendapatkan hasil mengejutkan pada peramban kuno tersebut:</p> + +<pre class="brush: js notranslate">parseInt("010"); // 8 +parseInt("0x10"); // 16 +</pre> + +<p>Di sini, kita melihat fungsi {{jsxref("Global_objeks/parseInt", "parseInt()")}} memperlakukan string pertama sebagai oktal karena diawali dengan "0", dan string kedua sebagai hexadecimal karena diawali dengan "0x". <em>Notasi heksadesimal masih ada</em>; hanya oktal yang telah dihapus.</p> + +<p>If you want to convert a binary number to an integer, just change the base:</p> + +<pre class="brush: js notranslate">parseInt("11", 2); // 3 +</pre> + +<p>Similarly, you can parse floating point numbers using the built-in {{jsxref("Global_objeks/parseFloat", "parseFloat()")}} function. Unlike its {{jsxref("Global_objeks/parseInt", "parseInt()")}} cousin, <code>parseFloat()</code> always uses base 10.</p> + +<p>You can also use the unary <code>+</code> operator to convert values to numbers:</p> + +<pre class="brush: js notranslate">+ "42"; // 42 ++ "010"; // 10 ++ "0x10"; // 16 +</pre> + +<p>A special value called {{jsxref("NaN")}} (short for "Not a Number") is returned if the string is non-numeric:</p> + +<pre class="brush: js notranslate">parseInt("hello", 10); // NaN +</pre> + +<p><code>NaN</code> is toxic: if you provide it as an input to any mathematical operation the result will also be <code>NaN</code>:</p> + +<pre class="brush: js notranslate">NaN + 5; // NaN +</pre> + +<p>You can test for <code>NaN</code> using the built-in {{jsxref("Global_objeks/isNaN", "isNaN()")}} function:</p> + +<pre class="brush: js notranslate">isNaN(NaN); // true +</pre> + +<p>JavaScript also has the special values {{jsxref("Infinity")}} and <code>-Infinity</code>:</p> + +<pre class="brush: js notranslate"> 1 / 0; // Infinity +-1 / 0; // -Infinity +</pre> + +<p>You can test for <code>Infinity</code>, <code>-Infinity</code> and <code>NaN</code> values using the built-in {{jsxref("Global_objeks/isFinite", "isFinite()")}} function:</p> + +<pre class="brush: js notranslate">isFinite(1/0); // false +isFinite(-Infinity); // false +isFinite(NaN); // false +</pre> + +<div class="note">The {{jsxref("Global_objeks/parseInt", "parseInt()")}} and {{jsxref("Global_objeks/parseFloat", "parseFloat()")}} functions parse a string until they reach a character that isn't valid for the specified number format, then return the number parsed up to that point. However the "+" operator simply converts the string to <code>NaN</code> if there is an invalid character contained within it. Just try parsing the string "10.2abc" with each method by yourself in the console and you'll understand the differences better.</div> + +<h2 id="Strings">Strings</h2> + +<p>Strings in JavaScript are sequences of <a href="/en-US/docs/Web/JavaScript/Guide/Values,_variables,_and_literals#Unicode">Unicode characters</a>. This should be welcome news to anyone who has had to deal with internationalization. More accurately, they are sequences of UTF-16 code units; each code unit is represented by a 16-bit number. Each Unicode character is represented by either 1 or 2 code units.</p> + +<p>If you want to represent a single character, you just use a string consisting of that single character.</p> + +<p>To find the length of a string (in code units), access its <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length">length</a></code> property:</p> + +<pre class="brush: js notranslate">"hello".length; // 5 +</pre> + +<p>There's our first brush with JavaScript objeks! Did we mention that you can use strings like {{jsxref("objek", "objeks", "", 1)}} too? They have {{jsxref("String", "methods", "#Methods", 1)}} as well that allow you to manipulate the string and access information about the string:</p> + +<pre class="brush: js notranslate">"hello".charAt(0); // "h" +"hello, world".replace("hello", "goodbye"); // "goodbye, world" +"hello".toUpperCase(); // "HELLO" +</pre> + +<h2 id="Other_types">Other types</h2> + +<p>JavaScript distinguishes between {{jsxref("null")}}, which is a value that indicates a deliberate non-value (and is only accessible through the <code>null</code> keyword), and {{jsxref("undefined")}}, which is a value of type <code>undefined</code> that indicates an uninitialized value — that is, a value hasn't even been assigned yet. We'll talk about variables later, but in JavaScript it is possible to declare a variable without assigning a value to it. If you do this, the variable's type is <code>undefined</code>. <code>undefined</code> is actually a constant.</p> + +<p>JavaScript has a boolean type, with possible values <code>true</code> and <code>false</code> (both of which are keywords.) Any value can be converted to a boolean according to the following rules:</p> + +<ol> + <li><code>false</code>, <code>0</code>, empty strings (<code>""</code>), <code>NaN</code>, <code>null</code>, and <code>undefined</code> all become <code>false.</code></li> + <li>All other values become <code>true.</code></li> +</ol> + +<p>You can perform this conversion explicitly using the <code>Boolean()</code> function:</p> + +<pre class="brush: js notranslate">Boolean(""); // false +Boolean(234); // true +</pre> + +<p>However, this is rarely necessary, as JavaScript will silently perform this conversion when it expects a boolean, such as in an <code>if</code> statement (see below.) For this reason, we sometimes speak simply of "true values" and "false values," meaning values that become <code>true</code> and <code>false</code>, respectively, when converted to booleans. Alternatively, such values can be called "truthy" and "falsy", respectively.</p> + +<p>Boolean operations such as <code>&&</code> (logical <em>and</em>), <code>||</code> (logical <em>or</em>), and <code>!</code> (logical <em>not</em>) are supported; see below.</p> + +<h2 id="Variables">Variables</h2> + +<p>New variables in JavaScript are declared using the <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/var" title="/en/JavaScript/Reference/Statements/var">var</a></code> keyword:</p> + +<pre class="brush: js notranslate">var a; +var name = "simon"; +</pre> + +<p>If you declare a variable without assigning any value to it, its type is <code>undefined</code>.</p> + +<p>An important difference between JavaScript and other languages like Java is that in JavaScript, blocks do not have scope; only functions have scope. So if a variable is defined using <code>var</code> in a compound statement (for example inside an <code>if</code> control structure), it will be visible to the entire function. However, starting with ECMAScript Edition 6, <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/let">let</a></code> and <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/const">const</a></code> declarations allow you to create block-scoped variables.</p> + +<h2 id="Operators">Operators</h2> + +<p>JavaScript's numeric operators are <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code> and <code>%</code> — which is the remainder operator (<a href="/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Remainder_%28%29">which is not the same as modulo</a>.) Values are assigned using <code>=</code>, and there are also compound assignment statements such as <code>+=</code> and <code>-=</code>. These extend out to <code>x = x <em>operator</em> y</code>.</p> + +<pre class="brush: js notranslate">x += 5 +x = x + 5 +</pre> + +<p>You can use <code>++</code> and <code>--</code> to increment and decrement respectively. These can be used as prefix or postfix operators.</p> + +<p>The <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Addition" title="/en/JavaScript/Reference/Operators/String_Operators"><code>+</code> operator</a> also does string concatenation:</p> + +<pre class="brush: js notranslate">"hello" + " world"; // "hello world" +</pre> + +<p>If you add a string to a number (or other value) everything is converted in to a string first. This might catch you up:</p> + +<pre class="brush: js notranslate">"3" + 4 + 5; // "345" + 3 + 4 + "5"; // "75" +</pre> + +<p>Adding an empty string to something is a useful way of converting it to a string itself.</p> + +<p><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators" title="/en/JavaScript/Reference/Operators/Comparison_Operators">Comparisons</a> in JavaScript can be made using <code><</code>, <code>></code>, <code><=</code> and <code>>=</code>. These work for both strings and numbers. Equality is a little less straightforward. The double-equals operator performs type coercion if you give it different types, with sometimes interesting results:</p> + +<pre class="brush: js notranslate">123 == "123"; // true +1 == true; // true +</pre> + +<p>To avoid type coercion and make sure your comparisons are always accurate, you should always use the triple-equals operator:</p> + +<pre class="brush: js notranslate">123 === "123"; // false +1 === true; // false +</pre> + +<p>There are also <code>!=</code> and <code>!==</code> operators.</p> + +<p>JavaScript also has <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators" title="/en/JavaScript/Reference/Operators/Bitwise_Operators">bitwise operations</a>. If you want to use them, they're there.</p> + +<h2 id="Control_structures">Control structures</h2> + +<p>JavaScript has a similar set of control structures to other languages in the C family. Conditional statements are supported by <code>if</code> and <code>else</code>; you can chain them together if you like:</p> + +<pre class="brush: js notranslate">var name = "kittens"; +if (name == "puppies") { + name += "!"; +} else if (name == "kittens") { + name += "!!"; +} else { + name = "!" + name; +} +name == "kittens!!" +</pre> + +<p>JavaScript has <code>while</code> loops and <code>do-while</code> loops. The first is good for basic looping; the second for loops where you wish to ensure that the body of the loop is executed at least once:</p> + +<pre class="brush: js notranslate">while (true) { + // an infinite loop! +} + +var input; +do { + input = get_input(); +} while (inputIsNotValid(input)) +</pre> + +<p>JavaScript's <code>for</code> loop is the same as that in C and Java: it lets you provide the control information for your loop on a single line.</p> + +<pre class="brush: js notranslate">for (var i = 0; i < 5; i++) { + // Will execute 5 times +} +</pre> + +<p>The <code>&&</code> and <code>||</code> operators use short-circuit logic, which means whether they will execute their second operand is dependent on the first. This is useful for checking for null objeks before accessing their attributes:</p> + +<pre class="brush: js notranslate">var name = o && o.getName(); +</pre> + +<p>Or for setting default values:</p> + +<pre class="brush: js notranslate">var name = otherName || "default"; +</pre> + +<p>JavaScript has a ternary operator for conditional expressions:</p> + +<pre class="brush: js notranslate">var allowed = (age > 18) ? "yes" : "no"; +</pre> + +<p>The <code>switch</code> statement can be used for multiple branches based on a number or string:</p> + +<pre class="brush: js notranslate">switch(action) { + case 'draw': + drawIt(); + break; + case 'eat': + eatIt(); + break; + default: + doNothing(); +} +</pre> + +<p>If you don't add a <code>break</code> statement, execution will "fall through" to the next level. This is very rarely what you want — in fact it's worth specifically labeling deliberate fallthrough with a comment if you really meant it to aid debugging:</p> + +<pre class="brush: js notranslate">switch(a) { + case 1: // fallthrough + case 2: + eatIt(); + break; + default: + doNothing(); +} +</pre> + +<p>The default clause is optional. You can have expressions in both the switch part and the cases if you like; comparisons take place between the two using the <code>===</code> operator:</p> + +<pre class="brush: js notranslate">switch(1 + 3) { + case 2 + 2: + yay(); + break; + default: + neverhappens(); +} +</pre> + +<h2 id="objeks">objeks</h2> + +<p>JavaScript objeks can be thought of as simple collections of name-value pairs. As such, they are similar to:</p> + +<ul> + <li>Dictionaries in Python.</li> + <li>Hashes in Perl and Ruby.</li> + <li>Hash tables in C and C++.</li> + <li>HashMaps in Java.</li> + <li>Associative arrays in PHP.</li> +</ul> + +<p>The fact that this data structure is so widely used is a testament to its versatility. Since everything (bar core types) in JavaScript is an objek, any JavaScript program naturally involves a great deal of hash table lookups. It's a good thing they're so fast!</p> + +<p>The "name" part is a JavaScript string, while the value can be any JavaScript value — including more objeks. This allows you to build data structures of arbitrary complexity.</p> + +<p>There are two basic ways to create an empty objek:</p> + +<pre class="brush: js notranslate">var obj = new objek(); +</pre> + +<p>And:</p> + +<pre class="brush: js notranslate">var obj = {}; +</pre> + +<p>These are semantically equivalent; the second is called objek literal syntax, and is more convenient. This syntax is also the core of JSON format and should be preferred at all times.</p> + +<p>objek literal syntax can be used to initialize an objek in its entirety:</p> + +<pre class="brush: js notranslate">var obj = { + name: "Carrot", + "for": "Max", + details: { + color: "orange", + size: 12 + } +} +</pre> + +<p>Attribute access can be chained together:</p> + +<pre class="brush: js notranslate">obj.details.color; // orange +obj["details"]["size"]; // 12 +</pre> + +<p>The following example creates an objek prototype, Person, and instance of that prototype, You.</p> + +<pre class="brush: js notranslate">function Person(name, age) { + this.name = name; + this.age = age; +} + +// Define an objek +var You = new Person("You", 24); +// We are creating a new person named "You" +// (that was the first parameter, and the age..) +</pre> + +<p>Once created, an objek's properties can again be accessed in one of two ways:</p> + +<pre class="brush: js notranslate">obj.name = "Simon"; +var name = obj.name; +</pre> + +<p>And...</p> + +<pre class="brush: js notranslate">obj["name"] = "Simon"; +var name = obj["name"]; +</pre> + +<p>These are also semantically equivalent. The second method has the advantage that the name of the property is provided as a string, which means it can be calculated at run-time. However, using this method prevents some JavaScript engine and minifier optimizations being applied. It can also be used to set and get properties with names that are <a href="/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords" title="/en/JavaScript/Reference/Reserved_Words">reserved words</a>:</p> + +<pre class="brush: js notranslate">obj.for = "Simon"; // Syntax error, because 'for' is a reserved word +obj["for"] = "Simon"; // works fine +</pre> + +<div class="note"> +<p>Starting in ECMAScript 5, reserved words may be used as objek property names "in the buff". This means that they don't need to be "clothed" in quotes when defining objek literals. See the ES5 <a href="http://es5.github.io/#x7.6.1">Spec</a>.</p> +</div> + +<p>For more on objeks and prototypes see: <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype">objek.prototype</a>.</p> + +<h2 id="Arrays">Arrays</h2> + +<p>Arrays in JavaScript are actually a special type of objek. They work very much like regular objeks (numerical properties can naturally be accessed only using <code>[]</code> syntax) but they have one magic property called '<code>length</code>'. This is always one more than the highest index in the array.</p> + +<p>One way of creating arrays is as follows:</p> + +<pre class="brush: js notranslate">var a = new Array(); +a[0] = "dog"; +a[1] = "cat"; +a[2] = "hen"; +a.length; // 3 +</pre> + +<p>A more convenient notation is to use an array literal:</p> + +<pre class="brush: js notranslate">var a = ["dog", "cat", "hen"]; +a.length; // 3 +</pre> + +<p>Note that <code>array.length</code> isn't necessarily the number of items in the array. Consider the following:</p> + +<pre class="brush: js notranslate">var a = ["dog", "cat", "hen"]; +a[100] = "fox"; +a.length; // 101 +</pre> + +<p>Remember — the length of the array is one more than the highest index.</p> + +<p>If you query a non-existent array index, you'll get a value of <code>undefined</code> returned:</p> + +<pre class="brush: js notranslate">typeof a[90]; // undefined +</pre> + +<p>If you take the above into account, you can iterate over an array using the following:</p> + +<pre class="brush: js notranslate">for (var i = 0; i < a.length; i++) { + // Do something with a[i] +} +</pre> + +<p>You can iterate over an array using a <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/for...in" title="/en/JavaScript/Reference/Statements/for...in">for...in</a></code> loop. Note that if someone added new properties to <code>Array.prototype</code>, they will also be iterated over by this loop. Therefore this method is "not" recommended.</p> + +<p>Another way of iterating over an array that was added with ECMAScript 5 is <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach">forEach()</a>:</p> + +<pre class="brush: js notranslate" style="font-size: 14px;">["dog", "cat", "hen"].forEach(function(currentValue, index, array) { + // Do something with currentValue or array[index] +}); +</pre> + +<p>If you want to append an item to an array simply do it like this:</p> + +<pre class="brush: js notranslate">a.push(item);</pre> + +<p>Arrays come with a number of methods. See also the <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array">full documentation for array methods</a>.</p> + +<table> + <thead> + <tr> + <th scope="col">Method name</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>a.toString()</code></td> + <td>Returns a string with the <code>toString()</code> of each element separated by commas.</td> + </tr> + <tr> + <td><code>a.toLocaleString()</code></td> + <td>Returns a string with the <code>toLocaleString()</code> of each element separated by commas.</td> + </tr> + <tr> + <td><code>a.concat(item1[, item2[, ...[, itemN]]])</code></td> + <td>Returns a new array with the items added on to it.</td> + </tr> + <tr> + <td><code>a.join(sep)</code></td> + <td>Converts the array to a string — with values delimited by the <code>sep</code> param</td> + </tr> + <tr> + <td><code>a.pop()</code></td> + <td>Removes and returns the last item.</td> + </tr> + <tr> + <td><code>a.push(item1, ..., itemN)</code></td> + <td>Adds one or more items to the end.</td> + </tr> + <tr> + <td><code>a.reverse()</code></td> + <td>Reverses the array.</td> + </tr> + <tr> + <td><code>a.shift()</code></td> + <td>Removes and returns the first item.</td> + </tr> + <tr> + <td><code>a.slice(start[, end])</code></td> + <td>Returns a sub-array.</td> + </tr> + <tr> + <td><code>a.sort([cmpfn])</code></td> + <td>Takes an optional comparison function.</td> + </tr> + <tr> + <td><code>a.splice(start, delcount[, item1[, ...[, itemN]]])</code></td> + <td>Lets you modify an array by deleting a section and replacing it with more items.</td> + </tr> + <tr> + <td><code>a.unshift(item1[, item2[, ...[, itemN]]])</code></td> + <td>Prepends items to the start of the array.</td> + </tr> + </tbody> +</table> + +<h2 id="Functions">Functions</h2> + +<p>Along with objeks, functions are the core component in understanding JavaScript. The most basic function couldn't be much simpler:</p> + +<pre class="brush: js notranslate">function add(x, y) { + var total = x + y; + return total; +} +</pre> + +<p>This demonstrates a basic function. A JavaScript function can take 0 or more named parameters. The function body can contain as many statements as you like, and can declare its own variables which are local to that function. The <code>return</code> statement can be used to return a value at any time, terminating the function. If no return statement is used (or an empty return with no value), JavaScript returns <code>undefined</code>.</p> + +<p>The named parameters turn out to be more like guidelines than anything else. You can call a function without passing the parameters it expects, in which case they will be set to <code>undefined</code>.</p> + +<pre class="brush: js notranslate">add(); // NaN +// You can't perform addition on undefined +</pre> + +<p>You can also pass in more arguments than the function is expecting:</p> + +<pre class="brush: js notranslate">add(2, 3, 4); // 5 +// added the first two; 4 was ignored +</pre> + +<p>That may seem a little silly, but functions have access to an additional variable inside their body called <a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments" title="/en/JavaScript/Reference/Functions_and_function_scope/arguments"><code>arguments</code></a>, which is an array-like objek holding all of the values passed to the function. Let's re-write the add function to take as many values as we want:</p> + +<pre class="brush: js notranslate">function add() { + var sum = 0; + for (var i = 0, j = arguments.length; i < j; i++) { + sum += arguments[i]; + } + return sum; +} + +add(2, 3, 4, 5); // 14 +</pre> + +<p>That's really not any more useful than writing <code>2 + 3 + 4 + 5</code> though. Let's create an averaging function:</p> + +<pre class="brush: js notranslate">function avg() { + var sum = 0; + for (var i = 0, j = arguments.length; i < j; i++) { + sum += arguments[i]; + } + return sum / arguments.length; +} + +avg(2, 3, 4, 5); // 3.5 +</pre> + +<p>This is pretty useful, but introduces a new problem. The <code>avg()</code> function takes a comma separated list of arguments — but what if you want to find the average of an array? You could just rewrite the function as follows:</p> + +<pre class="brush: js notranslate">function avgArray(arr) { + var sum = 0; + for (var i = 0, j = arr.length; i < j; i++) { + sum += arr[i]; + } + return sum / arr.length; +} + +avgArray([2, 3, 4, 5]); // 3.5 +</pre> + +<p>But it would be nice to be able to reuse the function that we've already created. Luckily, JavaScript lets you call a function and call it with an arbitrary array of arguments, using the {{jsxref("Function.apply", "apply()")}} method of any function objek.</p> + +<pre class="brush: js notranslate">avg.apply(null, [2, 3, 4, 5]); // 3.5 +</pre> + +<p>The second argument to <code>apply()</code> is the array to use as arguments; the first will be discussed later on. This emphasizes the fact that functions are objeks too.</p> + +<p>JavaScript lets you create anonymous functions.</p> + +<pre class="brush: js notranslate">var avg = function() { + var sum = 0; + for (var i = 0, j = arguments.length; i < j; i++) { + sum += arguments[i]; + } + return sum / arguments.length; +}; +</pre> + +<p>This is semantically equivalent to the <code>function avg()</code> form. It's extremely powerful, as it lets you put a full function definition anywhere that you would normally put an expression. This enables all sorts of clever tricks. Here's a way of "hiding" some local variables — like block scope in C:</p> + +<pre class="brush: js notranslate">var a = 1; +var b = 2; + +(function() { + var b = 3; + a += b; +})(); + +a; // 4 +b; // 2 +</pre> + +<p>JavaScript allows you to call functions recursively. This is particularly useful for dealing with tree structures, such as those found in the browser DOM.</p> + +<pre class="brush: js notranslate">function countChars(elm) { + if (elm.nodeType == 3) { // TEXT_NODE + return elm.nodeValue.length; + } + var count = 0; + for (var i = 0, child; child = elm.childNodes[i]; i++) { + count += countChars(child); + } + return count; +} +</pre> + +<p>This highlights a potential problem with anonymous functions: how do you call them recursively if they don't have a name? JavaScript lets you name function expressions for this. You can use named IIFEs (Immediately Invoked Function Expressions) as shown below:</p> + +<pre class="brush: js notranslate">var charsInBody = (function counter(elm) { + if (elm.nodeType == 3) { // TEXT_NODE + return elm.nodeValue.length; + } + var count = 0; + for (var i = 0, child; child = elm.childNodes[i]; i++) { + count += counter(child); + } + return count; +})(document.body); +</pre> + +<p>The name provided to a function expression as above is only available to the function's own scope. This allows more optimizations to be done by the engine and results in more readable code. The name also shows up in the debugger and some stack traces, which can save you time when debugging.</p> + +<p>Note that JavaScript functions are themselves objeks — like everything else in JavaScript — and you can add or change properties on them just like we've seen earlier in the objeks section.</p> + +<h2 id="Custom_objeks">Custom objeks</h2> + +<div class="note">For a more detailed discussion of objek-oriented programming in JavaScript, see <a href="/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript" title="https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript">Introduction to objek Oriented JavaScript</a>.</div> + +<p>In classic objek Oriented Programming, objeks are collections of data and methods that operate on that data. JavaScript is a prototype-based language that contains no class statement, as you'd find in C++ or Java (this is sometimes confusing for programmers accustomed to languages with a class statement.) Instead, JavaScript uses functions as classes. Let's consider a person objek with first and last name fields. There are two ways in which the name might be displayed: as "first last" or as "last, first". Using the functions and objeks that we've discussed previously, we could display the data like this:</p> + +<pre class="example-bad brush: js notranslate">function makePerson(first, last) { + return { + first: first, + last: last + }; +} +function personFullName(person) { + return person.first + ' ' + person.last; +} +function personFullNameReversed(person) { + return person.last + ', ' + person.first; +} + +s = makePerson("Simon", "Willison"); +personFullName(s); // "Simon Willison" +personFullNameReversed(s); // "Willison, Simon" +</pre> + +<p>This works, but it's pretty ugly. You end up with dozens of functions in your global namespace. What we really need is a way to attach a function to an objek. Since functions are objeks, this is easy:</p> + +<pre class="brush: js notranslate">function makePerson(first, last) { + return { + first: first, + last: last, + fullName: function() { + return this.first + ' ' + this.last; + }, + fullNameReversed: function() { + return this.last + ', ' + this.first; + } + }; +} + +s = makePerson("Simon", "Willison") +s.fullName(); // "Simon Willison" +s.fullNameReversed(); // "Willison, Simon" +</pre> + +<p>There's something here we haven't seen before: the <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/this" title="/en/JavaScript/Reference/Operators/this">this</a></code> keyword. Used inside a function, <code>this</code> refers to the current objek. What that actually means is specified by the way in which you called that function. If you called it using <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Accessing_properties" title="/en/JavaScript/Reference/Operators/Member_Operators">dot notation or bracket notation</a> on an objek, that objek becomes <code>this</code>. If dot notation wasn't used for the call, <code>this</code> refers to the global objek.</p> + +<p>Note that <code>this</code> is a frequent cause of mistakes. For example:</p> + +<pre class="brush: js notranslate">s = makePerson("Simon", "Willison"); +var fullName = s.fullName; +fullName(); // undefined undefined +</pre> + +<p>When we call <code>fullName()</code> alone, without using <code>s.fullName()</code>, <code>this</code> is bound to the global objek. Since there are no global variables called <code>first</code> or <code>last</code> we get <code>undefined</code> for each one.</p> + +<p>We can take advantage of the <code>this</code> keyword to improve our <code>makePerson</code> function:</p> + +<pre class="brush: js notranslate">function Person(first, last) { + this.first = first; + this.last = last; + this.fullName = function() { + return this.first + ' ' + this.last; + }; + this.fullNameReversed = function() { + return this.last + ', ' + this.first; + }; +} +var s = new Person("Simon", "Willison"); +</pre> + +<p>We have introduced another keyword: <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/new" title="/en/JavaScript/Reference/Operators/new">new</a></code>. <code>new</code> is strongly related to <code>this</code>. It creates a brand new empty objek, and then calls the function specified, with <code>this</code> set to that new objek. Notice though that the function specified with <code>this</code> does not return a value but merely modifies the <code>this</code> objek. It's new that returns the <code>this</code> objek to the calling site. Functions that are designed to be called by <code>new</code> are called constructor functions. Common practice is to capitalize these functions as a reminder to call them with <code>new</code>.</p> + +<p>The improved function still has the same pitfall with calling <code>fullName()</code> alone.</p> + +<p>Our person objeks are getting better, but there are still some ugly edges to them. Every time we create a person objek we are creating two brand new function objeks within it — wouldn't it be better if this code was shared?</p> + +<pre class="brush: js notranslate">function personFullName() { + return this.first + ' ' + this.last; +} +function personFullNameReversed() { + return this.last + ', ' + this.first; +} +function Person(first, last) { + this.first = first; + this.last = last; + this.fullName = personFullName; + this.fullNameReversed = personFullNameReversed; +} +</pre> + +<p>That's better: we are creating the method functions only once, and assigning references to them inside the constructor. Can we do any better than that? The answer is yes:</p> + +<pre class="brush: js notranslate">function Person(first, last) { + this.first = first; + this.last = last; +} +Person.prototype.fullName = function() { + return this.first + ' ' + this.last; +}; +Person.prototype.fullNameReversed = function() { + return this.last + ', ' + this.first; +}; +</pre> + +<p><code>Person.prototype</code> is an objek shared by all instances of <code>Person</code>. It forms part of a lookup chain (that has a special name, "prototype chain"): any time you attempt to access a property of <code>Person</code> that isn't set, JavaScript will check <code>Person.prototype</code> to see if that property exists there instead. As a result, anything assigned to <code>Person.prototype</code> becomes available to all instances of that constructor via the <code>this</code> objek.</p> + +<p>This is an incredibly powerful tool. JavaScript lets you modify something's prototype at any time in your program, which means you can add extra methods to existing objeks at runtime:</p> + +<pre class="brush: js notranslate">s = new Person("Simon", "Willison"); +s.firstNameCaps(); // TypeError on line 1: s.firstNameCaps is not a function + +Person.prototype.firstNameCaps = function firstNameCaps() { + return this.first.toUpperCase() +}; +s.firstNameCaps(); // "SIMON" +</pre> + +<p>Interestingly, you can also add things to the prototype of built-in JavaScript objeks. Let's add a method to <code>String</code> that returns that string in reverse:</p> + +<pre class="brush: js notranslate">var s = "Simon"; +s.reversed(); // TypeError on line 1: s.reversed is not a function + +String.prototype.reversed = function reversed() { + var r = ""; + for (var i = this.length - 1; i >= 0; i--) { + r += this[i]; + } + return r; +}; + +s.reversed(); // nomiS +</pre> + +<p>Our new method even works on string literals!</p> + +<pre class="brush: js notranslate">"This can now be reversed".reversed(); // desrever eb won nac sihT +</pre> + +<p>As mentioned before, the prototype forms part of a chain. The root of that chain is <code>objek.prototype</code>, whose methods include <code>toString()</code> — it is this method that is called when you try to represent an objek as a string. This is useful for debugging our <code>Person</code> objeks:</p> + +<pre class="brush: js notranslate">var s = new Person("Simon", "Willison"); +s; // [objek objek] + +Person.prototype.toString = function() { + return '<Person: ' + this.fullName() + '>'; +} + +s.toString(); // "<Person: Simon Willison>" +</pre> + +<p>Remember how <code>avg.apply()</code> had a null first argument? We can revisit that now. The first argument to <code>apply()</code> is the objek that should be treated as '<code>this</code>'. For example, here's a trivial implementation of <code>new</code>:</p> + +<pre class="brush: js notranslate">function trivialNew(constructor, ...args) { + var o = {}; // Create an objek + constructor.apply(o, args); + return o; +} +</pre> + +<p>This isn't an exact replica of <code>new</code> as it doesn't set up the prototype chain (it would be difficult to illustrate). This is not something you use very often, but it's useful to know about. In this snippet, <code>...args</code> (including the ellipsis) is called the "<a href="/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters">rest arguments</a>" — as the name implies, this contains the rest of the arguments.</p> + +<p>Calling</p> + +<pre class="brush: js notranslate">var bill = trivialNew(Person, "William", "Orange");</pre> + +<p>is therefore almost equivalent to</p> + +<pre class="brush: js notranslate">var bill = new Person("William", "Orange");</pre> + +<p><code>apply()</code> has a sister function named <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call" title="/en/JavaScript/Reference/Global_Objects/Function/call"><code>call</code></a>, which again lets you set <code>this</code> but takes an expanded argument list as opposed to an array.</p> + +<pre class="brush: js notranslate">function lastNameCaps() { + return this.last.toUpperCase(); +} +var s = new Person("Simon", "Willison"); +lastNameCaps.call(s); +// Is the same as: +s.lastNameCaps = lastNameCaps; +s.lastNameCaps(); +</pre> + +<h3 id="Inner_functions">Inner functions</h3> + +<p>JavaScript function declarations are allowed inside other functions. We've seen this once before, with an earlier <code>makePerson()</code> function. An important detail of nested functions in JavaScript is that they can access variables in their parent function's scope:</p> + +<pre class="brush: js notranslate">function betterExampleNeeded() { + var a = 1; + function oneMoreThanA() { + return a + 1; + } + return oneMoreThanA(); +} +</pre> + +<p>This provides a great deal of utility in writing more maintainable code. If a function relies on one or two other functions that are not useful to any other part of your code, you can nest those utility functions inside the function that will be called from elsewhere. This keeps the number of functions that are in the global scope down, which is always a good thing.</p> + +<p>This is also a great counter to the lure of global variables. When writing complex code it is often tempting to use global variables to share values between multiple functions — which leads to code that is hard to maintain. Nested functions can share variables in their parent, so you can use that mechanism to couple functions together when it makes sense without polluting your global namespace — "local globals" if you like. This technique should be used with caution, but it's a useful ability to have.</p> + +<h2 id="Closures">Closures</h2> + +<p>This leads us to one of the most powerful abstractions that JavaScript has to offer — but also the most potentially confusing. What does this do?</p> + +<pre class="brush: js notranslate">function makeAdder(a) { + return function(b) { + return a + b; + }; +} +var x = makeAdder(5); +var y = makeAdder(20); +x(6); // ? +y(7); // ? +</pre> + +<p>The name of the <code>makeAdder()</code> function should give it away: it creates a new 'adder' functions, which when called with one argument adds it to the argument that they were created with.</p> + +<p>What's happening here is pretty much the same as was happening with the inner functions earlier on: a function defined inside another function has access to the outer function's variables. The only difference here is that the outer function has returned, and hence common sense would seem to dictate that its local variables no longer exist. But they <em>do</em> still exist — otherwise the adder functions would be unable to work. What's more, there are two different "copies" of <code>makeAdder()</code>'s local variables — one in which <code>a</code> is 5 and one in which <code>a</code> is 20. So the result of those function calls is as follows:</p> + +<pre class="brush: js notranslate">x(6); // returns 11 +y(7); // returns 27 +</pre> + +<p>Here's what's actually happening. Whenever JavaScript executes a function, a 'scope' objek is created to hold the local variables created within that function. It is initialized with any variables passed in as function parameters. This is similar to the global objek that all global variables and functions live in, but with a couple of important differences: firstly, a brand new scope objek is created every time a function starts executing, and secondly, unlike the global objek (which is accessible as <code>this</code> and in browsers as <code>window</code>) these scope objeks cannot be directly accessed from your JavaScript code. There is no mechanism for iterating over the properties of the current scope objek, for example.</p> + +<p>So when <code>makeAdder()</code> is called, a scope objek is created with one property: <code>a</code>, which is the argument passed to the <code>makeAdder()</code> function. <code>makeAdder()</code> then returns a newly created function. Normally JavaScript's garbage collector would clean up the scope objek created for <code>makeAdder()</code> at this point, but the returned function maintains a reference back to that scope objek. As a result, the scope objek will not be garbage collected until there are no more references to the function objek that <code>makeAdder()</code> returned.</p> + +<p>Scope objeks form a chain called the scope chain, similar to the prototype chain used by JavaScript's objek system.</p> + +<p>A <strong>closure</strong> is the combination of a function and the scope objek in which it was created. Closures let you save state — as such, they can often be used in place of objeks. You can find <a href="http://stackoverflow.com/questions/111102/how-do-javascript-closures-work">several excellent introductions to closures</a>.</p> |
