<프로토타입>
:The __proto__ getter function exposes the value of the internal [[Prototype]] of an object. For objects created using an object literal, this value is Object.prototype. For objects created using array literals, this value is Array.prototype. For functions, this value is Function.prototype. For objects created using new fun, where fun is one of the built-in constructor functions provided by JavaScript (Array, Boolean, Date, Number, Object, String, and so on — including new constructors added as JavaScript evolves), this value is always fun.prototype. For objects created using new fun, where fun is a function defined in a script, this value is the value of fun.prototype. (That is, if the constructor didn't return an other object explicitly, or the fun.prototype has been reassigned since the instance was created).
//String.prototype is a "template object" for every single string.
//We could go crazy and add our own method called yell...
String.prototype.yell = function() {
return `OMG!!! ${this.toUpperCase()}!!!!! AGHGHGHG!`;
};
'bees'.yell(); //"OMG!!! BEES!!!!! AGHGHGHG!"
//We can overwrite an existing Array method like pop (not a good idea):
Array.prototype.pop = function() {
return 'SORRY I WANT THAT ELEMENT, I WILL NEVER POP IT OFF!';
};
const nums = [ 6, 7, 8, 9 ];
nums.pop(); // "SORRY I WANT THAT ELEMENT, I WILL NEVER POP IT OFF!"
<Factory Function 옳지 않은 예시>
function hex (r, g, b) {
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
function rgb (r, g, b) {
return `rgb(${r},${g},${b})`;
}
hex(255, 100, 25);
rgb(255, 100, 25);
function makeColor (r, g, b) {
//펑션안에 메소드를 추가해서 어디서나 접근가능
const color = {};
color.r = r;
color.g = g;
color.b = b;
color.rgb = function () {
const { r, g, b } = this;
//return `rgb(${r},${g},${b})`;
};
color.hex = function () {
const { r, g, b } = this;
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16) + slice(1);
};
return color;
}
const firstColor = makeColor(35, 40, 190);
firstColor.hex();
firstColor.rgb();
const black = makeColor(0, 0, 0);
black.hex();
black.rgb();
firstColor.hex !== black.hex
: 프로토타입에 저장된 메소드들과는 달리 두메소드는 각자의 firstColor와 black객체를 참조하기 떄문에 참조값이 다름
'hello'.slice === 'hi'.slice
: slice가 String.prototype.slice를 참조하기 때문
<THE NEW OPERATOR!>
function Color (r, g, b) {
this.r = r;
this.g = g;
this.b = b;
//console.log(this); // window obj를 프린트
}
//프로토타입을 이용해 프로토타입안에 메소드를 정의
Color.prototype.rgb = function () {
const { r, g, b } = this;
return `rgb(${r},${g},${b})`;
};
Color.prototype.hex = function () {
const { r, g, b } = this;
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16) + slice(1);
};
Color.prototype.rgba = function (a = 1.0) {
const { r, g, b } = this;
return `rgba(${r},${g},${b},${a})`;
};
//-> We develope recipe for Color
const color1 = new Color(255, 40, 100);
const color2 = new Color(0, 0, 0);
//new를 붙혀새로운 obj를 생성
color1.rgba(0.4);
-> 콘솔을 통해 color1, 2을 확인하면 color1, 2의 _proto_안에 rgb, hex 메소드가 정의된 것을 확인 할 수 있음
color1.rgb === color2.rgb
color1.hex === color2.hex
: Colol.prototype에 정의된 메소드를 참조하기 때문
<THE CLASS!>
클래스를 이용해 위의 코드를 재구성
class Color {
// constructor is function that excuted immediately whenever new color is created.
constructor (r, g, b, name) {
this.r = r;
this.g = g;
this.b = b;
this.name = name;
}
innerRGB () {
const { r, g, b } = this;
return `${r},${g},${b}`;
}
rgb () {
return `rgb(${this.innerRGB()})`;
}
rgba (a = 1.0) {
return `rgba(${this.innerRGB()}, ${a})`;
}
hex () {
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16) + slice(1);
}
}
//Color.prototype.rgb
//Color.prototype.rgba
//Color.prototype.hex
const color1 = new Color(255, 45, 78, 'tomato');
const color2 = new Color(255, 255, 255, 'white');
//color1.hex === color2.hex //true
color1.rgba(0.5);
<MORE CLASS!!>
class Color {
constructor(r, g, b, name) {
this.r = r;
this.g = g;
this.b = b;
this.name = name;
this.calcHSL();
}
innerRGB() {
const { r, g, b } = this;
return `${r}, ${g}, ${b}`;
}
rgb() {
return `rgb(${this.innerRGB()})`;
}
rgba(a = 1.0) {
return `rgba(${this.innerRGB()}, ${a})`;
}
hex() {
const { r, g, b } = this;
return (
'#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)
);
}
hsl() {
const { h, s, l } = this;
return `hsl(${h},${s}%, ${l}%)`;
}
fulllySaturated() {
const { h, l } = this;
return `hsl(${h},100%, ${l}%)`;
}
opposite() {
const { h, s, l } = this;
const newHue = (h + 180) % 360;
return `hsl(${newHue},${s}%, ${l}%)`;
}
calcHSL() {
let { r, g, b } = this;
// Make r, g, and b fractions of 1
r /= 255;
g /= 255;
b /= 255;
// Find greatest and smallest channel values
let cmin = Math.min(r, g, b),
cmax = Math.max(r, g, b),
delta = cmax - cmin,
h = 0,
s = 0,
l = 0;
if (delta == 0) h = 0;
else if (cmax == r)
// Red is max
h = ((g - b) / delta) % 6;
else if (cmax == g)
// Green is max
h = (b - r) / delta + 2;
else
// Blue is max
h = (r - g) / delta + 4;
h = Math.round(h * 60);
// Make negative hues positive behind 360°
if (h < 0) h += 360;
// Calculate lightness
l = (cmax + cmin) / 2;
// Calculate saturation
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
// Multiply l and s by 100
s = +(s * 100).toFixed(1);
l = +(l * 100).toFixed(1);
this.h = h;
this.s = s;
this.l = l;
}
}
const red = new Color(255, 67, 89, 'tomato');
red.hsl();
red.opposite();
red.rgba(0.3);
const white = new Color(255, 255, 255, 'white');