title |
---|
Fyrirlestur 12.2 – Hlutir |
Ólafur Sverrir Kjartansson, osk@hi.is
- Objects & encapsulation
- Ein af aðal hugmyndum hlutbundinnar forritunar er að skipta forritum upp og láta hvern hluta bera ábyrgð á eigin stöðu
- Hjúpum virkni og flækjustig, vinnum með í gegnum interface
- Method er fall á hlut
- Hvað ef við viljum nálgast gögn á hlutnum úr falli?
- Notum
this
this
hagar sér öðruvísi í JavaScript en í öðrum málum- Skilgreinist af því hvernig kallað er í fallið
- Utan hluta er
this
global hluturinn, þ.e. þar sem allt er geymt (í browserwindow
)
function foo() {
console.log(this);
}
const bar = {
foo() {
console.log(this);
},
};
console.log(this); // window
foo(); // window
bar.foo(); // {foo: f}
const rabbit = {};
rabbit.speak = (line) => {
console.log(`The rabbit says '${line}'`);
};
rabbit.speak('I’m alive.');
// → The rabbit says 'I’m alive.'
- Leyfir okkur að kalla í föll með ákveðnu
this
apply
– köllum í fall með gefnuthis
og fylki af argumentscall
– köllum í fall með gefnuthis
og lista af arguments
function speak(line) {
console.log(
`${this.type} rabbit says ${line}`
);
}
const oldRabbit = { type: 'old', speak };
const hungryRabbit = { type: 'hungry', speak };
oldRabbit.speak('Oh my');
// old rabbit says Oh my
hungryRabbit.speak('I could use a carrot');
// hungry rabbit says I could use a carrot
function speak(line) {
console.log(
`${this.type} rabbit says ${line}`
);
}
const oldRabbit = { type: 'old' };
speak.apply(oldRabbit, ['Oh my']);
// old rabbit says Oh my
speak.call({ type: 'hungry' }, 'Yum');
// hungry rabbit says Yum
- Leyfir okkur að festa, binda,
this
fyrir föll - Kemur okkur ekki á óvart hvað
this
er - Getum líka bundið argument...
function speak(line) {
console.log(
`${this.type} rabbit says ${line}`
);
}
const blueRabbit = { type: 'blue' };
const bound = speak.bind(blueRabbit);
bound('hi');
// blue rabbit says hi
speak.bind(blueRabbit, 'bye')();
// blue rabbit says bye
- Arrow föll eru öðruvísi—endurskilgreina ekki
this
this
er skilgreint eins og það var skilgreint í scope kringum fall
function normalize() {
console.log(
this.coords.map(
n => n / this.length
)
);
}
const o = { coords: [0, 2, 3], length: 5 };
normalize.call(o);
// → [0, 0.4, 0.6]
function normalize() {
function inner(n) {
return n / this.length;
}
console.log(this.coords.map(inner));
}
const o = { coords: [0, 2, 3], length: 5 };
normalize.call(o);
// → [NaN, Infinity, Infinity]
- Flestir hlutir hafa prótótýpu, hlutur sem geymir fleiri properties
- Ef við biðjum um property á hlut sem er ekki skilgreint á hlut er leitað á prótótýpu hans
- Í grunninn höfum við
Object
- Eða nánar tiltekið
Object.prototype
- Eða nánar tiltekið
Object.getPrototypeOf()
skilar hvaða prótótýpu gildi hefur
const empty = {};
console.log(empty.toString);
// → function toString() { … }
console.log(empty.toString());
// → [object Object]
- Aðrir hlutir hafa aðrar prótótýpur
[]
hefurArray.prototype
- Föll hafa
Function.prototype
- Þessar prótótýpur hafa sínar eigin prótótýpur!
- Mynda prótótýpu keðju
const emptyProto = Object.getPrototypeOf({});
console.log(
emptyProto === Object.prototype
);
// → true
console.log(
Object.getPrototypeOf(Object.prototype)
);
// → null
const funcProto = Object.getPrototypeOf(
Math.max
);
console.log(
funcProto === Function.prototype
);
// → true
console.log(
Object.getPrototypeOf(funcProto) ===
Object.prototype
);
// → true
const arrayProto = Object.getPrototypeOf([]);
console.log(
arrayProto === Array.prototype
);
// → true
- Hlutir fá eigindi frá prótótýpunni en eigindi á hlutnum hafa aldrei áhrif á keðjuna
- Getum ekki skrifað yfir hluti á prótótýpu
- Að setja eigindi á hlut setur það alltaf á honum sjálfum
- Ef við biðjum um eigindi á hlut er reglan:
- Ef það er á hlut fáum við það
- Ef ekki förum við upp prótótýpu keðjuna og leitum þar
- Ef finnst hvergi er
undefined
skilað
Object.create()
býr til hlut með ákveðinni prótótýpu- Leið til að hópa saman föllum
- Prótótýpan geymir sameiginlegu föllin
const protoRabbit = {
speak(line) {
console.log(
`${this.type} rabbit says '${line}'`
);
}
};
const killer = Object.create(protoRabbit);
killer.type = 'killer';
killer.speak('SKREEEE!');
// → killer rabbit says 'SKREEEE!'
- Í JavaScript höfum við ekki klasa eins og í klassískum hlutbundnum málum
- Notum prótótýpu til að erfa frá öðrum hlutum
- Í klassískum erfðum
- Hlutir eru tilvik af klösum
- Klasar erfa frá öðrum klösum
- Með prótótýpum
- Engir klasar
- Hlutir erfa frá öðrum hlutum
- Í JavaScript eru smiðir föll, skýrð með stórum staf
- Þegar við notum
new
og tilgreinum fall búum við til nýjan hlut þar semthis
bendir á hlutinn - Skilar sjálfkrafa
this
sem hlut vegnanew
ef engu er skilað - Bætum við prótótýpu til að bæta við sameiginlegum föllum
function Rabbit(type) {
this.type = type;
}
Rabbit.prototype.speak = function (line) {
console.log(
`The ${this.type} rabbit says '${line}'`
);
};
const weirdRabbit = new Rabbit('weird');
console.log(weirdRabbit);
// Rabbit {type: "weird"}
weirdRabbit.speak('🐰');
// The weird rabbit says '🐰'
- Að setja eigindi á hlut setur það alltaf á honum sjálfum
- Getum nýtt til að yfirskrifa eigindi frá prótótýpu
- T.d.
toString()
til að skila sértæku gildi fyrir okkar hlut
- T.d.
Rabbit.prototype.teeth = 'small';
const killerRabbit = new Rabbit('killer');
console.log(killerRabbit.teeth);
// → small
killerRabbit.teeth = 'long, sharp, bloody';
console.log(killerRabbit.teeth);
// → long, sharp, and bloody
function Rabbit(type) {
this.type = type;
}
const fooRabbit = new Rabbit('foo');
console.log(fooRabbit.toString());
// "[object Object]"
Rabbit.prototype.toString = function () {
return `Rabbit of type ${this.type}`;
};
console.log(fooRabbit.toString());
// "Rabbit of type foo"
- Í ECMAScript 6 er
class
skilgreint - Syntactic sugar til að herma eftir klassískum OO hlutum með prótótýpum
extends
,constructor
,super
,static
og getters og setters
class Rabbit {
constructor(type) {
this.type = type;
}
speak(line) {
console.log(
`${this.type} rabbit says '${line}'`
);
}
toString() {
return `Rabbit of type ${this.type}`;
}
}
const killerRabbit = new Rabbit('killer');
class Foo {
constructor(name) {
this._name = name;
}
hi() { return 'hi!'; }
static bar() { return 1; }
get name() { return this._name; }
set name(value) { this._name = value; }
}
const foo = new Foo('Asdf');
foo.hi(); // "hi!"
foo.name = 'bar';
foo.name; // "bar"
Foo.bar(); // 1