-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
501 lines (346 loc) · 125 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Yovelas</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description" content="This is yovelas blog, include Java,JavaScript,Node,Python programing technology article">
<meta property="og:type" content="website">
<meta property="og:title" content="Yovelas">
<meta property="og:url" content="http://yovelas.github.io/">
<meta property="og:site_name" content="Yovelas">
<meta property="og:description" content="This is yovelas blog, include Java,JavaScript,Node,Python programing technology article">
<meta property="og:locale" content="en_US">
<meta property="article:author" content="Yovelas">
<meta property="article:tag" content="Java">
<meta property="article:tag" content="JavaScript">
<meta property="article:tag" content="Python">
<meta property="article:tag" content="MySQL">
<meta property="article:tag" content="Angular">
<meta property="article:tag" content="SpringBoot">
<meta property="article:tag" content="Node">
<meta property="article:tag" content="Less">
<meta property="article:tag" content="Design">
<meta property="article:tag" content="UI">
<meta name="twitter:card" content="summary">
<link rel="alternate" href="/atom.xml" title="Yovelas" type="application/atom+xml">
<link rel="icon" href="/favicon.png">
<link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="/css/style.css">
<meta name="generator" content="Hexo 4.2.0"></head>
<body>
<div id="container">
<div id="wrap">
<header id="header">
<div id="banner"></div>
<div id="header-outer" class="outer">
<div id="header-title" class="inner">
<h1 id="logo-wrap">
<a href="/" id="logo">Yovelas</a>
</h1>
<h2 id="subtitle-wrap">
<a href="/" id="subtitle">Yovelas Blog</a>
</h2>
</div>
<div id="header-inner" class="inner">
<nav id="main-nav">
<a id="main-nav-toggle" class="nav-icon"></a>
<a class="main-nav-link" href="/">Home</a>
<a class="main-nav-link" href="/archives">Archives</a>
</nav>
<nav id="sub-nav">
<a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
<a id="nav-search-btn" class="nav-icon" title="Search"></a>
</nav>
<div id="search-form-wrap">
<form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit"></button><input type="hidden" name="sitesearch" value="http://yovelas.github.io"></form>
</div>
</div>
</div>
</header>
<div class="outer">
<section id="main">
<article id="post-Class and Module" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2019/09/22/Class%20and%20Module/" class="article-date">
<time datetime="2019-09-22T13:36:38.000Z" itemprop="datePublished">2019-09-22</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2019/09/22/Class%20and%20Module/">Class and Module</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h1 id="Class"><a href="#Class" class="headerlink" title="Class"></a>Class</h1><p>Treated each object as a unique set of properties, different from every other object. It is often useful, however, to define a <code>class</code> of objects that share certain properties. Members, or <code>instances</code>, of the class have their own properties to hold or define their state, but they also have properties (typically methods) that define their behavior. This behavior is defined by the class and is shared by all instances. Imagine a class named Complex to represent and perform arithmetic on complex numbers, for example. A Complex instance would have properties to hold the real and imaginary parts (state) of the complex number. And the Complex class would define methods to perfor addition and multiplication (behavior) of those numbers.</p>
<p>In JavaScript, classes are based on JavaScript’s prototype-based inheritance mechanism. If two objects inherit properties from the same prototype object, then we say that they are instances of the same class.</p>
<p>If two objects inherit from the same prototype, this typically (but not necessarily) means that they were created and initialized by the same constructor function.</p>
<p>JavaScript classes are quite different from classes in the Java or C++ languges. There are some syntaxtic similarities, and you can emulate many features of “classical” classes in JavaScript, but it is best to understand up front that JavaScript’s classes and prototype-based inheritance mechanism are substantially different from the classes and class-based inheritance mechanism of Java and similar languages.</p>
<p>One of the important features of JavaScript classes is that they are dynamically extendable. </p>
<h2 id="Classes-and-Prototypes"><a href="#Classes-and-Prototypes" class="headerlink" title="Classes and Prototypes"></a>Classes and Prototypes</h2><p>In JavaScript, a class is a set of objects that inherit properties from the same prototype object. The prototype object, therefore, is the central feature of a class. Usually, the instances of a class require further initialization, and it is common to define a function that creates and initializes the new object. Following demonstrates this: it defines a prototype object for a class that represents a range of values and also defines a “factory” function the creates and initializes a new instance of the class.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// range.js: A class representing a range of values.</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// This is a factory function that returns a new range object. </span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">range</span>(<span class="params">from, to</span>) </span>{</span><br><span class="line"> <span class="comment">// Use the inherit() function to create an object that inherits from the </span></span><br><span class="line"> <span class="comment">// prototype object defined below. The prototype object is stored as</span></span><br><span class="line"> <span class="comment">// a property of this function, and defines the shared methods (behavior) </span></span><br><span class="line"> <span class="comment">// for all range objects.</span></span><br><span class="line"> <span class="keyword">var</span> r = <span class="built_in">Object</span>.create(range.methods);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Store the start and end points (state) of this new range object. </span></span><br><span class="line"> <span class="comment">// These are noninherited properties that are unique to this object. </span></span><br><span class="line"> r.from = <span class="keyword">from</span>;</span><br><span class="line"> r.to = to;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// Finally return the new object</span></span><br><span class="line"> <span class="keyword">return</span> r; </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// This prototype object defines methods inherited by all range objects. </span></span><br><span class="line">range.methods = {</span><br><span class="line"> <span class="comment">// Return true if x is in the range, false otherwise</span></span><br><span class="line"> <span class="comment">// This method works for textual and Date ranges as well as numeric.</span></span><br><span class="line"> includes: <span class="function"><span class="keyword">function</span>(<span class="params">x</span>) </span>{ <span class="keyword">return</span> <span class="keyword">this</span>.from <= x && x <= <span class="keyword">this</span>.to; },</span><br><span class="line"> <span class="comment">// Invoke f once for each integer in the range.</span></span><br><span class="line"> <span class="comment">// This method works only for numeric ranges.</span></span><br><span class="line"> foreach: <span class="function"><span class="keyword">function</span>(<span class="params">f</span>) </span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> x = <span class="built_in">Math</span>.ceil(<span class="keyword">this</span>.from); x <= <span class="keyword">this</span>.to; x++) f(x); </span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// Return a string representation of the range</span></span><br><span class="line"> toString: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{ <span class="keyword">return</span> <span class="string">"("</span> + <span class="keyword">this</span>.from + <span class="string">"..."</span> + <span class="keyword">this</span>.to + <span class="string">")"</span>; }</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">// Here are example uses of a range object.</span></span><br><span class="line"><span class="keyword">var</span> r = range(<span class="number">1</span>,<span class="number">3</span>); <span class="comment">// Create a range object</span></span><br><span class="line">r.includes(<span class="number">2</span>); <span class="comment">// => true: 2 is in the range </span></span><br><span class="line">r.foreach(<span class="built_in">console</span>.log); <span class="comment">// Prints 1 2 3</span></span><br><span class="line"><span class="built_in">console</span>.log(r); <span class="comment">// Prints (1...3)</span></span><br></pre></td></tr></table></figure>
<p>This code defines a factory function <code>range()</code> for creating new range objects. Notice that we use a property of this <code>range()</code> function <code>range.methods</code> as a convenient place to store the prototype object that defines the class. There is nothing special or idiomatic about putting the prototype object here. Second, notice that the <code>range()</code> function defines <code>from</code> and <code>to</code> prototype on each range object. These are unshared, noninherited properties that define the unique state of each individual range object. Finally, notice that the shared, inherited methods defined in <code>range.methods</code> all use these <code>from</code> and <code>to</code> properties, and in order to refer to them, they use the <code>this</code> keyword to refer to the object through which they were invoked. This use of <code>this</code> is a fundamental characteristic of the methods of any class.</p>
<h2 id="Classes-and-Constructors"><a href="#Classes-and-Constructors" class="headerlink" title="Classes and Constructors"></a>Classes and Constructors</h2><p>Above demonstrates one way to define a JavaScript class. It is not the idiomatic way to do so, however, because it did not define a <code>constructor</code>. A constructor is function designed for the initialization of newly created objects. Constructors are invoked using the <code>new</code> keyword. Constructor invocations using <code>new</code> automatically create the new object, so the constructor itself only needs to initialize the state of that new object. The critical feature of constructor invocations is that the <code>prototype</code> property of the constructor is used as the prototype of the new object. This means that all objects created with the same constructor inherit from the same object and are therefore members of the same class.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// range2.js: Another class representing a range of values.</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// This is a constructor function that initializes new Range objects.</span></span><br><span class="line"><span class="comment">// Note that it does not create or return the object. It just initializes this.</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Range</span>(<span class="params">from, to</span>) </span>{</span><br><span class="line"> <span class="comment">// Store the start and end points (state) of this new range object. </span></span><br><span class="line"> <span class="comment">// These are noninherited properties that are unique to this object. </span></span><br><span class="line"> <span class="keyword">this</span>.from = <span class="keyword">from</span>;</span><br><span class="line"> <span class="keyword">this</span>.to = to;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// All Range objects inherit from this object.</span></span><br><span class="line"><span class="comment">// Note that the property name must be "prototype" for this to work.</span></span><br><span class="line">Range.prototype = {</span><br><span class="line"> <span class="comment">// Return true if x is in the range, false otherwise</span></span><br><span class="line"> <span class="comment">// This method works for textual and Date ranges as well as numeric. </span></span><br><span class="line"> includes: <span class="function"><span class="keyword">function</span>(<span class="params">x</span>) </span>{ </span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.from <= x && x <= <span class="keyword">this</span>.to; </span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// Invoke f once for each integer in the range.</span></span><br><span class="line"> <span class="comment">// This method works only for numeric ranges.</span></span><br><span class="line"> foreach: <span class="function"><span class="keyword">function</span>(<span class="params">f</span>) </span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> x = <span class="built_in">Math</span>.ceil(<span class="keyword">this</span>.from); x <= <span class="keyword">this</span>.to; x++) f(x); </span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// Return a string representation of the range</span></span><br><span class="line"> toString: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{ </span><br><span class="line"> <span class="keyword">return</span> <span class="string">"("</span> + <span class="keyword">this</span>.from + <span class="string">"..."</span> + <span class="keyword">this</span>.to + <span class="string">")"</span>; </span><br><span class="line"> } </span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">// Here are example uses of a range object</span></span><br><span class="line"><span class="keyword">var</span> r = <span class="keyword">new</span> Range(<span class="number">1</span>,<span class="number">3</span>); <span class="comment">// Create a range object</span></span><br><span class="line">r.includes(<span class="number">2</span>); <span class="comment">// => true: 2 is in the range </span></span><br><span class="line">r.foreach(<span class="built_in">console</span>.log); <span class="comment">// Prints 1 2 3</span></span><br><span class="line"><span class="built_in">console</span>.log(r); <span class="comment">// Prints (1...3)</span></span><br></pre></td></tr></table></figure>
<p>Noting the differences between these two techniques for defining classes. First, notice that we renamed the <code>range()</code> factory function to <code>Range()</code> when we converted it to a constructor. This is very common coding convention: constructor functions define, in a sense, classes, and classes have names that begin with capital letter. Regular functions and methods have names that begin with lowercase letters.</p>
<p>Next, notice that the <code>Range()</code> constructor is invoked with <code>new</code> keyword while the <code>range()</code> factory function was invoked without it. Because the <code>Range()</code> constructor is invoked with <code>new</code>, it does not have to call <code>Object.create()</code> or take any action to create a new object. The new object is automatically created before the constructor is called, and it is accessible as the <code>this</code> value. The <code>Range()</code> constructor merely has to initalize <code>this</code>. Constructors do not even have to return the newly created object. Constructor invocation automatically creates a new object, invokes the constructor as a method of that object, and returns the new object. The fact that constructor invocation is so different from regular function invocation is another reason that we give constructors names that start with capital letters. Constructors are written to be invoked as constructors, with the <code>new</code> keyword, and they usually won’t work properly if they are invoked as regular functions. A naming convention that keeps constructor functions distinct from regular functions helps progrmmers to know when to use <code>new</code>.</p>
<p>Another critical difference is the way the prototype object is named. In the first example, the prototype was <code>range.methods</code>. This was a convenient and descriptive name, but arbitrary. In the second example, the prototype is <code>Range.prototype</code>, and this name is mandatory. An invocation of the <code>Range()</code> constructor automatically uses <code>Range.prototype</code> as the prototype of the new Range object.</p>
<h3 id="Constructors-and-Class-Identity"><a href="#Constructors-and-Class-Identity" class="headerlink" title="Constructors and Class Identity"></a>Constructors and Class Identity</h3><p>The prototype object is fundamental to the identify of a class: two objects are instances of the same class if and only if they inherit from the same prototype object. The constructor function that initializes the state of a new object is not fundamental: two constructor functions may have <code>prototype</code> properties that point to the same property object. Then both constructors can be used to create instances of the same class.</p>
<p>Even through constructors are not as fundamental as prototypes, the constructor serves as the public face of a class. Most obviously, the name of the constructor function is usually adopted as the name of the class. We say, for example, that the <code>Range()</code> constructor creates Range objects. More fundamentally, however, constructors are used with the <code>instanceof</code> operator when testing objects for membership in a class. If we have an object <code>r</code> and want to known if it is a Range object, we can write:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">r <span class="keyword">instanceof</span> Range <span class="comment">// Returns true if r inherits from Range.prototype</span></span><br></pre></td></tr></table></figure>
<p>The <code>instanceof</code> operator does not actually check whether <code>r</code> was initialized by the <code>Range</code> constructor. It checks whether it inherits from <code>Range.prototype</code>. Nevertheless, this <code>instaceof</code> syntax reinforces the use of constructors as the public identity of a class.</p>
<h3 id="The-constructor-Property"><a href="#The-constructor-Property" class="headerlink" title="The constructor Property"></a>The constructor Property</h3><p>We set <code>Range.prototype</code> to a new object that contained the methods for our class. Although it was convenient to express those methods as properties of a single object literal, it was not actually necessary to create a new object. Any JavaScript function can be used as a constructor, and constructor invocations need a <code>prototype</code> property. Therefore, every JavaScript function (except functions returned by the ECMAScript 5 <code>Function.bind()</code> method) automatically has a <code>prototype</code> property. The value of this property is an object that has a single nonenumerable <code>constructor</code> property. The value of the <code>constructor</code> property is the function object:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> F = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{}; <span class="comment">// This is a function object.</span></span><br><span class="line"><span class="keyword">var</span> p = F.prototype; <span class="comment">// This is the prototype object associated with it. </span></span><br><span class="line"><span class="keyword">var</span> c = p.constructor; <span class="comment">// This is the function associated with the prototype.</span></span><br><span class="line">c === F <span class="comment">// => true: F.prototype.constructor==F for any function</span></span><br></pre></td></tr></table></figure>
<p>The existence of this predefined prototype object with its <code>constructor</code> property means that objects typically inherit a <code>constructor</code> property that refers to their constructor. Since constructors serve as the public identity of a class, this constructor property gives the class of an object:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> o = <span class="keyword">new</span> F(); <span class="comment">// Create an object o of class F</span></span><br><span class="line">o.constructor === F <span class="comment">// true: the constructor property specifies the class</span></span><br></pre></td></tr></table></figure>
<p>In fact, the Range class defined in Simple Class Example By Constructor overwrites the predefined <code>Range.prototype</code> object with an object of its own. And the new prototype object it defines does not have a <code>constructor</code> property. So instances of the Range class, as defined, do not have a <code>constructor</code> property. We can remedy this problem by explicitly adding a constructor to the prototype:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Range.prototype = {</span><br><span class="line"> <span class="keyword">constructor</span>: Range, // Explicitly <span class="keyword">set</span> the <span class="keyword">constructor</span> back-reference </span><br><span class="line"> includes: function(x) { <span class="keyword">return</span> <span class="keyword">this</span>.from <= x && x <= <span class="keyword">this</span>.to; }, </span><br><span class="line"> foreach: <span class="function"><span class="keyword">function</span>(<span class="params">f</span>) </span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> x = <span class="built_in">Math</span>.ceil(<span class="keyword">this</span>.from); x <= <span class="keyword">this</span>.to; x++) f(x); </span><br><span class="line"> },</span><br><span class="line"> toString: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{ <span class="keyword">return</span> <span class="string">"("</span> + <span class="keyword">this</span>.from + <span class="string">"..."</span> + <span class="keyword">this</span>.to + <span class="string">")"</span>; } </span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>Another common technique is to use the predefined prototype object with its <code>constructor</code> property, and add methods to it one at a time:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Extend the predefined Range.prototype object so we don't overwrite</span></span><br><span class="line"><span class="comment">// the automatically created Range.prototype.constructor property.</span></span><br><span class="line">Range.prototype.includes = <span class="function"><span class="keyword">function</span>(<span class="params">x</span>) </span>{ </span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.from<=x && x<=<span class="keyword">this</span>.to;</span><br><span class="line">};</span><br><span class="line">Range.prototype.foreach = <span class="function"><span class="keyword">function</span>(<span class="params">f</span>) </span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> x = <span class="built_in">Math</span>.ceil(<span class="keyword">this</span>.from); x <= <span class="keyword">this</span>.to; x++) f(x); </span><br><span class="line">};</span><br><span class="line">Range.prototype.toString = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"("</span> + <span class="keyword">this</span>.from + <span class="string">"..."</span> + <span class="keyword">this</span>.to + <span class="string">")"</span>;</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h2 id="ES6-Classes"><a href="#ES6-Classes" class="headerlink" title="ES6 Classes"></a>ES6 Classes</h2><p>In JavaScript, classes are the special type of functions. We can define the class just like function declarations and function expressions.</p>
<p>The JavaScript class contains various class members within a body including methods or constructor. The class is executed in strict mode. So,the code containing the silent error or mistake throws an error.</p>
<h3 id="Class-declarations-define-classes"><a href="#Class-declarations-define-classes" class="headerlink" title="Class declarations define classes"></a>Class declarations define classes</h3><p>A class can be defined by using a class declaration. A <code>class</code> keyword is used to declare a class with any particular name. According to JavaScript naming conventions,the name of the class always starts with an uppercase letter.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Employee</span> </span>{ </span><br><span class="line"> <span class="comment">//Initializing an object </span></span><br><span class="line"> <span class="keyword">constructor</span>(id,name) { </span><br><span class="line"> <span class="keyword">this</span>.id=id; </span><br><span class="line"> <span class="keyword">this</span>.name=name; </span><br><span class="line"> } </span><br><span class="line"></span><br><span class="line"> <span class="comment">//Declaring method </span></span><br><span class="line"> detail() { </span><br><span class="line"> <span class="built_in">document</span>.writeln(<span class="keyword">this</span>.id+<span class="string">" "</span>+<span class="keyword">this</span>.name+<span class="string">"<br>"</span>) </span><br><span class="line"> } </span><br><span class="line">} </span><br><span class="line"></span><br><span class="line"><span class="comment">//passing object to a variable </span></span><br><span class="line"><span class="keyword">var</span> e1=<span class="keyword">new</span> Employee(<span class="number">101</span>,<span class="string">"Martin Roy"</span>); </span><br><span class="line"><span class="keyword">var</span> e2=<span class="keyword">new</span> Employee(<span class="number">102</span>,<span class="string">"Duke William"</span>); </span><br><span class="line"><span class="comment">//calling method </span></span><br><span class="line">e1.detail(); <span class="comment">// => 101 Martin Roy</span></span><br><span class="line">e2.detail(); <span class="comment">// => 102 Duke William</span></span><br></pre></td></tr></table></figure>
<p>When <code>new Employee(101, "Martin Roy")</code> is called. A new object is created. The <code>constructor</code> runs with the given argument and assigns <code>this.name</code> and <code>this.id</code> to it. Then we can call object methods, such as <code>e.detail()</code>.</p>
<p>What <code>class Employee{...}</code> construct really does is: Creates a function named <code>Employee</code>, that becomes the result of the class declaration. The function code is taken from the <code>constructor</code> method (assumed empty if we don’t write such method). Stores class methods, such as <code>detail()</code>, in <code>Employee.prototype</code>.</p>
<p>After <code>new User</code> object is created, when we call its methods, it’s taken from the prototype.</p>
<p>Note that no comma between class methods, A common pitfall for novice developers is to put a comma between class methods, which would result in a syntax error. </p>
<p>It is required to declare the class before invoking it.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//Here, we are invoking the class before declaring it. </span></span><br><span class="line"><span class="comment">// herer is error => Uncaught ReferenceError:Employee is not defined</span></span><br><span class="line"><span class="keyword">var</span> e1=<span class="keyword">new</span> Employee(<span class="number">101</span>,<span class="string">"Martin Roy"</span>); </span><br><span class="line"><span class="keyword">var</span> e2=<span class="keyword">new</span> Employee(<span class="number">102</span>,<span class="string">"Duke William"</span>); </span><br><span class="line">e1.detail(); <span class="comment">//calling method </span></span><br><span class="line">e2.detail(); </span><br><span class="line"> </span><br><span class="line"><span class="comment">//Declaring class </span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Employee</span> </span>{ </span><br><span class="line"> <span class="comment">//Initializing an object </span></span><br><span class="line"> <span class="keyword">constructor</span>(id,name) { </span><br><span class="line"> <span class="keyword">this</span>.id=id; </span><br><span class="line"> <span class="keyword">this</span>.name=name; </span><br><span class="line"> } </span><br><span class="line"> detail() { </span><br><span class="line"> <span class="built_in">document</span>.writeln(<span class="keyword">this</span>.id+<span class="string">" "</span>+<span class="keyword">this</span>.name+<span class="string">"<br>"</span>) </span><br><span class="line"> } </span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>Above code occur a error: Uncaught ReferenceError:Employee is not defined </p>
<p>A class can be declared once only. If we try to declare class more than one time,it throws an error.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//Declaring class </span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Employee</span> </span>{ </span><br><span class="line"></span><br><span class="line"> <span class="comment">//Initializing an object </span></span><br><span class="line"> <span class="keyword">constructor</span>(id,name) { </span><br><span class="line"> <span class="keyword">this</span>.id=id; </span><br><span class="line"> <span class="keyword">this</span>.name=name; </span><br><span class="line"> }</span><br><span class="line"> detail() { </span><br><span class="line"> <span class="built_in">document</span>.writeln(<span class="keyword">this</span>.id+<span class="string">" "</span>+<span class="keyword">this</span>.name+<span class="string">"<br>"</span>) </span><br><span class="line"> }</span><br><span class="line">} </span><br><span class="line"></span><br><span class="line"><span class="comment">//passing object to a variable </span></span><br><span class="line"><span class="keyword">var</span> e1=<span class="keyword">new</span> Employee(<span class="number">101</span>,<span class="string">"Martin Roy"</span>); </span><br><span class="line"><span class="keyword">var</span> e2=<span class="keyword">new</span> Employee(<span class="number">102</span>,<span class="string">"Duke William"</span>); </span><br><span class="line">e1.detail(); <span class="comment">//calling method </span></span><br><span class="line">e2.detail(); </span><br><span class="line"></span><br><span class="line"><span class="comment">//Re-declaring class </span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Employee</span> </span>{ } </span><br><span class="line"><span class="comment">// => Uncaught SyntaxError:Identifier 'Employee' has already been declared</span></span><br></pre></td></tr></table></figure>
<h3 id="Class-expressions-define-classes"><a href="#Class-expressions-define-classes" class="headerlink" title="Class expressions define classes"></a>Class expressions define classes</h3><p>Another way to define a class is by using a class expression. Here, it is not mandatory to assign the name of the class. So,the class expression can be named or unnamed. The class expression allows us to fetch the class name. However,this will not be possible with class declaration.</p>
<p>The class can be expressed without assigning any name to it.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> emp = <span class="class"><span class="keyword">class</span> </span>{ </span><br><span class="line"> <span class="keyword">constructor</span>(id, name) { </span><br><span class="line"> <span class="keyword">this</span>.id = id; </span><br><span class="line"> <span class="keyword">this</span>.name = name;</span><br><span class="line"> } </span><br><span class="line">}; </span><br><span class="line"><span class="built_in">document</span>.writeln(emp.name); <span class="comment">// => emp</span></span><br></pre></td></tr></table></figure>
<p>Unlike class declaration,the class expression allows us to re-declare the same class.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//Declaring class </span></span><br><span class="line"><span class="keyword">var</span> emp=<span class="class"><span class="keyword">class</span> </span>{ </span><br><span class="line"></span><br><span class="line"> <span class="comment">//Initializing an object </span></span><br><span class="line"> <span class="keyword">constructor</span>(id,name) { </span><br><span class="line"> <span class="keyword">this</span>.id=id; </span><br><span class="line"> <span class="keyword">this</span>.name=name; </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//Declaring method </span></span><br><span class="line"> detail() { </span><br><span class="line"> <span class="built_in">document</span>.writeln(<span class="keyword">this</span>.id+<span class="string">" "</span>+<span class="keyword">this</span>.name+<span class="string">"<br>"</span>) </span><br><span class="line"> } </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//passing object to a variable </span></span><br><span class="line"><span class="keyword">var</span> e1=<span class="keyword">new</span> emp(<span class="number">101</span>,<span class="string">"Martin Roy"</span>); <span class="comment">// => 101 Martin Roy</span></span><br><span class="line"><span class="keyword">var</span> e2=<span class="keyword">new</span> emp(<span class="number">102</span>,<span class="string">"Duke William"</span>); <span class="comment">// => 102 Duke William</span></span><br><span class="line">e1.detail(); <span class="comment">//calling method </span></span><br><span class="line">e2.detail(); </span><br><span class="line"> </span><br><span class="line"><span class="comment">//Re-declaring class </span></span><br><span class="line"><span class="keyword">var</span> emp=<span class="class"><span class="keyword">class</span> </span>{ </span><br><span class="line"></span><br><span class="line"> <span class="comment">//Initializing an object </span></span><br><span class="line"> <span class="keyword">constructor</span>(id,name) { </span><br><span class="line"> <span class="keyword">this</span>.id=id; </span><br><span class="line"> <span class="keyword">this</span>.name=name; </span><br><span class="line"> }</span><br><span class="line"> detail() { </span><br><span class="line"> <span class="built_in">document</span>.writeln(<span class="keyword">this</span>.id+<span class="string">" "</span>+<span class="keyword">this</span>.name+<span class="string">"<br>"</span>) </span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//passing object to a variable </span></span><br><span class="line"><span class="keyword">var</span> e1=<span class="keyword">new</span> emp(<span class="number">103</span>,<span class="string">"James Bella"</span>); <span class="comment">// => 103 James Bella</span></span><br><span class="line"><span class="keyword">var</span> e2=<span class="keyword">new</span> emp(<span class="number">104</span>,<span class="string">"Nick Johnson"</span>); <span class="comment">// => 104 Nick Johnson</span></span><br><span class="line">e1.detail(); <span class="comment">//calling method </span></span><br><span class="line">e2.detail();</span><br></pre></td></tr></table></figure>
<p>We can express the class with the particular name. Here,the scope of the class name is up to the class body. The class is retrieved using <code>class.name</code> property.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> emp = <span class="class"><span class="keyword">class</span> <span class="title">Employee</span> </span>{ </span><br><span class="line"> <span class="keyword">constructor</span>(id, name) { </span><br><span class="line"> <span class="keyword">this</span>.id = id; </span><br><span class="line"> <span class="keyword">this</span>.name = name; </span><br><span class="line"> } </span><br><span class="line">}; </span><br><span class="line"></span><br><span class="line"><span class="built_in">document</span>.writeln(emp.name); <span class="comment">// => Employee</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">document.writeln(Employee.name); </span></span><br><span class="line"><span class="comment">Error occurs on console: </span></span><br><span class="line"><span class="comment">"ReferenceError: Employee is not defined </span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<h3 id="Constructor-method"><a href="#Constructor-method" class="headerlink" title="Constructor method"></a>Constructor method</h3><p>Javascript constructor method is a special type of method which is used to initalize and create an object. it is called when memory is allocated for an object. The <code>constructor</code> keyword is used to declare a constructor method. The class can contain one constructor method only. Javascript allows us to used parent class constructor through <code>super</code> keyword.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">employee</span> </span>{ </span><br><span class="line"> <span class="keyword">constructor</span>() { </span><br><span class="line"> <span class="keyword">this</span>.id=<span class="number">101</span>; </span><br><span class="line"> <span class="keyword">this</span>.name = <span class="string">"martin roy"</span>; </span><br><span class="line"> } </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> emp = <span class="keyword">new</span> employee(); </span><br><span class="line"><span class="built_in">document</span>.writeln(emp.id+<span class="string">" "</span>+emp.name); <span class="comment">// => 101 martin roy</span></span><br></pre></td></tr></table></figure>
<p>the <code>super</code> keyword is used to call the parent class constructor.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">companyname</span> </span>{ </span><br><span class="line"> <span class="keyword">constructor</span>() { </span><br><span class="line"> <span class="keyword">this</span>.company=<span class="string">"javatpoint"</span>; </span><br><span class="line"> } </span><br><span class="line">} </span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">employee</span> <span class="keyword">extends</span> <span class="title">companyname</span> </span>{ </span><br><span class="line"> <span class="keyword">constructor</span>(id,name) { </span><br><span class="line"> <span class="keyword">super</span>(); </span><br><span class="line"> <span class="keyword">this</span>.id=id; </span><br><span class="line"> <span class="keyword">this</span>.name=name; </span><br><span class="line"> } </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> emp = <span class="keyword">new</span> employee(<span class="number">1</span>,<span class="string">"john"</span>); </span><br><span class="line"><span class="built_in">document</span>.writeln(emp.id+<span class="string">" "</span>+emp.name+<span class="string">" "</span>+emp.company); <span class="comment">// => 1 john javatpoint</span></span><br></pre></td></tr></table></figure>
<h3 id="Static-Method"><a href="#Static-Method" class="headerlink" title="Static Method"></a>Static Method</h3><p>The javascript provides static methods that belong to the class instead of an instance of that class. so,an instance is not required to call the static method. these methods are called directly on the class itself. The <code>static</code> keyword is used to declare a static method. The static method can be of any name. A class can contain more than one static method. If we declare more than one static method with a similar name,the javascript always invokes that last one. The static method can be used to create utility functions. We can use <code>this</code> keyword to call a static method within another static method. We cannot use <code>this</code> keyword directly to call a static method within the non-static method. In such case, we can call the static method either using the class name or as the property of the contructor.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">test</span> </span>{ </span><br><span class="line"> <span class="keyword">static</span> display() { </span><br><span class="line"> <span class="keyword">return</span> <span class="string">"static method is invoked"</span> </span><br><span class="line"> } </span><br><span class="line">} </span><br><span class="line"></span><br><span class="line"><span class="built_in">document</span>.writeln(test.display()); <span class="comment">// => static method is invoked</span></span><br></pre></td></tr></table></figure>
<p>more than one static method</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">test</span> </span>{ </span><br><span class="line"> <span class="keyword">static</span> display1() { </span><br><span class="line"> <span class="keyword">return</span> <span class="string">"static method is invoked"</span> </span><br><span class="line"> } </span><br><span class="line"> </span><br><span class="line"> <span class="keyword">static</span> display2() { </span><br><span class="line"> <span class="keyword">return</span> <span class="string">"static method is invoked again"</span> </span><br><span class="line"> } </span><br><span class="line">} </span><br><span class="line"><span class="built_in">document</span>.writeln(test.display1()+<span class="string">"<br>"</span>); <span class="comment">// => static method is invoked</span></span><br><span class="line"><span class="built_in">document</span>.writeln(test.display2()); <span class="comment">// => static method is invoked again</span></span><br></pre></td></tr></table></figure>
<p>more than one static method with similar names</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">test</span> </span>{ </span><br><span class="line"> <span class="keyword">static</span> display() { </span><br><span class="line"> <span class="keyword">return</span> <span class="string">"static method is invoked"</span> </span><br><span class="line"> } </span><br><span class="line"> <span class="keyword">static</span> display() { </span><br><span class="line"> <span class="keyword">return</span> <span class="string">"static method is invoked again"</span> </span><br><span class="line"> } </span><br><span class="line">} </span><br><span class="line"></span><br><span class="line"><span class="built_in">document</span>.writeln(test.display()); <span class="comment">// => static method is invoked again</span></span><br></pre></td></tr></table></figure>
<p>invoke a static method within the contructor</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">test</span> </span>{ </span><br><span class="line"> <span class="keyword">constructor</span>() { </span><br><span class="line"> <span class="built_in">document</span>.writeln(test.display()+<span class="string">"<br>"</span>); </span><br><span class="line"> <span class="built_in">document</span>.writeln(<span class="keyword">this</span>.constructor.display()); </span><br><span class="line"> } </span><br><span class="line"> </span><br><span class="line"> <span class="keyword">static</span> display() { </span><br><span class="line"> <span class="keyword">return</span> <span class="string">"static method is invoked"</span> </span><br><span class="line"> } </span><br><span class="line">} </span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> t=<span class="keyword">new</span> test();</span><br><span class="line"><span class="comment">// => static method is invoked</span></span><br><span class="line"><span class="comment">// => static method is invoked</span></span><br></pre></td></tr></table></figure>
<p>invoke a static method within te non-static method</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">test</span> </span>{ </span><br><span class="line"> <span class="keyword">static</span> display() { </span><br><span class="line"> <span class="keyword">return</span> <span class="string">"static method is invoked"</span> </span><br><span class="line"> } </span><br><span class="line"> </span><br><span class="line"> show() { </span><br><span class="line"> <span class="built_in">document</span>.writeln(test.display()+<span class="string">"<br>"</span>); </span><br><span class="line"> } </span><br><span class="line">} </span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> t=<span class="keyword">new</span> test(); </span><br><span class="line">t.show(); <span class="comment">// => static method is invoked</span></span><br></pre></td></tr></table></figure>
<h2 id="Augmenting-Classes"><a href="#Augmenting-Classes" class="headerlink" title="Augmenting Classes"></a>Augmenting Classes</h2><p>JavaScript’s prototype-based inheritance mechanism is dynamic: an object inherits properties from its prototype, even if the prototype changes after the object is created. This means that we can augment JavaScript classes simply by adding new methods to their prototype objects. The prototype object of built-in JavaScript classes is also “open” like this, which means that we can add methods to numbers, strings, arrays, functions, and so on.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Invoke the function f this many times, passing the iteration number </span></span><br><span class="line"><span class="comment">// For example, to print "hello" 3 times:</span></span><br><span class="line"><span class="comment">// var n = 3;</span></span><br><span class="line"><span class="comment">// n.times(function(n) { console.log(n + " hello"); });</span></span><br><span class="line"><span class="built_in">Number</span>.prototype.times = <span class="function"><span class="keyword">function</span>(<span class="params">f, context</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> n = <span class="built_in">Number</span>(<span class="keyword">this</span>);</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> i = <span class="number">0</span>; i < n; i++) f.call(context, i); </span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">// Define the ES5 String.trim() method if one does not already exist.</span></span><br><span class="line"><span class="comment">// This method returns a string with whitespace removed from the start and end. </span></span><br><span class="line"><span class="built_in">String</span>.prototype.trim = <span class="built_in">String</span>.prototype.trim || <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">this</span>) <span class="keyword">return</span> <span class="keyword">this</span>; <span class="comment">// Don't alter the empty string</span></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.replace(<span class="regexp">/^\s+|\s+$/g</span>, <span class="string">""</span>); <span class="comment">// Regular expression magic </span></span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">// Return a function's name. If it has a (nonstandard) name property, use it.</span></span><br><span class="line"><span class="comment">// Otherwise, convert the function to a string and extract the name from that. // Returns an empty string for unnamed functions like itself. </span></span><br><span class="line"><span class="built_in">Function</span>.prototype.getName = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.name || <span class="keyword">this</span>.toString().match(<span class="regexp">/function\s*([^(]*)\(/</span>)[<span class="number">1</span>]; </span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>It is possible to add methods to <code>Object.prototype</code>, making them available on all objects. This is not recommended, however, because prior to ECMAScript 5, there is no way to make these add-on methods nonenumerable, and if you add properties to <code>Object.prototype</code>, those properties will be reported by all <code>for/in</code> loops. We can use ECMAScript 5 method <code>Object.defineProperty()</code> to safely augment <code>Object.prototype</code>.</p>
<p>It is implementation-dependent whether classes defined by the host environment (such as the web browser) can be augmented in this way. In many web browsers, for example, you can add methods to <code>HTMLElement.prototype</code> and those methods will be inherited by the objects that represent the HTML tags in the current document. This does not work in current versions of Microsoft’s Internet Explorer, however, which severely limits the utility of this technique for client-side programming.</p>
<h2 id="Classes-and-Types"><a href="#Classes-and-Types" class="headerlink" title="Classes and Types"></a>Classes and Types</h2><p>The <code>typeof</code> operator allows us to distinguish among these types. Often, however, it is useful to treat class as its own type and to be able to distinguish objects based on their class. The built-in objects of core JavaScript (and often the host objects of client-side JavaScript) can be distinguished on the basis of their <code>class</code> attribute using code like the <code>classof()</code> function.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">classof</span>(<span class="params">o</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (o === <span class="literal">null</span>) <span class="keyword">return</span> <span class="string">"Null"</span>;</span><br><span class="line"> <span class="keyword">if</span> (o === <span class="literal">undefined</span>) <span class="keyword">return</span> <span class="string">"Undefined"</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.toString.call(o).slice(<span class="number">8</span>,<span class="number">-1</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>But when we define our own classes, the instance objects always have a <code>class</code> attribute of “Object”, so the <code>classof()</code> function doesn’t help here.</p>
<p>The three techniques for determining the class of an arbitrary object: the <code>instanceof</code> operator: the <code>constructor</code> property, and the name of the constructor function. None of these techniques is entirely satisfactory, however, and the section concludes with a discussion of duck-typing, a programming philosophy that focuses on what an object can do (what methods it has) rather than what its class is.</p>
<h3 id="The-instanceof-operator"><a href="#The-instanceof-operator" class="headerlink" title="The instanceof operator"></a>The instanceof operator</h3><p>The left-hand of <code>instanceof</code> operand should be the object whose class is begin tested, and the right-hand operand should be a constructor function that names a class. The expressions <code>o instanceof c</code> evaluates to <code>true</code> if <code>o</code> inherits from <code>c.prototype</code>. The inheritance need not be direct. If <code>o</code> inherits from an object that inherits from an object that inherits from <code>c.prototype</code>, the expression will still evaluate to <code>true</code>.</p>
<p>Constructors act as the public identity of classes, but prototypes are the fundamental identity. Despite the use of a constructor function with <code>instanceof</code>, this operator is really testing what an object inherits from, not what constructor was used to create it.</p>
<p>If you want to test the prototype chain of an object for a specific prototype object and do not want to use the constructor function as an intermediary, you can use the <code>isPrototypeOf()</code> method.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">range.methods.isPrototypeOf(r); <span class="comment">// range.methods is the prototype object.</span></span><br></pre></td></tr></table></figure>
<p>One shortcoming of the <code>instanceof</code> operator and the <code>isPrototypeOf()</code> method is that they do not allow us to query the class of an object, only to test an object against a class we specify. A more serious shortcoming arises in client-side JavaScript where a web application uses more than one window or frame. Each window or frame is a distinct execution context, and each has its own global object and its own set of constructor functions. Two arrays created in two different frames inherit from two identical but distinct prototype objects, and an array created in one frame is not <code>instanceof</code> the <code>Array()</code> constructor of another frame.</p>
<h3 id="The-constructor-proeperty"><a href="#The-constructor-proeperty" class="headerlink" title="The constructor proeperty"></a>The constructor proeperty</h3><p>Another way to identify the class of an object is to simply use the <code>constructor</code> property. Since constructors are the public face of classes, this is a straightforward approach. For example:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">typeAndValue</span>(<span class="params">x</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (x == <span class="literal">null</span>) <span class="keyword">return</span> <span class="string">""</span>; <span class="comment">// Null and undefined don't have constructors </span></span><br><span class="line"> <span class="keyword">switch</span>(x.constructor) {</span><br><span class="line"> <span class="keyword">case</span> <span class="built_in">Number</span>: <span class="keyword">return</span> <span class="string">"Number: "</span> + x; <span class="comment">// Works for primitive types </span></span><br><span class="line"> <span class="keyword">case</span> <span class="built_in">String</span>: <span class="keyword">return</span> <span class="string">"String: '"</span> + x + <span class="string">"'"</span>; </span><br><span class="line"> <span class="keyword">case</span> <span class="built_in">Date</span>: <span class="keyword">return</span> <span class="string">"Date: "</span> + x; <span class="comment">// And for built-in types</span></span><br><span class="line"> <span class="keyword">case</span> <span class="built_in">RegExp</span>: <span class="keyword">return</span> <span class="string">"Regexp: "</span> + x;</span><br><span class="line"> <span class="keyword">case</span> Complex: <span class="keyword">return</span> <span class="string">"Complex: "</span> + x; <span class="comment">// And for user-defined types</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>Note that the expressions following the <code>case</code> keyword in the code above are functions. If we were using the <code>typeof</code> operator or extracting the <code>class</code> attribute of the object, they would be strings instead.</p>
<p>This technique of using the <code>constructor</code> property is subject to the same problem as <code>instanceof</code>. It won’t always work when there are multiple execution contexts (such as multiple frame in a browser window) that share values. In this situation, each frame has its own set of constructor functions: the <code>Array</code> constructor in one frame is not the same as the <code>Array</code> constructor in another frame.</p>
<p>Also, JavaScript does not require that every object have a <code>constructor</code> property: this is a convention based on the default prototype object created for each function, but it is easy to accidentally or intentionally omit the <code>constructor</code> property on the prototype.</p>
<h3 id="The-Constructor-Name"><a href="#The-Constructor-Name" class="headerlink" title="The Constructor Name"></a>The Constructor Name</h3><p>The main problem with using the <code>instanceof</code> operator or the <code>constructor</code> property for determining the class of an object occurs when there are multiple execution contexts and thus multiple copies of the constructor functions. These functions may well be identical, but they are distinct objects and are therefore not equal to each other.</p>
<p>One possible workaround is to use the name of the constructor function as the class identifier rather than the function itself. The <code>Array</code> constructor is one window is not equal to the <code>Array</code> constructor in another window, but their names are equal. Some JavaScript implementations make the name of a function available through a nonstandard <code>name</code> property of the function object. For implementations without a <code>name</code> property, we can convert the function to a string and extract the name from that.</p>
<h2 id="Encapsulation"><a href="#Encapsulation" class="headerlink" title="Encapsulation"></a>Encapsulation</h2><p>Javascript encapsulation is a process of binding the data (i.e. variables) with the functions acting on that data. it allows us to control the data and validate it. To achieve an encapsulation in javascript: use <code>var</code> keyword to make data members private. use setter methods to set the data and getter methods to get that data. The encapsulation allows us to handle an object using the following properties: <code>read/write</code> – we use setter methods to write the data and and getter methods read that data; <code>read only</code> – we use getter methods only; <code>write only</code> – we use setter methods only.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">student</span> </span>{ </span><br><span class="line"> <span class="keyword">constructor</span>() { </span><br><span class="line"> <span class="keyword">var</span> name; </span><br><span class="line"> <span class="keyword">var</span> marks; </span><br><span class="line"> } </span><br><span class="line"> getname() { </span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.name; </span><br><span class="line"> } </span><br><span class="line"> setname(name) { </span><br><span class="line"> <span class="keyword">this</span>.name=name; </span><br><span class="line"> } </span><br><span class="line"> getmarks() { </span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.marks; </span><br><span class="line"> } </span><br><span class="line"> setmarks(marks) { </span><br><span class="line"> <span class="keyword">this</span>.marks=marks; </span><br><span class="line"> } </span><br><span class="line">} </span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> stud=<span class="keyword">new</span> student(); </span><br><span class="line">stud.setname(<span class="string">"john"</span>); </span><br><span class="line">stud.setmarks(<span class="number">80</span>); </span><br><span class="line"><span class="built_in">document</span>.writeln(stud.getname()+<span class="string">" "</span>+stud.getmarks()); <span class="comment">// => john 80</span></span><br></pre></td></tr></table></figure>
<p>we validate the marks of the student.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">student</span> </span>{ </span><br><span class="line"> <span class="keyword">constructor</span>() { </span><br><span class="line"> <span class="keyword">var</span> name; </span><br><span class="line"> <span class="keyword">var</span> marks; </span><br><span class="line"> } </span><br><span class="line"> getname() { </span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.name; </span><br><span class="line"> } </span><br><span class="line"> setname(name) { </span><br><span class="line"> <span class="keyword">this</span>.name=name; </span><br><span class="line"> } </span><br><span class="line"> getmarks() { </span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.marks; </span><br><span class="line"> } </span><br><span class="line"> setmarks(marks) { </span><br><span class="line"> <span class="keyword">if</span>(marks<<span class="number">0</span>||marks><span class="number">100</span>) { </span><br><span class="line"> alert(<span class="string">"invalid marks"</span>); </span><br><span class="line"> } <span class="keyword">else</span> { </span><br><span class="line"> <span class="keyword">this</span>.marks=marks; </span><br><span class="line"> } </span><br><span class="line"> } </span><br><span class="line">} </span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> stud=<span class="keyword">new</span> student(); </span><br><span class="line">stud.setname(<span class="string">"john"</span>); </span><br><span class="line">stud.setmarks(<span class="number">110</span>);<span class="comment">//alert() invokes </span></span><br><span class="line"><span class="built_in">document</span>.writeln(stud.getname()+<span class="string">" "</span>+stud.getmarks()); <span class="comment">// => john undefined</span></span><br></pre></td></tr></table></figure>
<h2 id="Inheritance"><a href="#Inheritance" class="headerlink" title="Inheritance"></a>Inheritance</h2><p>Javascript inheritance is a mechanism that allows us to create new classes on the basis of already existing classes. it provides flexibility to the child class to reuse the methods and variables of a parent class.</p>
<p>Javascript <code>extends</code> keyword is used to create a child class on the basis of parent class. it facilitates child class to acquire all the properties and behavior of its parent class. It maintains an <code>is-a</code> relationship. The <code>extends</code> keyword is used in class expressions or class declarations. We can also use a prototype-based approach to achieve inheritance.</p>
<p>We extends <code>date</code> object to display today’s date.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">moment</span> <span class="keyword">extends</span> <span class="title">date</span> </span>{</span><br><span class="line"> <span class="keyword">constructor</span>() {</span><br><span class="line"> <span class="keyword">super</span>();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> m=<span class="keyword">new</span> moment();</span><br><span class="line"><span class="built_in">document</span>.writeln(<span class="string">"current date:"</span>);</span><br><span class="line"><span class="built_in">document</span>.writeln(m.getdate()+<span class="string">"-"</span>+(m.getmonth()+<span class="number">1</span>)+<span class="string">"-"</span>+m.getfullyear()); <span class="comment">// => current date:4-9-2020</span></span><br></pre></td></tr></table></figure>
<p>display the year value from the given date</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">moment</span> <span class="keyword">extends</span> <span class="title">date</span> </span>{ </span><br><span class="line"> <span class="keyword">constructor</span>(year) { </span><br><span class="line"> <span class="keyword">super</span>(year); </span><br><span class="line"> }</span><br><span class="line">} </span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> m=<span class="keyword">new</span> moment(<span class="string">"august 15, 1947 20:22:10"</span>); </span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">"year value:"</span>, m.getfullyear()) <span class="comment">// => year value:1947</span></span><br></pre></td></tr></table></figure>
<p>We declare sub-class that extends the properties of its parent class.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">bike</span> </span>{ </span><br><span class="line"> <span class="keyword">constructor</span>() { </span><br><span class="line"> <span class="keyword">this</span>.company=<span class="string">"honda"</span>; </span><br><span class="line"> } </span><br><span class="line">} </span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">vehicle</span> <span class="keyword">extends</span> <span class="title">bike</span> </span>{ </span><br><span class="line"> <span class="keyword">constructor</span>(name,price) { </span><br><span class="line"> <span class="keyword">super</span>(); </span><br><span class="line"> <span class="keyword">this</span>.name=name; </span><br><span class="line"> <span class="keyword">this</span>.price=price; </span><br><span class="line"> } </span><br><span class="line">} </span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> v = <span class="keyword">new</span> vehicle(<span class="string">"shine"</span>,<span class="string">"70000"</span>); </span><br><span class="line"><span class="built_in">console</span>.log(v.company+<span class="string">" "</span>+v.name+<span class="string">" "</span>+v.price); <span class="comment">// => honda shine 70000</span></span><br></pre></td></tr></table></figure>
<h1 id="Module"><a href="#Module" class="headerlink" title="Module"></a>Module</h1><p>An important reason to organize code into classes is to make that code more <code>modular</code> and suitable for reuse in a variety of situations. Classes are not the only kind of modular code, however. Typically, a module is a single file of JavaScript code. A module file might contain a class definition, a set of related classes, a library of utility functions, or just a script of code to execute. Any chunk of JavaScript code can be a module, as long as it is written in a modular way. </p>
<p>In recent years to start thinking about providing mechanisms for splitting JavaScript programs up into separate modules that can be imported when needed. Node.js has has this ability for a long time, and there are a number of JavaScript and framework that enable module usage (for example, other <a href="https://en.wikipedia.org/wiki/CommonJS" target="_blank" rel="noopener">CommonJS</a> and <a href="https://github.com/amdjs/amdjs-api/blob/master/AMD.md" target="_blank" rel="noopener">AMD</a>-based module systems like <a href="https://requirejs.org/" target="_blank" rel="noopener">ReuqireJS</a>, and more recently <a href="https://webpack.github.io/" target="_blank" rel="noopener">Webpack</a> and <a href="https://babeljs.io/" target="_blank" rel="noopener">Babel</a>). Both the Dojo toolkit and Google’s Closure library, for example, define <code>provide()</code> and <code>require()</code> functions for declaring and loading modules. And the CommonJS server-side JavaScript standardization effort (see <a href="http://commonjs.org" target="_blank" rel="noopener">http://commonjs.org</a>) has created a modules specification that also uses a <code>require()</code> function. Module systems like this often handle module loading and dependency management for you and are beyond the scope of this discussion. If you use one of these frameworks, then you should use and define modules following the conventions appropriate to that framework.</p>
<p>The goal of modules is to allow large programs to be assembled using code from disparate sources, and for all of that code to run correctly even in the presence of code that the module authors did not anticipate. In order for this to work, the various modules must avoid altering the global execution environment, so that subsequent modules are allowed to run in the pristine (or near pristine) environment that it expects. As a practical matter, this means that modules should minimize the number of global symbols they define – ideally, no module should define more than one.</p>
<h2 id="exporting-module-features"><a href="#exporting-module-features" class="headerlink" title="exporting module features"></a>exporting module features</h2><p>The first thing you to get access to module features is export them. This is done using the <code>export</code> statement.</p>
<p>The easiest way to use it is to place it front of any items you want exported out of the moduels, for example:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> name = <span class="string">'square'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="function"><span class="keyword">function</span> <span class="title">draw</span>(<span class="params">ctx, length, x, y, color</span>) </span>{</span><br><span class="line"> ctx.fillStyle = color;</span><br><span class="line"> ctx.fillRect(x, y, length, length);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> length: length,</span><br><span class="line"> x: x,</span><br><span class="line"> y: y,</span><br><span class="line"> color: color</span><br><span class="line"> };</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>You can export functions, <code>var</code>, <code>let</code>, <code>const</code>, and classes. They need to be top-level items; you can’t use <code>export</code> inside a function, for example.</p>
<p>A more convenient way of exporting all the items you want to export is to use a single export statement at the end of your module file, followed by a comma-separated list of the features you want to export wrapped in curly braces. For example:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> { name, draw, reportArea, reportPerimeter };</span><br></pre></td></tr></table></figure>
<h2 id="Importing-features-into-your-script"><a href="#Importing-features-into-your-script" class="headerlink" title="Importing features into your script"></a>Importing features into your script</h2><p>Once you’ve exported some features out of your module, you need to import them into your script to be able to use them. The simplest way to do this is as follows:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { name, draw, reportArea, reportPerimeter } <span class="keyword">from</span> <span class="string">'./modules/square.js'</span>;</span><br></pre></td></tr></table></figure>
<p>You use the <code>import</code> statement, follwed by a comma-separated list of the features you want to import wrapped in curly braces, followed by the keyword <code>from</code>, followed by the path to the module file – a path relative to the site root.</p>
<p>However, we’ve written the path a bit differently – we are using the dot <code>.</code> syntax to mean “the current location”, followed by the path beyond that to the file we are trying to find. This is much better than writing out the entire relative path each time, as it is shorter, and it makes the URL portable – the example will still work if you move it to a different location in the site hierarchy.</p>
<blockquote>
<p>In some module systems, you can omit the file extension and the dot (e.g. <code>/modules/square</code>). This doesn’t work in native JavaScript modules.</p>
</blockquote>
<p>Once you’ve imported the features into your script, you can use them just like they were defined inside the same file.</p>
<blockquote>
<p>Althought imported features are available in the file, they are read only views of the feature that was exported. You cannot change the variable that was imported, but you can still modify properties similar to <code>const</code>. Additionally, these features are imported as live bindings, meaning that they can change in value even if you cannot modify the binding unlike <code>const</code>.</p>
</blockquote>
<h2 id="Applying-the-module-to-your-HTML"><a href="#Applying-the-module-to-your-HTML" class="headerlink" title="Applying the module to your HTML"></a>Applying the module to your HTML</h2><p>Now we just need to apply the <code>main.js</code> module to our HTML page. This is very similar to how we apply a regular script to a page, with a few notable differences. </p>
<p>First of all, you need to include <code>type=module</code> in the <code><script></code> element, to declare this script as a module:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><script type=<span class="string">"module"</span> src=<span class="string">"main.js"</span>><<span class="regexp">/script></span></span><br></pre></td></tr></table></figure>
<p>The script into which you import the module features basically acts as the top-level module. If you omit it, Firefox, for example gives you an error of “SyntaxError: import declarations may only appear at top level of a module”.</p>
<p>You can only use <code>import</code> and <code>export</code> statements inside modules; not regular scripts.</p>
<blockquote>
<p>You can also import modules into internal scripts, as long as you include <code>type="module"</code>, for example <code><script type="module"> // include script here </script></code>.</p>
</blockquote>
<h2 id="Other-differences-between-modules-and-standard-scripts"><a href="#Other-differences-between-modules-and-standard-scripts" class="headerlink" title="Other differences between modules and standard scripts"></a>Other differences between modules and standard scripts</h2><ul>
<li><p>You need to pay attention to local testing – if you try to load the HTML file locally (i.e. with a <code>file://</code> URL), you’ll run into CORS error due to JavaScript module security requirements. You need to do your testing through a server.</p>
</li>
<li><p>Also, note that you might get different behavior from sections of script defined inside modules as opposed to in standard script. This is because modules use strict mode automatically.</p>
</li>
<li><p>There is no need to use the <code>defer</code> attribute (see <code><script> attributes</code>) when loading a module script; modules are deerred automatically.</p>
</li>
<li><p>Modules are only executed once, even if they have been referenced in multiple <code><script></code> tags.</p>
</li>
<li><p>Last but not least, let’s make this clear — module features are imported into the scope of a single script — they aren’t available in the global scope. Therefore, you will only be able to access imported features in the script they are imported into, and you won’t be able to access them from the JavaScript console, for example. You’ll still get syntax errors shown in the DevTools, but you’ll not be able to use some of the debugging techniques you might have expected to use.</p>
</li>
</ul>
<h2 id="Default-exports-versus-named-exports"><a href="#Default-exports-versus-named-exports" class="headerlink" title="Default exports versus named exports"></a>Default exports versus named exports</h2><p>The functionality we’ve exported so far has been comprised of named exports – each item (be it a function, <code>const</code>, etc.) has been referred to by its name export, and that name has been used to refer to it on import as well.</p>
<p>There is also a type of export called the <code>default export</code> – this is designed to make it easy to have a default function provided by a module, and also helps JavaScript modules to interoperate with existing CommonJS and AMD module systems.</p>
<p>Let’s look at an example as we explain how it works. In <code>square.js</code> have a function called <code>randomSquare()</code> that creates a square with a random color, size, and position. We want to export this as our default, so at the bottom of the file we write this:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> randomSquare;</span><br></pre></td></tr></table></figure>
<p>Note the lack of curly braces.</p>
<p>We could instead prepend <code>export default</code> onto the function and define it as an anonymous function, like this:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="function"><span class="keyword">function</span>(<span class="params">ctx</span>) </span>{</span><br><span class="line"> ...</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>Over in our <code>main.js</code> file, we import the default function using this line:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> randomSquare <span class="keyword">from</span> <span class="string">'./modules/square.js'</span>;</span><br></pre></td></tr></table></figure>
<p>Again, not the lack of curly braces. This is because there is only one default export allowed per module, and we know that <code>randomSquare</code> is it. The above line is basically shorthand for:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> {<span class="keyword">default</span> <span class="keyword">as</span> randomSquare} <span class="keyword">from</span> <span class="string">'./modules/square.js'</span>;</span><br></pre></td></tr></table></figure>
<h2 id="Renaming-imports-and-exports"><a href="#Renaming-imports-and-exports" class="headerlink" title="Renaming imports and exports"></a>Renaming imports and exports</h2><p>Inside your <code>import</code> and <code>export</code> statment’s curly braces, you can use the keyword <code>as</code> along with a new feature name, to change the identifying name you will use for a feature inside the top-level module.</p>
<p>So for example, both of the following would do the same job:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// inside module.js</span></span><br><span class="line"><span class="keyword">export</span> {</span><br><span class="line"> function1 <span class="keyword">as</span> newFunctionName,</span><br><span class="line"> function2 <span class="keyword">as</span> anotherNewFunctionName</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">// inside main.js</span></span><br><span class="line"><span class="keyword">import</span> { newFunctionName, anotherNewFunctionName } <span class="keyword">from</span> <span class="string">'./modules/module.js'</span>;</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// inside module.js</span></span><br><span class="line"><span class="keyword">export</span> { function1, function2 };</span><br><span class="line"></span><br><span class="line"><span class="comment">// inside main.js</span></span><br><span class="line"><span class="keyword">import</span> { function1 <span class="keyword">as</span> newFunctionName,</span><br><span class="line"> function2 <span class="keyword">as</span> anotherNewFunctionName } <span class="keyword">from</span> <span class="string">'./modules/module.js'</span>;</span><br></pre></td></tr></table></figure>
<p>Let’s look at a real example. In out renaming directory you’ll see the same module system as in the previous example, except that we’ve added <code>cricle.js</code> and <code>triangle.js</code> modules to draw and report on circles and triangles.</p>
<p>Inside each of these modules, we’ve got features with the same names being exported, and therefore each has the same <code>export</code> statement at the bottom:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> { name, draw, reportArea, reportPerimeter };</span><br></pre></td></tr></table></figure>
<p>When importing these into <code>main.js</code>, if we tried to use</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { name, draw, reportArea, reportPerimeter } <span class="keyword">from</span> <span class="string">'./modules/square.js'</span>;</span><br><span class="line"><span class="keyword">import</span> { name, draw, reportArea, reportPerimeter } <span class="keyword">from</span> <span class="string">'./modules/circle.js'</span>;</span><br><span class="line"><span class="keyword">import</span> { name, draw, reportArea, reportPerimeter } <span class="keyword">from</span> <span class="string">'./modules/triangle.js'</span>;</span><br></pre></td></tr></table></figure>
<p>The browser would throw an error such as “SyntaxError: Redeclaration of import name”(Firefox).</p>
<p>Instead we need to rename the imports so that they are unique:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { name <span class="keyword">as</span> squareName,</span><br><span class="line"> draw <span class="keyword">as</span> drawSquare,</span><br><span class="line"> reportArea <span class="keyword">as</span> reportSquareArea,</span><br><span class="line"> reportPerimeter <span class="keyword">as</span> reportSquarePerimeter } <span class="keyword">from</span> <span class="string">'./modules/square.js'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> { name <span class="keyword">as</span> circleName,</span><br><span class="line"> draw <span class="keyword">as</span> drawCircle,</span><br><span class="line"> reportArea <span class="keyword">as</span> reportCircleArea,</span><br><span class="line"> reportPerimeter <span class="keyword">as</span> reportCirclePerimeter } <span class="keyword">from</span> <span class="string">'./modules/circle.js'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> { name <span class="keyword">as</span> triangleName,</span><br><span class="line"> draw <span class="keyword">as</span> drawTriangle,</span><br><span class="line"> reportArea <span class="keyword">as</span> reportTriangleArea,</span><br><span class="line"> reportPerimeter <span class="keyword">as</span> reportTrianglePerimeter } <span class="keyword">from</span> <span class="string">'./modules/triangle.js'</span>;</span><br></pre></td></tr></table></figure>
<p>Note that you could solve the problem in the module files instead, e.g.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// in square.js</span></span><br><span class="line"><span class="keyword">export</span> { name <span class="keyword">as</span> squareName,</span><br><span class="line"> draw <span class="keyword">as</span> drawSquare,</span><br><span class="line"> reportArea <span class="keyword">as</span> reportSquareArea,</span><br><span class="line"> reportPerimeter <span class="keyword">as</span> reportSquarePerimeter };</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// in main.js</span></span><br><span class="line"><span class="keyword">import</span> { squareName, drawSquare, reportSquareArea, reportSquarePerimeter } <span class="keyword">from</span> <span class="string">'./modules/square.js'</span>;</span><br></pre></td></tr></table></figure>
<p>And it would work just the same. What style you use is up to you, however it arguably makes more sense to leave your module code alone, and make the changes in the imports. This especially makes sense when you are importing from third party modules that you don’t have any control over.</p>
<h2 id="Creating-a-module-object"><a href="#Creating-a-module-object" class="headerlink" title="Creating a module object"></a>Creating a module object</h2><p>The above method works OK, but it’s a little messy and longwinded. An even better solution is to import each module’s features inside a module object. The following syntax form does that:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> Module <span class="keyword">from</span> <span class="string">'./modules/module.js'</span>;</span><br></pre></td></tr></table></figure>
<p>This grabs all the exports available inside <code>module.js</code>, and makes them available as members of an object <code>Module</code>, effectively giving it its own namespace. So for example:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Module.function1()</span><br><span class="line">Module.function2()</span><br><span class="line">etc.</span><br></pre></td></tr></table></figure>
<p>In the modules, the exports are all in the following simple form:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> { name, draw, reportArea, reportPerimeter };</span><br></pre></td></tr></table></figure>
<p>The imports on the other hand look like this:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> Canvas <span class="keyword">from</span> <span class="string">'./modules/canvas.js'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> Square <span class="keyword">from</span> <span class="string">'./modules/square.js'</span>;</span><br><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> Circle <span class="keyword">from</span> <span class="string">'./modules/circle.js'</span>;</span><br><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> Triangle <span class="keyword">from</span> <span class="string">'./modules/triangle.js'</span>;</span><br></pre></td></tr></table></figure>
<p>In each case, you can now access the module’s imports underneath the specified object name, for example:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> square1 = Square.draw(myCanvas.ctx, <span class="number">50</span>, <span class="number">50</span>, <span class="number">100</span>, <span class="string">'blue'</span>);</span><br><span class="line">Square.reportArea(square1.length, reportList);</span><br><span class="line">Square.reportPerimeter(square1.length, reportList);</span><br></pre></td></tr></table></figure>
<p>So you can now write the code just the same as before (as long as you include the object names where needed), and the imports are much neater.</p>
<h2 id="Modules-and-classes"><a href="#Modules-and-classes" class="headerlink" title="Modules and classes"></a>Modules and classes</h2><p>You can also export and import classes; this is another option for avoiding conflicts in your code, and is easpecially useful if you’ve already got your module code written in an object-oriented style.</p>
<p>You can see an example of our shape drawing modules rewritten with ES classes in our <a href="https://github.com/mdn/js-examples/tree/master/modules/classes" target="_blank" rel="noopener">classes</a> directory. As an example, the <code>square.js</code> file now contains all its functionality in a single class:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Square</span> </span>{</span><br><span class="line"> <span class="keyword">constructor</span>(ctx, listId, length, x, y, color) {</span><br><span class="line"> ...</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> draw() {</span><br><span class="line"> ...</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> ...</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> { Square };</span><br></pre></td></tr></table></figure>
<p>Over in <code>main.js</code>, we import it like this:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { Square } <span class="keyword">from</span> <span class="string">'./modules/square.js'</span>;</span><br></pre></td></tr></table></figure>
<p>And then use the class to draw our square:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> square1 = <span class="keyword">new</span> Square(myCanvas.ctx, myCanvas.listId, <span class="number">50</span>, <span class="number">50</span>, <span class="number">100</span>, <span class="string">'blue'</span>);</span><br><span class="line">square1.draw();</span><br><span class="line">square1.reportArea();</span><br><span class="line">square1.reportPerimeter();</span><br></pre></td></tr></table></figure>
<h2 id="Aggregating-modules"><a href="#Aggregating-modules" class="headerlink" title="Aggregating modules"></a>Aggregating modules</h2><p>There will be times where you’ll want to aggregate modules together. You might have multiple levels of dependencies, where you want to simplify things, combining several submodules into one parent modules. This is possible using export syntax of the following forms in the parent modules:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> * <span class="keyword">from</span> <span class="string">'x.js'</span></span><br><span class="line"><span class="keyword">export</span> { name } <span class="keyword">from</span> <span class="string">'x.js'</span></span><br></pre></td></tr></table></figure>
<p>For an example, see our <a href="https://github.com/mdn/js-examples/tree/master/modules/module-aggregation" target="_blank" rel="noopener">module-aggregation</a> directory. In this example (based on our earlier classes example) we’ve got an extra modules called <code>shapes.js</code>, which aggregates all the functionality from <code>circle.js</code>, <code>square.js</code>, and <code>triangle.js</code> together. We’ve also moved our submodules inside a subdirectory inside the <code>moduels</code> directory called <code>shapes</code>. So the modules structure in this example is:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">modules/</span><br><span class="line"> canvas.js</span><br><span class="line"> shapes.js</span><br><span class="line"> shapes/</span><br><span class="line"> circle.js</span><br><span class="line"> square.js</span><br><span class="line"> triangle.js</span><br></pre></td></tr></table></figure>
<p>In each of the submodules, the export is of the same form, e.g.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> { Square };</span><br></pre></td></tr></table></figure>
<p>Next up comes the aggregation part. Inside <code>shapes.js</code>, we include the following lines:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> { Square } <span class="keyword">from</span> <span class="string">'./shapes/square.js'</span>;</span><br><span class="line"><span class="keyword">export</span> { Triangle } <span class="keyword">from</span> <span class="string">'./shapes/triangle.js'</span>;</span><br><span class="line"><span class="keyword">export</span> { Circle } <span class="keyword">from</span> <span class="string">'./shapes/circle.js'</span>;</span><br></pre></td></tr></table></figure>
<p>These grab the exports from the individual submodules and effectively make them available from the <code>shapes.js</code> module.</p>
<blockquote>
<p>The exports referenced in <code>shapes.js</code> basically get redirected through the file and don’t really exist there, so you won’t be able to write any useful related code inside the same file.</p>
</blockquote>
<p>So now in the <code>main.js</code> file, we can get access to all three module classes by replacing</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { Square } <span class="keyword">from</span> <span class="string">'./modules/square.js'</span>;</span><br><span class="line"><span class="keyword">import</span> { Circle } <span class="keyword">from</span> <span class="string">'./modules/circle.js'</span>;</span><br><span class="line"><span class="keyword">import</span> { Triangle } <span class="keyword">from</span> <span class="string">'./modules/triangle.js'</span>;</span><br></pre></td></tr></table></figure>
<p>with the following single line:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { Square, Circle, Triangle } <span class="keyword">from</span> <span class="string">'./modules/shapes.js'</span>;</span><br></pre></td></tr></table></figure>
<h2 id="Dynamic-module-loading"><a href="#Dynamic-module-loading" class="headerlink" title="Dynamic module loading"></a>Dynamic module loading</h2><p>The newest part of the JavaScript modules functionality to be available in browsers is dynamic module loading. This allows you to dynamically load modules only when they are needed, rather than having to load everything up front. This has some obvious performance advantages; let’s read on and see how it works.</p>
<p>This new functionality allows you to call <code>import()</code> as a function, passing it the path to the modules as a parameter. It returns a <code>Promise</code>, which fulfills with a modules object giving you access to that object’s exports, e.g.</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span>(<span class="string">'./modules/myModule.js'</span>)</span><br><span class="line"> .then(<span class="function">(<span class="params"><span class="built_in">module</span></span>) =></span> {</span><br><span class="line"> <span class="comment">// Do something with the module.</span></span><br><span class="line"> });</span><br></pre></td></tr></table></figure>
<p>Let’s look at an example. In the <a href="https://github.com/mdn/js-examples/tree/master/modules/dynamic-module-imports" target="_blank" rel="noopener">dynamic-module-imports</a> directory we’ve got another example based on our classes example. This time however we are not drawing anything on the canvas when the example loads. Instead, we include three buttons – “Circle”, “Square”, and “Triangle” – that, when pressed, dynamically load the required module and then use it to draw the associated shape.</p>
<p>In this example we’ve only made changes to our <code>index.html</code> and <code>main.js</code> file – the module exports remain the same as before.</p>
<p>Over in <code>main.js</code> we’ve grabbed a reference to each button using a <code>Document.querySelector()</code> call, for example:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> squareBtn = <span class="built_in">document</span>.querySelector(<span class="string">'.square'</span>);</span><br></pre></td></tr></table></figure>
<p>We then attach an event listener to each button so that when pressed, the relevant modules is dynamically loaded and used to draw the shape:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">squareBtn.addEventListener(<span class="string">'click'</span>, () => {</span><br><span class="line"> <span class="keyword">import</span>(<span class="string">'./modules/square.js'</span>).then(<span class="function">(<span class="params">Module</span>) =></span> {</span><br><span class="line"> <span class="keyword">let</span> square1 = <span class="keyword">new</span> Module.Square(myCanvas.ctx, myCanvas.listId, <span class="number">50</span>, <span class="number">50</span>, <span class="number">100</span>, <span class="string">'blue'</span>);</span><br><span class="line"> square1.draw();</span><br><span class="line"> square1.reportArea();</span><br><span class="line"> square1.reportPerimeter();</span><br><span class="line"> })</span><br><span class="line">});</span><br></pre></td></tr></table></figure>
<p>Note that, because the promise fulfillment returns a module object, the class is then made a subfeature of the object, hence we now need to access the constructor with <code>Module.</code> prepended to it, e.g. <code>Module.Square(...)</code>.</p>
<h2 id="Troubleshooting"><a href="#Troubleshooting" class="headerlink" title="Troubleshooting"></a>Troubleshooting</h2><p>Here are few tips that may help you if you are having trouble getting your modules to work.</p>
<p>Feel free to add to the list if you discover more!</p>
<ul>
<li><p>We mentioned this before, but to reiterate: <code>.js</code> files need to be loaded with a MIME-type of <code>text/javascript</code> (or another JavaScript-compatible MIME-type, but <code>text/javascript</code> is recommended), otherwise you’ll get a strict MIME type checking error like “The server responed with a non-JavaScript MIME type”.</p>
</li>
<li><p>If you try to load the HTML file locally (i.e. with a <code>file://</code> URL), you’ll run into CORS error due to JavaScript module security requirements. You need to do your testing through a server. Github pages is ideal as it also serves <code>.js</code> files with the correct MIME type.</p>
</li>
<li><p>Because <code>.mjs</code> is a non-standard file extension, some operating system might not recognise it, or try to replace it with something else. For example, we found that macOS was silently adding on <code>.js</code> to the end of <code>.mjs</code> files and then automatically hiding the file extension. So all of our file were actually coming out as <code>x.mjs.js</code>. Once we turned off automatically hiding file extensions, and trained it to accept <code>.mjs</code>, it was OK.</p>
</li>
</ul>
</div>
<footer class="article-footer">
<a data-url="http://yovelas.github.io/2019/09/22/Class%20and%20Module/" data-id="cka9d9kuz0000i2fy4y9geocs" class="article-share-link">Share</a>
<ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Java-JavaScript-Class-Module-ES6/" rel="tag">Java,JavaScript,Class,Module,ES6</a></li></ul>
</footer>
</div>
</article>
</section>
<aside id="sidebar">
<div class="widget-wrap">
<h3 class="widget-title">Tags</h3>
<div class="widget">
<ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/tags/Java-JavaScript-Class-Module-ES6/" rel="tag">Java,JavaScript,Class,Module,ES6</a></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Tag Cloud</h3>
<div class="widget tagcloud">
<a href="/tags/Java-JavaScript-Class-Module-ES6/" style="font-size: 10px;">Java,JavaScript,Class,Module,ES6</a>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Archives</h3>
<div class="widget">
<ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/09/">September 2019</a></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">Recent Posts</h3>
<div class="widget">
<ul>
<li>
<a href="/2019/09/22/Class%20and%20Module/">Class and Module</a>
</li>
</ul>
</div>
</div>
</aside>
</div>
<footer id="footer">
<div class="outer">
<div id="footer-info" class="inner">
© 2020 Yovelas<br>
Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
</div>
</div>
</footer>
</div>
<nav id="mobile-nav">
<a href="/" class="mobile-nav-link">Home</a>
<a href="/archives" class="mobile-nav-link">Archives</a>
</nav>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
<script src="/fancybox/jquery.fancybox.pack.js"></script>
<script src="/js/script.js"></script>
</div>
</body>
</html>