diff options
Diffstat (limited to 'files/vi/learn/javascript/objects')
-rw-r--r-- | files/vi/learn/javascript/objects/index.html | 42 | ||||
-rw-r--r-- | files/vi/learn/javascript/objects/inheritance/index.html | 440 |
2 files changed, 482 insertions, 0 deletions
diff --git a/files/vi/learn/javascript/objects/index.html b/files/vi/learn/javascript/objects/index.html new file mode 100644 index 0000000000..adaad99507 --- /dev/null +++ b/files/vi/learn/javascript/objects/index.html @@ -0,0 +1,42 @@ +--- +title: Introducing JavaScript objects +slug: Learn/JavaScript/Objects +translation_of: Learn/JavaScript/Objects +--- +<div>{{LearnSidebar}}</div> + +<div>Trong JavaScript, hầu hết mọi thứ đều là các đối tượng, từ các tính nắng cốt lõi của JavaScript như chuỗi và mảng đến các {{Glossary("API", "APIs")}} của trình duyệt được xây dựng dựa trên JavaScript. Thậm chí bạn có thể tự tạo các đối tượng để bao đóng các hàm và các biến thành các gói và hoạt động như một kho chứa dữ liệu. Bản chất của JavaScript là dựa trên đối tượng, đây là hiểu biết quan trọng nếu bạn muốn tìm hiểu sâu hơn về ngôn ngữ này. Do đó, chúng tôi cung cấp mô đun này để giúp bạn. Chúng tôi trình bày chi tiết về nguyên lý và cú pháp đối tượng, sau đó là cách để bạn tự tạo các đối tượng cho riêng mình.</div> + +<h2 id="Điều_kiện_tiên_quyết">Điều kiện tiên quyết</h2> + +<p>Trước khi bắt đầu mô đun này, bạn cần có hiểu biết về {{Glossary("HTML")}} và {{Glossary("CSS")}}. Bạn có thể tìm hiểu qua <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Introduction">Introduction to HTML</a> và <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS">Introduction to CSS</a> trước khi bắt đầu học JavaScript.</p> + +<p>Bạn cũng cần có hiểu biết cơ bản về JavaScript. Trước khi bắt đầu nghiên cứu mô đun này, bạn nên tìm hiểu <a href="/en-US/docs/Learn/JavaScript/First_steps">JavaScript first steps</a> và <a href="/en-US/docs/Learn/JavaScript/Building_blocks">JavaScript building blocks</a>.</p> + +<div class="note"> +<p><strong>Chú ý</strong>: Nếu bạn đang làm việc trên các thiết bị (máy tính bàn/máy tính bản/các thiết bị khác) mà không thể tạo các tệp riêng trên đó thì bạn có thể thử gõ mã trên <a href="http://jsbin.com/">JSBin</a> hoặc <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Các_hướng_dẫn">Các hướng dẫn</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/Basics">Cơ bản về đối tượng</a></dt> + <dd>In the first article looking at JavaScript objects, we'll look at fundamental JavaScript object syntax, and revisit some JavaScript features we've already looked at earlier on in the course, reiterating the fact that many of the features you've already dealt with are in fact objects.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">Hướng đối tượng trong JavaScript cho người mới học</a></dt> + <dd>With the basics out of the way, we'll now focus on object-oriented JavaScript (OOJS) — this article presents a basic view of object-oriented programming (OOP) theory, then explores how JavaScript emulates object classes via constructor functions, and how to create object instances.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Nguyên mẫu của đối tượng</a></dt> + <dd>Prototypes are the mechanism by which JavaScript objects inherit features from one another, and they work differently to inheritance mechanisms in classical object-oriented programming languages. In this article we explore that difference, explain how prototype chains work, and look at how the prototype property can be used to add methods to existing constructors.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">Kế thừa trong JavaScript</a></dt> + <dd>With most of the gory details of OOJS now explained, this article shows how to create "child" object classes (constructors) that inherit features from their "parent" classes. In addition, we present some advice on when and where you might use OOJS.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Làm việc với định dạng dữ liệu JSON</a></dt> + <dd>JavaScript Object Notation (JSON) is a standard text-based format for representing structured data based on JavaScript object syntax, which is commonly used for representing and transmitting data on web sites (i.e. sending some data from the server to the client, so it can be displayed on a web page). You'll come across it quite often, so in this article we give you all you need to work with JSON using JavaScript, including parsing the JSON so you can access data items within it and writing your own JSON.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Luyện tập xây dựng đối tượng</a></dt> + <dd>In previous articles we looked at all the essential JavaScript object theory and syntax details, giving you a solid base to start from. In this article we dive into a practical exercise, giving you some more practice in building custom JavaScript objects, which produce something fun and colorful — some colored bouncing balls.</dd> +</dl> + +<h2 id="Assessments">Assessments</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Adding features to our bouncing balls demo</a></dt> + <dd>In this assessment, you are expected to use the bouncing balls demo from the previous article as a starting point, and add some new and interesting features to it.</dd> +</dl> diff --git a/files/vi/learn/javascript/objects/inheritance/index.html b/files/vi/learn/javascript/objects/inheritance/index.html new file mode 100644 index 0000000000..56fb732295 --- /dev/null +++ b/files/vi/learn/javascript/objects/inheritance/index.html @@ -0,0 +1,440 @@ +--- +title: Inheritance in JavaScript +slug: Learn/JavaScript/Objects/Inheritance +translation_of: Learn/JavaScript/Objects/Inheritance +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}</div> + +<p>Lúc này chúng ta đã timnf hiểu hầu hết về OOJS, bài viết này sẽ nói về cách để tạo ra một đối tượng "child" classes (constructors), thứ kế thừa các đặc trưng từ "parent" classes. Thêm nữa, chúng tôi sẽ chỉ cho bạn khi nào và ở đâu bạn có thể sử dụng OOJS, và cách mà các classes được xử lý trong cú pháp ECMAScript.</p> + +<table> + <tbody> + <tr> + <th scope="row">Điều kiện:</th> + <td>Kiến thức cơ bản về máy tính, hiểu biết về HTML và CSS, đã quen với Javsacript căn bản (xem <a href="/en-US/docs/Learn/JavaScript/First_steps">First steps</a> và <a href="/en-US/docs/Learn/JavaScript/Building_blocks">Building blocks</a>) và OOJS căn bản (xem <a href="/en-US/docs/Learn/JavaScript/Object-oriented/Introduction">Introduction to objects</a>).</td> + </tr> + <tr> + <th scope="row">Mục tiêu:</th> + <td>Hiểu về cách thực hiện việc kế thừa trong Javascript.</td> + </tr> + </tbody> +</table> + +<h2 id="Prototypal_inheritance">Prototypal inheritance</h2> + +<p>Ở nhứng bài trước chúng ta đã thực hiện việc kế thừa — chúng ta đã thấy cách mà prototype chains hoạt động, và cách mà các thành phần được kế thừa bằng cách đi ngược lên chuỗi prototype. Nhưng hầu hết chúng chỉ liên quan đến kế thừa từ function. Làm sao để tạo ra một object trong Javascript kế thừa từ một object khác?</p> + +<p>Hãy cùng tìm hiểu với một ví dụ cụ thể:</p> + +<h2 id="Getting_started">Getting started</h2> + +<p>Đầu tiên, hãy tạo một bản copy của file <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-start.html">oojs-class-inheritance-start.html</a> (xem nó hoạt động: <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-start.html">running live</a>). Bạn sẽ thấy có cùng một constructor <code>Person()</code> mà chúng ta sử dụng trong các bài trước, và một chút thay đổi — chúng tôi chỉ định nghĩa các properties trong constructor:</p> + +<pre class="brush: js notranslate">function Person(first, last, age, gender, interests) { + this.name = { + first, + last + }; + this.age = age; + this.gender = gender; + this.interests = interests; +};</pre> + +<p>Các methods đều được định nghĩa trong prototype của constructor. Ví dụ:</p> + +<pre class="brush: js notranslate">Person.prototype.greeting = function() { + alert('Hi! I\'m ' + this.name.first + '.'); +};</pre> + +<div class="note"> +<p><strong>Ghi chú</strong>: Trong source code, bạn sẽ thấy các methods <code>bio()</code> và <code>farewell()</code> được định nghĩa. Lát nữa bạn sẽ thấy cách chúng được kế thừa bởi các constructors khác.</p> +</div> + +<p>Chúng ta muốn tạo một class <code>Teacher</code>, như đã mô tả trong định nghĩa ban đầu về object-oriented, là class kế thừa mọi thành phần từ <code>Person</code>, và có cả:</p> + +<ol> + <li>Một property mới, <code>subject</code> — nó sẽ chứa tên môn học mà teacher dạy.</li> + <li>Một method <code>greeting()</code> đã được chỉnh sửa sao cho trang trọng hơn so với method <code>greeting()</code> ban đầu — để phù hợp hơn khi một giáo viên nói chuyện với một học sinh ở trường.</li> +</ol> + +<h2 id="Định_nghĩa_hàm_Teacher_constructor">Định nghĩa hàm Teacher() constructor</h2> + +<p>Đầu tiên chúng ta cần tạo một <code>Teacher()</code> constructor — hãy thêm đoạn code bên dưới vào source code:</p> + +<pre class="brush: js notranslate">function Teacher(first, last, age, gender, interests, subject) { + Person.call(this, first, last, age, gender, interests); + + this.subject = subject; +}</pre> + +<p>Nhìn có vẻ giống với Person constructor, nhưng có một vài điều khác lạ mà chúng ta chưa từng thấy trước đó — hàm <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call">call()</a></code>. Hàm này cho phép bạn gọi một function được định nghĩa ở một nơi khác. Tham số đầu tiên có giá trị <code>this</code> mà bạn muốn sử dụng khi đang thực thi function, và các tham số khác sẽ được chuyển cho function khi nó được gọi.</p> + +<p>Chúng ta muốn <code>Teacher()</code> constructor có cùng tham số với <code>Person()</code> constructor mà nó kế thừa, nên chúng ta chỉ định chúng như các tham số khi gọi hàm <code>call()</code>.</p> + +<p>Dòng cuối cùng trong constructor chỉ đơn giản định nghĩa property <code>subject</code>.mà chỉ teachers có, và people không có</p> + +<p>Nhưng chúng ta cũng có thể thực hiện điều này như sau:</p> + +<pre class="brush: js notranslate">function Teacher(first, last, age, gender, interests, subject) { + this.name = { + first, + last + }; + this.age = age; + this.gender = gender; + this.interests = interests; + this.subject = subject; +}</pre> + +<p>Nhưng đó là định nghĩa một properties mới, không kế thừa từ <code>Person()</code>, không giống như những gì chúng ta định làm. Nó cũng khiến code dài dòng hơn.</p> + +<h3 id="Kế_thừa_từ_một_constructor_không_có_tham_số">Kế thừa từ một constructor không có tham số</h3> + +<p>Lưu ý rằng nếu constructor mà bạn đang kế thừa không nhận các giá trị properties của nó từ tham số, bạn không cần thêm các tham số vào <code>call()</code>. Vậy, nếu bạn viết một vài dòng code như sau:</p> + +<pre class="brush: js notranslate">function Brick() { + this.width = 10; + this.height = 20; +}</pre> + +<p>Bạn có thể kế thừa các properties <code>width</code> và <code>height</code> (cũng như các bước khác đã được mô tả bên dưới):</p> + +<pre class="brush: js notranslate">function BlueGlassBrick() { + Brick.call(this); + + this.opacity = 0.5; + this.color = 'blue'; +}</pre> + +<p>Chú ý rằng chúng ta chỉ chỉ định <code>this</code> bên trong <code>call()</code> — Không có tham số nào là bắt buộc vì chúng ta không kế thừa bất cứ properties nào từ cha nó thông qua tham số.</p> + +<h2 id="Cấu_hình_prototype_của_Teacher_và_về_constructor">Cấu hình prototype của Teacher() và về constructor</h2> + +<p>Mọi thứ đều ổn, nhưng có một vấn đề. Chúng ta vừa định nghĩa một constructor mới, và nó có <code>prototype</code> property, được mặc định là tham chiếu đến hàm constructor của nó. Nó không chứa các method trong property <code>prototype</code> của constructor của Person. Để thấy điều này, nhập <code>Object.getOwnPropertyNames(Teacher.prototype)</code> vào màn hình Javascript console. Sau đó, thay thế <code>Teacher</code> thành <code>Person</code>. Constructor cũng không kế thừa các methods đó. Đề thấy điều này, hãy so sánh kết quả của <code>Person.prototype.greeting</code> và <code>Teacher.prototype.greeting</code>. Chúng ta cần các methods của <code>Teacher()</code> để kế thừa các methods được định nghĩa trong prototype của <code>Person()</code>. Làm sao để thực hiện việc này?</p> + +<ol> + <li>Thêm dòng code sau vào dưới phần đã thêm vào trước đó: + <pre class="brush: js notranslate">Teacher.prototype = Object.create(Person.prototype);</pre> + Here our friend <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create">create()</a></code> comes to the rescue again. In this case we are using it to create a new object and make it the value of <code>Teacher.prototype</code>. The new object has <code>Person.prototype</code> as its prototype and will therefore inherit, if and when needed, all the methods available on <code>Person.prototype</code>.</li> + <li>We need to do one more thing before we move on. After adding the last line, <code>Teacher.</code><code>prototype</code>'s <code>constructor</code> property is now equal to <code>Person()</code>, because we just set <code>Teacher.prototype</code> to reference an object that inherits its properties from <code>Person.prototype</code>! Try saving your code, loading the page in a browser, and entering <code>Teacher.prototype.constructor</code> into the console to verify.</li> + <li>This can become a problem, so we need to set this right. You can do so by going back to your source code and adding the following line at the bottom: + <pre class="brush: js notranslate">Object.defineProperty(Teacher.prototype, 'constructor', { + value: Teacher, + enumerable: false, // so that it does not appear in 'for in' loop + writable: true });</pre> + </li> + <li>Now if you save and refresh, entering <code>Teacher.prototype.constructor</code> should return <code>Teacher()</code>, as desired, plus we are now inheriting from <code>Person()</code>!</li> +</ol> + +<h2 id="Giving_Teacher_a_new_greeting_function">Giving Teacher() a new greeting() function</h2> + +<p>To finish off our code, we need to define a new <code>greeting()</code> function on the <code>Teacher()</code> constructor.</p> + +<p>The easiest way to do this is to define it on <code>Teacher()</code>'s prototype — add the following at the bottom of your code:</p> + +<pre class="brush: js notranslate">Teacher.prototype.greeting = function() { + let prefix; + + if (this.gender === 'male' || this.gender === 'Male' || this.gender === 'm' || this.gender === 'M') { + prefix = 'Mr.'; + } else if (this.gender === 'female' || this.gender === 'Female' || this.gender === 'f' || this.gender === 'F') { + prefix = 'Ms.'; + } else { + prefix = 'Mx.'; + } + + alert('Hello. My name is ' + prefix + ' ' + this.name.last + ', and I teach ' + this.subject + '.'); +};</pre> + +<p>This alerts the teacher's greeting, which also uses an appropriate name prefix for their gender, worked out using a conditional statement.</p> + +<h2 id="Trying_the_example_out">Trying the example out</h2> + +<p>Now that you've entered all the code, try creating an object instance from <code>Teacher()</code> by putting the following at the bottom of your JavaScript (or something similar of your choosing):</p> + +<pre class="brush: js notranslate">let teacher1 = new Teacher('Dave', 'Griffiths', 31, 'male', ['football', 'cookery'], 'mathematics');</pre> + +<p>Now save and refresh, and try accessing the properties and methods of your new <code>teacher1</code> object, for example:</p> + +<pre class="brush: js notranslate">teacher1.name.first; +teacher1.interests[0]; +teacher1.bio(); +teacher1.subject; +teacher1.greeting(); +teacher1.farewell();</pre> + +<p>These should all work just fine. The queries on lines 1, 2, 3, and 6 access members inherited from the generic <code>Person()</code> constructor (class). The query on line 4 accesses a member that is available only on the more specialized <code>Teacher()</code> constructor (class). The query on line 5 would have accessed a member inherited from <code>Person()</code>, except for the fact that <code>Teacher()</code> has its own member with the same name, so the query accesses that member.</p> + +<div class="note"> +<p><strong>Note</strong>: If you have trouble getting this to work, compare your code to our <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-finished.html">finished version</a> (see it <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-finished.html">running live</a> also).</p> +</div> + +<p>The technique we covered here is not the only way to create inheriting classes in JavaScript, but it works OK, and it gives you a good idea about how to implement inheritance in JavaScript.</p> + +<p>You might also be interested in checking out some of the new {{glossary("ECMAScript")}} features that allow us to do inheritance more cleanly in JavaScript (see <a href="/en-US/docs/Web/JavaScript/Reference/Classes">Classes</a>). We didn't cover those here, as they are not yet supported very widely across browsers. All the other code constructs we discussed in this set of articles are supported as far back as IE9 or earlier, and there are ways to achieve earlier support than that.</p> + +<p>A common way is to use a JavaScript library — most of the popular options have an easy set of functionality available for doing inheritance more easily and quickly. <a href="http://coffeescript.org/#classes">CoffeeScript</a> for example provides <code>class</code>, <code>extends</code>, etc.</p> + +<h2 id="A_further_exercise">A further exercise</h2> + +<p>In our <a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS#Object-oriented_programming_from_10000_meters">OOP theory section</a>, we also included a <code>Student</code> class as a concept, which inherits all the features of <code>Person</code>, and also has a different <code>greeting()</code> method from <code>Person</code> that is much more informal than the <code>Teacher</code>'s greeting. Have a look at what the student's greeting looks like in that section, and try implementing your own <code>Student()</code> constructor that inherits all the features of <code>Person()</code>, and implements the different <code>greeting()</code> function.</p> + +<div class="note"> +<p><strong>Note</strong>: If you have trouble getting this to work, have a look at our <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-student.html">finished version</a> (see it <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-student.html">running live</a> also).</p> +</div> + +<h2 id="Object_member_summary">Object member summary</h2> + +<p>To summarize, you've got four types of property/method to worry about:</p> + +<ol> + <li>Those defined inside a constructor function that are given to object instances. These are fairly easy to spot — in your own custom code, they are the members defined inside a constructor using the <code>this.x = x</code> type lines; in built in browser code, they are the members only available to object instances (usually created by calling a constructor using the <code>new</code> keyword, e.g. <code>let myInstance = new myConstructor()</code>).</li> + <li>Those defined directly on the constructor themselves, that are available only on the constructor. These are commonly only available on built-in browser objects, and are recognized by being chained directly onto a constructor, <em>not</em> an instance. For example, <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys">Object.keys()</a></code>. These are also known as <strong>static properties/methods</strong>.</li> + <li>Those defined on a constructor's prototype, which are inherited by all instances and inheriting object classes. These include any member defined on a Constructor's <code>prototype</code> property, e.g. <code>myConstructor.prototype.x()</code>.</li> + <li>Those available on an object instance, which can either be an object created when a constructor is instantiated like we saw above (so for example <code>var teacher1 = new Teacher( name = 'Chris' );</code> and then <code>teacher1.name</code>), or an object literal (<code>let teacher1 = { name = 'Chris' }</code> and then <code>teacher1.name</code>).</li> +</ol> + +<p>If you are not sure which is which, don't worry about it just yet — you are still learning, and familiarity will come with practice.</p> + +<h2 id="ECMAScript_2015_Classes">ECMAScript 2015 Classes</h2> + +<p>ECMAScript 2015 introduces <a href="/en-US/docs/Web/JavaScript/Reference/Classes">class syntax</a> to JavaScript as a way to write reusable classes using easier, cleaner syntax, which is more similar to classes in C++ or Java. In this section we'll convert the Person and Teacher examples from prototypal inheritance to classes, to show you how it's done.</p> + +<div class="note"> +<p><strong>Note</strong>: This modern way of writing classes is supported in all modern browsers, but it is still worth knowing about the underlying prototypal inheritance in case you work on a project that requires supporting a browser that doesn't support this syntax (most notably Internet Explorer).</p> +</div> + +<p>Let's look at a rewritten version of the Person example, class-style:</p> + +<pre class="brush: js notranslate">class Person { + constructor(first, last, age, gender, interests) { + this.name = { + first, + last + }; + this.age = age; + this.gender = gender; + this.interests = interests; + } + + greeting() { + console.log(`Hi! I'm ${this.name.first}`); + }; + + farewell() { + console.log(`${this.name.first} has left the building. Bye for now!`); + }; +} +</pre> + +<p>The <a href="/en-US/docs/Web/JavaScript/Reference/Statements/class">class</a> statement indicates that we are creating a new class. Inside this block, we define all the features of the class:</p> + +<ul> + <li>The <code><a href="/en-US/docs/Web/JavaScript/Reference/Classes/constructor">constructor()</a></code> method defines the constructor function that represents our <code>Person</code> class.</li> + <li><code>greeting()</code> and <code>farewell()</code> are class methods. Any methods you want associated with the class are defined inside it, after the constructor. In this example, we've used <a href="/en-US/docs/Web/JavaScript/Reference/Template_literals">template literals</a> rather than string concatenation to make the code easier to read.</li> +</ul> + +<p>We can now instantiate object instances using the <a href="/en-US/docs/Web/JavaScript/Reference/Operators/new"><code>new</code> operator</a>, in just the same way as we did before:</p> + +<pre class="brush: js notranslate">let han = new Person('Han', 'Solo', 25, 'male', ['Smuggling']); +han.greeting(); +// Hi! I'm Han + +let leia = new Person('Leia', 'Organa', 19, 'female', ['Government']); +leia.farewell(); +// Leia has left the building. Bye for now +</pre> + +<div class="note"> +<p><strong>Note</strong>: Under the hood, your classes are being converted into Prototypal Inheritance models — this is just syntactic sugar. But I'm sure you'll agree that it's easier to write.</p> +</div> + +<h3 id="Inheritance_with_class_syntax">Inheritance with class syntax</h3> + +<p>Above we created a class to represent a person. They have a series of attributes that are common to all people; in this section we'll create our specialized <code>Teacher</code> class, making it inherit from <code>Person</code> using modern class syntax. This is called creating a subclass or subclassing.</p> + +<p>To create a subclass we use the <a href="/en-US/docs/Web/JavaScript/Reference/Classes/extends">extends keyword</a> to tell JavaScript the class we want to base our class on,</p> + +<pre class="brush: js notranslate">class Teacher extends Person { + constructor(subject, grade) { + this.subject = subject; + this.grade = grade; + } +}</pre> + +<p>but there's a little catch.</p> + +<p>Unlike old-school constructor functions where the <a href="/en-US/docs/Web/JavaScript/Reference/Operators/new"><code>new</code> operator</a> does the initialization of <code>this</code> to a newly-allocated object, this isn't automatically initialized for a class defined by the <a href="/en-US/docs/Web/JavaScript/Reference/Classes/extends">extends</a> keyword, i.e the sub-classes.</p> + +<p>Therefore running the above code will give an error:</p> + +<pre class="brush: js notranslate">Uncaught ReferenceError: Must call super constructor in derived class before +accessing 'this' or returning from derived constructor</pre> + +<p>For sub-classes, the <code>this</code> intialization to a newly allocated object is always dependant on the parent class constructor, i.e the constructor function of the class from which you're extending.</p> + +<p>Here we are extending the <code>Person</code> class — the <code>Teacher</code> sub-class is an extension of the <code>Person</code> class. So for <code>Teacher</code>, the <code>this</code> initialization is done by the <code>Person</code> constructor.</p> + +<p>To call the parent constructor we have to use the <a href="/en-US/docs/Web/JavaScript/Reference/Operators/super"><code>super()</code> operator</a>, like so:</p> + +<pre class="brush: js notranslate">class Teacher extends Person { + constructor(subject, grade) { + super(); // Now 'this' is initialized by calling the parent constructor. + this.subject = subject; + this.grade = grade; + } +}</pre> + +<p>There is no point having a sub-class if it doesn't inherit properties from the parent class.<br> + It is good then, that the <a href="/en-US/docs/Web/JavaScript/Reference/Operators/super"><code>super()</code> operator</a> also accepts arguments for the parent constructor.</p> + +<p>Looking back to our <code>Person</code> constructor, we can see it has the following block of code in its constructor method:</p> + +<pre class="brush: js notranslate"> constructor(first, last, age, gender, interests) { + this.name = { + first, + last + }; + this.age = age; + this.gender = gender; + this.interests = interests; +} </pre> + +<p>Since the <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/super">super()</a></code> operator is actually the parent class constructor, passing it the necessary arguments of the <code>Parent</code> class constructor will also initialize the parent class properties in our sub-class, thereby inheriting it:</p> + +<pre class="brush: js notranslate">class Teacher extends Person { + constructor(first, last, age, gender, interests, subject, grade) { + super(first, last, age, gender, interests); + + // subject and grade are specific to Teacher + this.subject = subject; + this.grade = grade; + } +} +</pre> + +<p>Now when we instantiate <code>Teacher</code> object instances, we can call methods and properties defined on both <code>Teacher</code>and <code>Person</code> as we'd expect:</p> + +<pre class="brush: js notranslate">let snape = new Teacher('Severus', 'Snape', 58, 'male', ['Potions'], 'Dark arts', 5); +snape.greeting(); // Hi! I'm Severus. +snape.farewell(); // Severus has left the building. Bye for now. +snape.age // 58 +snape.subject; // Dark arts +</pre> + +<p>Like we did with Teachers, we could create other subclasses of <code>Person</code> to make them more specialized without modifying the base class.</p> + +<div class="note"> +<p><strong>Note</strong>: You can find this example on GitHub as <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/es2015-class-inheritance.html">es2015-class-inheritance.html</a> (<a href="https://mdn.github.io/learning-area/javascript/oojs/advanced/es2015-class-inheritance.html">see it live also</a>).</p> +</div> + +<h2 id="Getters_and_Setters">Getters and Setters</h2> + +<p>There may be times when we want to change the values of an attribute in the classes we create or we don't know what the final value of an attribute will be. Using the <code>Teacher</code> example, we may not know what subject the teacher will teach before we create them, or their subject may change between terms.</p> + +<p>We can handle such situations with getters and setters.</p> + +<p>Let's enhance the Teacher class with getters and setters. The class starts the same as it was the last time we looked at it.</p> + +<p>Getters and setters work in pairs. A getter returns the current value of the variable and its corresponding setter changes the value of the variable to the one it defines.</p> + +<p>The modified <code>Teacher</code> class looks like this:</p> + +<pre class="brush: js notranslate">class Teacher extends Person { + constructor(first, last, age, gender, interests, subject, grade) { + super(first, last, age, gender, interests); + // subject and grade are specific to Teacher + this._subject = subject; + this.grade = grade; + } + + get subject() { + return this._subject; + } + + set subject(newSubject) { + this._subject = newSubject; + } +} +</pre> + +<p>In our class above we have a getter and setter for the <code>subject</code> property. We use <strong><code>_</code> </strong> to create a separate value in which to store our name property. Without using this convention, we would get errors every time we called get or set. At this point:</p> + +<ul> + <li>To show the current value of the <code>_subject</code> property of the <code>snape</code> object we can use the <code>snape.subject</code> getter method.</li> + <li>To assign a new value to the <code>_subject</code> property we can use the <code>snape.subject="new value"</code> setter method.</li> +</ul> + +<p>The example below shows the two features in action:</p> + +<pre class="brush: js notranslate">// Check the default value +console.log(snape.subject) // Returns "Dark arts" + +// Change the value +snape.subject = "Balloon animals" // Sets _subject to "Balloon animals" + +// Check it again and see if it matches the new value +console.log(snape.subject) // Returns "Balloon animals" +</pre> + +<div class="note"> +<p><strong>Note</strong>: You can find this example on GitHub as <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/es2015-getters-setters.html">es2015-getters-setters.html</a> (<a href="https://mdn.github.io/learning-area/javascript/oojs/advanced/es2015-getters-setters.html">see it live also</a>).</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Note:</strong> Getters and setters can be very useful at times, for example when you want to run some code every time a property is requested or set. For simple cases, however, plain property access without a getter or setter will do just fine.</p> +</div> + +<h2 id="When_would_you_use_inheritance_in_JavaScript">When would you use inheritance in JavaScript?</h2> + +<p>Particularly after this last article, you might be thinking "woo, this is complicated". Well, you are right. Prototypes and inheritance represent some of the most complex aspects of JavaScript, but a lot of JavaScript's power and flexibility comes from its object structure and inheritance, and it is worth understanding how it works.</p> + +<p>In a way, you use inheritance all the time. Whenever you use various features of a Web API , or methods/properties defined on a built-in browser object that you call on your strings, arrays, etc., you are implicitly using inheritance.</p> + +<p>In terms of using inheritance in your own code, you probably won't use it often, especially to begin with, and in small projects. It is a waste of time to use objects and inheritance just for the sake of it when you don't need them. But as your code bases get larger, you are more likely to find a need for it. If you find yourself starting to create a number of objects that have similar features, then creating a generic object type to contain all the shared functionality and inheriting those features in more specialized object types can be convenient and useful.</p> + +<div class="note"> +<p><strong>Note</strong>: Because of the way JavaScript works, with the prototype chain, etc., the sharing of functionality between objects is often called <strong>delegation</strong>. Specialized objects delegate functionality to a generic object type.</p> +</div> + +<p>When using inheritance, you are advised to not have too many levels of inheritance, and to keep careful track of where you define your methods and properties. It is possible to start writing code that temporarily modifies the prototypes of built-in browser objects, but you should not do this unless you have a really good reason. Too much inheritance can lead to endless confusion, and endless pain when you try to debug such code.</p> + +<p>Ultimately, objects are just another form of code reuse, like functions or loops, with their own specific roles and advantages. If you find yourself creating a bunch of related variables and functions and want to track them all together and package them neatly, an object is a good idea. Objects are also very useful when you want to pass a collection of data from one place to another. Both of these things can be achieved without use of constructors or inheritance. If you only need a single instance of an object, then you are probably better off just using an object literal, and you certainly don't need inheritance.</p> + +<h2 id="Alternatives_for_extending_the_prototype_chain">Alternatives for extending the prototype chain</h2> + +<p>In JavaScript, there are several different ways to extend the prototype of an object aside from what we've shown above. To find out more about the other ways, visit our <a href="/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain#Different_ways_to_create_objects_and_the_resulting_prototype_chain">Inheritance and the prototype chain</a> article.</p> + +<h2 id="Test_your_skills!">Test your skills!</h2> + +<p>You've reached the end of this article, but can you remember the most important information? You can find some further tests to verify that you've retained this information before you move on — see <a href="/en-US/docs/Learn/JavaScript/Objects/Test_your_skills:_Object-oriented_JavaScript">Test your skills: Object-oriented JavaScript</a>.</p> + +<h2 id="Summary">Summary</h2> + +<p>This article has covered the remainder of the core OOJS theory and syntax that we think you should know now. At this point you should understand JavaScript object and OOP basics, prototypes and prototypal inheritance, how to create classes (constructors) and object instances, add features to classes, and create subclasses that inherit from other classes.</p> + +<p>In the next article we'll have a look at how to work with JavaScript Object Notation (JSON), a common data exchange format written using JavaScript objects.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="http://www.objectplayground.com/">ObjectPlayground.com</a> — A really useful interactive learning site for learning about objects.</li> + <li><a href="https://www.manning.com/books/secrets-of-the-javascript-ninja-second-edition">Secrets of the JavaScript Ninja</a>, Chapter 7 — A good book on advanced JavaScript concepts and techniques, by John Resig, Bear Bibeault, and Josip Maras. Chapter 7 covers aspects of prototypes and inheritance really well; you can probably track down a print or online copy fairly easily.</li> + <li><a href="https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/README.md">You Don't Know JS: this & Object Prototypes</a> — Part of Kyle Simpson's excellent series of JavaScript manuals, Chapter 5 in particular looks at prototypes in much more detail than we do here. We've presented a simplified view in this series of articles aimed at beginners, whereas Kyle goes into great depth and provides a more complex but more accurate picture.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics">Object basics</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">Object-oriented JavaScript for beginners</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Object prototypes</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">Inheritance in JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Working with JSON data</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Object building practice</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Adding features to our bouncing balls demo</a></li> +</ul> |