Detta verk är framtaget av Mats Loock i anslutning till kursen Grundläggande programmering (1DV021) vid Linnéuniversitetet.
Allt innehåll i detta verk förutom fotografier, ikoner, bild på kurslitteraturen samt Linnéuniversitetets logotyp och symbol,
är licensierad under en
Creative Commons Erkännande 4.0 Internationell Licens
.
Om du förändrar innehållet så ta inte med fotografier, ikoner, bild på kurslitteraturen samt Linnéuniversitetets logotyp och symbol i din nya version!
Vid all användning måste du ange källan: ”Linnéuniversitetet – Grundläggande programmering (1DV021)” och en länk till https://coursepress.lnu.se/kurs/grundlaggande-programmering och till Creative Common-licensen här ovan.
const rectangle = { length: 6, width: 7}console.log('Area: ' + rectangle.length * rectangle.width)
const rectangle = { length: 6, width: 7, getArea: function () { return this.length * this.width }}console.log('Area: ' + rectangle.getArea())
src/Rectangle.js
function Rectangle () { this.length = 0 this.width = 0 this.getArea = function () { return this.length * this.width }}module.exports = Rectangle
app.js
const Rectangle = require('./src/Rectangle')const rectangle = new Rectangle()rectangle.length = 6rectangle.width = 7console.log('Area: ' + rectangle.getArea())
src/Rectangle.js
function Rectangle (length = 0, width = 0) { this.length = length this.width = width}Rectangle.prototype.getArea = function () { return this.length * this.width}module.exports = Rectangle
app.js
const Rectangle = require('./src/Rectangle')const rectangle = new Rectangle(6, 7)console.log('Area: ' + rectangle.getArea())
src/Rectangle.js
class Rectangle { constructor (length = 0, width = 0) { this.length = length this.width = width } getArea () { return this.length * this.width }}module.exports = Rectangle
app.js
const Rectangle = require('./src/Rectangle')const rectangle = new Rectangle(6, 7)console.log('Area: ' + rectangle.getArea())
src/Rectangle.js
function Rectangle (length = 0, width = 0) { this.length = length this.width = width}Rectangle.prototype.getArea = function () { return this.length * this.width}
app.js
const Rectangle = require('./src/Rectangle')const rectangle1 = new Rectangle(6, 7)const rectangle2 = new Rectangle(3, 4)console.log('Area: ' + rectangle1.getArea())console.log('Area: ' + rectangle2.getArea())
constructor
, till konstruktorfunktionen samt egenskaper och metoder gemensamma för alla instanser av typen.__proto__
, till konstruktorns prototyp.src/Die.js
function Die () { this.faceValue}Die.prototype.roll = function () { this.faceValue = Math.floor(Math.random() * 6) + 1}module.exports = Die
app.js
const Die = require('./src/Die')const die1 = new Die()const die2 = new Die()// Inte några värden en sexsidig tärning ska ha...die1.faceValue = 42die2.faceValue = 'Kilroy was here!'
faceValue
, ska kapslas in (och döljas).function Foo (param) { // "privat" this.ohSoPublic = param // "publik" this._notSoPrivate = param // "publik" MEN "semi-privat" genom namngivning (namn inleds med _) let secret = 42 // "privat" const getTheMeaningOfLife = function () { // "privat" return 'forty-two' }}const foo = new Foo(21)console.log(foo.ohSoPublic) // OUTPUT: 21console.log(foo._notSoPrivate) // OUTPUT: 21console.log(foo.secret) // OUTPUT: undefinedconsole.log(foo.getTheMeaningOfLife()) // EXCEPTION: TypeError: foo.getTheMeaningOfLife is not a function
Object.defineProperty
kan du ange den funktion som ska köras då en egenskaps värde hämtas.src/Die.js
function Die () { this._faceValue = undefined // semi-private property}Object.defineProperty(Die.prototype, 'faceValue', { get: function () { return this._faceValue }})Die.prototype.roll = function () { this._faceValue = Math.floor(Math.random() * 6) + 1}module.exports = Die
app.js
const Die = require('./src/Die')const die1 = new Die()const die2 = new Die()die1.roll()die2.roll()console.log(die1.faceValue)console.log(die2.faceValue)die1.faceValue = 42 // EXCEPTION: TypeError: Cannot set property faceValue of #<Die> which has only a getterdie1._faceValue = 42 // Fortfarande möjligt, egenskapen är ju "bara" semi-privat! Programmeraren får skylla sig själv...
Object.defineProperty
kan du ange den funktion som ska köras då en egenskaps värde hämtas respektive tilldelas ett värde.src/Die.js
function Die () { let _faceValue Object.defineProperty(this, 'faceValue', { get: function () { return _faceValue }, set: function (value) { const intValue = Number.parseInt(value, 10) if (!Number.isInteger(intValue) || intValue < 1 || intValue > 6) { throw new Error('faceValue must be set to an integer between 1 and 6.') } _faceValue = intValue } })}Die.prototype.roll = function () { this.faceValue = Math.floor(Math.random() * 6) + 1}module.exports = Die
app.js
const Die = require('./src/Die')const die1 = new Die()die1.faceValue = 42 // EXCEPTION: Error: faceValue must be set to an integer between 1 and 6.
src/Die.js
class Die { constructor () { this._faceValue = undefined } get faceValue () { return this._faceValue } roll () { this._faceValue = Math.floor(Math.random() * 6) + 1 }}module.exports = Die
app.js
const Die = require('./src/Die')const die1 = new Die()const die2 = new Die()die1.roll()die2.roll()console.log(die1.faceValue)console.log(die2.faceValue)die1.faceValue = 42 // EXCEPTION: TypeError: Cannot set property faceValue of #<Die> which has only a getter
src/Die.js
const _faceValue = new WeakMap()class Die { constructor () { _faceValue.set(this, undefined) } get faceValue () { return _faceValue.get(this) } set faceValue (value) { const numberValue = Number(value) if (!Number.isInteger(numberValue) || numberValue < 1 || numberValue > 6) { throw new Error('faceValue must be set to an integer between 1 and 6.') } _faceValue.set(this, value) } roll () { this.faceValue = Math.floor(Math.random() * 6) + 1 }}module.exports = Die
app.js
const Die = require('./src/Die')const die1 = new Die()die1.faceValue = 42 // EXCEPTION: Error: faceValue must be set to an integer between 1 and 6.
src/Die.js
class Die { #faceValue // private class field/class property, stage 3 proposal ES2019 constructor () { this.roll() } get faceValue () { return this.#faceValue } set faceValue (value) { const numberValue = Number(value) if (!Number.isInteger(numberValue) || numberValue < 1 || numberValue > 6) { throw new Error('faceValue must be set to an integer between 1 and 6.') } this.#faceValue = value } roll () { this.#faceValue = Math.floor(Math.random() * 6) + 1 }}module.exports = Die
app.js
const Die = require('./src/Die')const die1 = new Die()die1.faceValue = 42 // EXCEPTION: Error: faceValue must be set to an integer between 1 and 6.
Person
och Student
innehåller kod gemensam för de båda typerna. Behöver det vara så? Nej, med hjälp av arv ("inheritance") kan kod återanvändas instället för att upprepas.src/Person.js
function Person (name, age) { this.name = name this.age = age}Person.prototype.toString = function () { return 'Jag, ' + this.name + ', är ' + this.age + ' år.'}module.exports = Person
src/Student.js
function Student(name, age, isCampus) { this.name = name this.age = age this.isCampus = isCampus}Student.prototype.toString = function () { return 'Jag, ' + this.name + ', läser på ' + (this.isCampus ? 'campus' : 'distans') + ' och är ' + this.age + ' år.'}module.exports = Student
Student
ärva från Person
kan kod i Person
återanvändas av Student
.src/Person.js
function Person (name, age) { this.name = name this.age = age}Person.prototype.toString = function() { // överskuggar metoden i Object.prototype return 'Jag, ' + this.name + ', är ' + this.age + ' år.'}module.exports = Person
src/Student.js
const Person = require('./Person')function Student (name, age, isCampus) { Person.call(this, name, age) // anrop av konstruktorn för Person this.isCampus = isCampus}Student.prototype = Object.create(Person.prototype) // ärver prototypen från PersonStudent.prototype.constructor = Student // återställer konstruktorn till StudentStudent.prototype.toString = function() { // överskuggar metoden i Person.prototype return 'Jag, ' + this.name + ', läser på ' + (this.isCampus ? 'campus' : 'distans') + ' och är ' + this.age + ' år.'}module.exports = Student
src/Person.js
class Person { constructor (name, age) { this.name = name this.age = age } toString() { // överskuggar metoden i Object.prototype return 'Jag, ' + this.name + ', är ' + this.age + ' år.' }}module.exports = Person
src/Student.js
const Person = require('./Person')class Student extends Person { constructor (name, age, isCampus) { super(name, age) // anrop av konstruktorn för Person this.isCampus = isCampus } toString() { // överskuggar metoden i Person return 'Jag, ' + this.name + ', läser på ' + (this.isCampus ? 'campus' : 'distans') + ' och är ' + this.age + ' år.' }}module.exports = Student
app.js
const p = new Person('Ellen', 6)console.log(p.toString()) // OUTPUT: Jag, Ellen, är 6 år.const s = new Student('Nisse', 42, true)console.log(s.toString()); // OUTPUT: Jag, Nisse, läser på campus och är 42 år.
instanceof
kan du undersöka om en konstruktor har används för att skapa ett objekt.const person1 = new Person('Nisse', 42)const student1 = new Student('Ellen', 21, true)console.log(person1 instanceof Person) // OUTPUT: trueconsole.log(person1 instanceof Student) // OUTPUT: falseconsole.log(student1 instanceof Person) // OUTPUT: trueconsole.log(student1 instanceof Student) // OUTPUT: true
src/personMaker.js
const personBase = { toString: function () { return `Jag, ${this.name}, är ${this.age} år.` }}let createPerson = function (name, age) { return Object.create(personBase, { age: { value: age, writable: true, configurable: true, enumerable: true }, name: { value: name, writable: true, configurable: true, enumerable: true } })}module.exports.createPerson = createPerson
src/studentMaker.js
const personMaker = require('./personMaker')let createStudent = function (name, age, isCampus) { let obj = Object.create(personMaker.createPerson(name, age), { isCampus: { value: isCampus, writable: true, configurable: true, enumerable: true } }) obj.toString = function () { return `Jag, ${this.name}, läser på ${this.isCampus ? 'campus' : 'distans'} och är ${this.age} år.` } return obj}module.exports.createStudent = createStudent
Detta verk är framtaget av Mats Loock i anslutning till kursen Grundläggande programmering (1DV021) vid Linnéuniversitetet.
Allt innehåll i detta verk förutom fotografier, ikoner, bild på kurslitteraturen samt Linnéuniversitetets logotyp och symbol,
är licensierad under en
Creative Commons Erkännande 4.0 Internationell Licens
.
Om du förändrar innehållet så ta inte med fotografier, ikoner, bild på kurslitteraturen samt Linnéuniversitetets logotyp och symbol i din nya version!
Vid all användning måste du ange källan: ”Linnéuniversitetet – Grundläggande programmering (1DV021)” och en länk till https://coursepress.lnu.se/kurs/grundlaggande-programmering och till Creative Common-licensen här ovan.
Keyboard shortcuts
↑, ←, Pg Up, k | Go to previous slide |
↓, →, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
Number + Return | Go to specific slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
Esc | Back to slideshow |