(동결, 밀봉, 확장 금지)
Object.freeze
수정과 추가, 삭제, 쓰기, 속성 재정의 불가능
const hwuiinn = { name: "호이인" };
const pat = { name: "초코", emoji: "🐶", owner: hwuiinn };
Object.freeze(pat);
pat.name = "왈왈";
console.log(" pat : ", pat);
pat.age = 5;
console.log(" pat : ", pat);
delete pat.name;
console.log(" pat : ", pat);
hwuiinn.name = "호이잉이니"; // 얕은 동결(?) 때문에 pat이 참조하고 있는 hwuiinn 객체는 수정이 가능하다.
console.log(" pat : ", pat);
Object.seal
밀봉된 객체는 값의 수정이 가능.
But, 추가, 삭제, 속성 재정의 불가능.
// 오브젝트 밀봉. Object.seal
// 밀봉된 객체는 값의 수정 가능.
// 추가, 삭제, 속성 재정의 불가능.
const cat = { ...pat };
// Object.assign(cat, pat);
// assign을 이용하면 복사가 가능하다. (cat 객체에 dog 프로퍼티를 모두 복사한다.)
// Object.assign(cat, pat); === const cat = {...pat};
Object.seal(cat);
console.log(" cat : ", cat);
cat.name = "야오옹";
console.log(" cat : ", cat);
delete cat.emoji;
console.log(" cat : ", cat);
console.log(cat.emoji);
Object.preventExtensions
밀봉된 객체는 추가만 불가능.
But, 추가, 삭제, 속성 재정의 가능.
// 확장 금지 preventExtensions
// 추가만 불가능.
// 삭제, 수정, 속성 재정의 가능
const tiger = { name: "호랑이" };
Object.preventExtensions(tiger);
console.log(" tiger : ", tiger);
console.log(" Object.isExtensible(tiger) : ", Object.isExtensible(tiger));
tiger.name = "호으으응";
console.log(" tiger : ", tiger);
delete tiger.name;
console.log(" tiger : ", tiger);
tiger.age = 1;
console.log(" tiger : ", tiger);
// 동결, 밀봉되었는지 확인할 수 있는 함수?
console.log(" Object.isFrozen(pat) : ", Object.isFrozen(pat));
console.log(" Object.isSealed(cat) : ", Object.isSealed(cat));
Boolean 값으로 알려준다.
요약
객체에서 가질 수 있는 함수 세 가지
1. 인스턴스 레벨 함수 / 2. 프로토타입 레벨 함수 / 3. 정적 레벨 함수
모든 인스턴스마다 가지고있을 인스턴스 레벨 함수,
각각의 인스턴스에서 공통적으로 가질 수 있는 프로토타입 레벨 함수,
생성자 함수 이름, 클래스 이름으로만 접근가능한 정적 레벨 함수.
function Dog(name, emoji) {
this.name = name;
this.emoji = emoji;
// 인스턴스 레벨의 함수 => 메모리 낭비가 될 수 있다.
this.printName = () => {
console.log(`${this.name} ${this.emoji}`);
};
}
왜 사용하는가? (내 생각)
function Dog(name, emoji) {
this.name = name;
this.emoji = emoji;
}
// 프로토타입 레벨의 함수
Dog.prototype.printName = function () {
console.log(`${this.name}!! ${this.emoji}!!!`);
};
const dog1 = new Dog("몽몽쓰", "🐶");
const dog2 = new Dog("갱갱쓰", "🐈");
console.log(" dog1, dog2 : ", dog1, dog2);
dog1.printName();
dog2.printName();
function Dog(name, emoji) {
this.name = name;
this.emoji = emoji;
}
// 프로토타입 레벨의 함수
Dog.prototype.printName = function () {
console.log(`${this.name}!! ${this.emoji}!!!`);
};
const dog1 = new Dog("몽몽쓰", "🐶");
const dog2 = new Dog("갱갱쓰", "🐈");
console.log(" dog1, dog2 : ", dog1, dog2);
dog1.printName();
dog2.printName();
// 오버라이딩
dog1.printName = function () {
console.log("오버라이딩 된 것");
};
dog1.printName();
// dog1에서 printName()에 접근 할 경우, 콘솔에 console.log("오버라이딩 된 것");이 뜬다.
//반면 dog2에서 접근할 경우, 덮어씌워지지 않은 프로토타입 레벨의 함수값이 출력된다.
function Dog(name, emoji) {
this.name = name;
this.emoji = emoji;
}
// 정적(Static) 레벨
// 정적 레벨 함수는 생성자 네임으로 접근해야 한다.
Dog.static = () => {
console.log("Static Level function");
};
// dog1.static(); 접근 불가함.
Dog.static();
Dog.MAX_AGE = 20;
console.log(" Dog : ", Dog);
알고 넘어가기
Class
를 사용하여 구현한다.function Animal(name, emoji) {
this.name = name;
this.emoji = emoji;
}
Animal.prototype.printName = function () {
console.log(`${this.name} ${this.emoji}`);
};
function Dog(name, emoji, owner) {
// super(name, emoji) => 부모 프로퍼티를 사용할 수 있도록 해줌.
// Static.call() => 생성자 프로퍼티를 사용할 수 있도록 해줌.
// 즉, super와 동일한 기능이라고 생각하면 된다.
Animal.call(this, name, emoji);
this.owner = owner;
}
//Dog의 프로토타입을 object가 아닌 Animal로 변경. (프로토타입 체인을 변경)
// 변경 전 : Dog.prototype = Object.create(Object.prototype);
Dog.prototype = Object.create(Animal.prototype); // 변경 후
Dog.prototype.play = () => {
console.log("놀아달라몽");
};
const dog1 = new Dog("멍멍쓰", "🐶", "민수");
dog1.play();
dog1.printName();
function Tiger(name, emoji) {
Animal.call(this, name, emoji);
}
Tiger.prototype = Object.create(Animal.prototype);
Tiger.prototype.hunt = () => {
console.log("저녁을 찾고 있습니다.");
};
const tiger1 = new Tiger("어어흥흥", "🐯");
tiger1.printName();
tiger1.hunt();
// 어떤 것을 상속하고 있는지 확인하는 방법
console.log(dog1 instanceof Dog); // true
console.log(dog1 instanceof Animal); // true
console.log(dog1 instanceof Tiger); // false
오브젝트는 단 하나의 Prototype
을 가리킬 수 있다. (== 부모는 단 하나만)
하지만, 다중 상속 방법이 있음(여러 함수를 상속하는). 그게 Mixin
이다.
Class
를 사용해도 실직적으로 프로토타입을 사용한다 볼 수 있다.
Object.assign(상속받을 생성자 함수.prototype, 상속받을 속성1, 상속받을 속성2 ...);
const play = {
play: function () {
console.log(`${this.name} 놀자고!!!!`);
},
};
const sleep = {
sleep: function () {
console.log(`${this.name} 자니까 제발 깨우지 마.`);
},
};
function Dog(name) {
this.name = name;
}
// Mixin
Object.assign(Dog.prototype, play, sleep);
const dog = new Dog("왈왈이");
console.log(dog);
dog.play();
dog.sleep();
class Animal {}
class Tiger extends Animal {
constructor(name) {
super();
this.name = name;
}
}
// 매우 중요
// 자바스크립트는 본질적으로 프로토타입을 베이스로 한 프로그래밍 언어임. 클래스를 사용해도 실직적으로 프로토타입을 사용한다 볼 수 있다.
// 그 증거로 class를 사용하여도 mixin 적용 가능함.
Object.assign(Tiger.prototype, play, sleep);
const tiger1 = new Tiger("호랭이");
console.log(tiger1);
tiger1.play();
tiger1.sleep();
특정 두 가지 함수와 렉시컬환경 콤비네이션.
내부 함수에서 외부 함수에 있는 상태에 접근할 수 있는 권한을 주는 것.
- 자신이 생성될 때의 렉시컬 환경을 기억하는 함수다.
- 클로저에 의해 참조되는 외부함수의 변수를 자유변수라고 부른다.