ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Javascript] ํ”„๋กœํ† ํƒ€์ž…๊ณผ ํ”„๋กœํ† ํƒ€์ž… ์ƒ์†
    Language/JavaScript 2023. 1. 3. 15:22
    ๐Ÿ“Œ ์ถœ์ฒ˜ : https://ko.javascript.info/

    ํ”„๋กœํ† ํƒ€์ž… ์ƒ์†

    [[Prototype]]

    ์ •์˜

    ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๊ฐ์ฒด๋Š” [[Prototype]]์ด๋ผ๋Š” ์ˆจ๊น€ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ–๋Š”๋‹ค. ์ด ๊ฐ’์€ null์ด๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ๋˜๋Š”๋ฐ, ๋‹ค๋ฅธ ๊ฐ์ฑ„๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒฝ์šฐ ๊ทธ ์ฐธ์กฐ ๋Œ€์ƒ์„ ํ”„๋กœํ† ํƒ€์ž…์ด๋ผ ๋ถ€๋ฅธ๋‹ค.

    ๋™์ž‘๋ฐฉ์‹

    const animal = {
    	eats: true
    }
    const rabbit = {
    	jumps:true
    }
    
    console.log(rabbit.eats) // undefined
    
    Object.setPrototypeOf(rabbit, animal) //rabbit.__proto__ = animal;
    
    console.log(rabbit.eats) // true

    ํ”„๋กœํผํ‹ฐ๊ฐ€ ์ •์˜๋œ ๊ฐ์ฒด ๋‘ ๊ฐœ์˜ ์˜ˆ์‹œ๋ฅผ ๋ณด์ž.

    ๊ฐ์ฒด rabbit๊ฐ€ ๊ฐ–๋Š” ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผํ•  ๋•Œ, ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ๊ฐ€ ์—†์œผ๋ฉด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ์ž๋™์œผ๋กœ ํ”„๋กœํ† ํƒ€์ž…์—์„œ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ฐพ๋Š”๋‹ค. ๊ฐ์ฒด rabbit์€ jumps๋ผ๋Š” ํ”„๋กœํผํ‹ฐ๋งŒ์„ ๊ฐ–๊ณ  ์žˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ rabbit์€ ๋™์‹œ์— animal์ด๊ธฐ ๋•Œ๋ฌธ์— eats๋ผ๋Š” ํ”„๋กœํผํ‹ฐ์—๋„ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๊ณ ์‹ถ๋‹ค๋ฉด, ์–ด๋–ป๊ฒŒ ํ• ๊นŒ? ์ด ๋•Œ, ํ”„๋กœํ† ํƒ€์ž… ์ƒ์†์ด๋ผ๋Š” ๋™์ž‘ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    [[Prototype]] ํ”„๋กœํผํ‹ฐ๋Š” ๋‚ด๋ถ€ ํ”„๋กœํผํ‹ฐ์ด๋ฉด์„œ ์ˆจ๊น€ ํ”„๋กœํผํ‹ฐ์ด์ง€๋งŒ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์œ„ ์˜ˆ์‹œ์ฒ˜๋Ÿผ __proto__์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด์— ๋”ฐ๋ผ rabbit์— animal์ด๋ผ๋Š” ํ”„๋กœํ† ํƒ€์ž…์„ ์ง€์ •ํ•ด์ฃผ๋ฉด, ์—ฌ์ „ํžˆ rabbit์—๋Š” eats๋ผ๋Š” ํ”„๋กœํผํ‹ฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์ง€๋งŒ, ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ๊ฐ€ ์—†์œผ๋ฉด ์ž๋™์œผ๋กœ ํ”„๋กœํ† ํƒ€์ž…์—์„œ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ฐพ์•„ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

     

    ์ฆ‰ ๊ฐ์ฒด rabbit์—์„œ ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผํ•˜๊ณ  ์‹ถ์ง€๋งŒ ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ๊ฐ€ ์—†๋‹ค๋ฉด ์ž๋™์œผ๋กœ animal์ด๋ผ๋Š” ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด์—์„œ ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผํ•˜๊ฒŒ ๋œ๋‹ค. ์ด๋Ÿฌํ•œ ๊ด€๊ณ„๋ฅผ “rabbit์˜ ํ”„๋กœํ† ํƒ€์ž…์€ animal์ด๋‹ค” ํ˜น์€ “rabbit์€ animal์„ ์ƒ์†๋ฐ›๋Š”๋‹ค”๊ณ  ๋งํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋ ‡๊ฒŒ ์ƒ์†๋ฐ›์€ ํ”„๋กœํผํ‹ฐ๋ฅผ ‘์ƒ์† ํ”„๋กœํผํ‹ฐ’๋ผ๊ณ  ํ•œ๋‹ค.

     

    ๐Ÿ“Œ __proto__๋Š” [[Prototype]] ์šฉ getter, setter์ด๋‹ค. ํ•˜์œ„ ํ˜ธํ™˜์„ฑ ๋•Œ๋ฌธ์— ์—ฌ์ „ํžˆ __proto__๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ทผ๋ž˜์—๋Š” Object.getPrototypeOf๋‚˜ Object.setPrototypeOf์„ ์จ์„œ ํ”„๋กœํ† ํƒ€์ž…์„ getํ•˜๊ฑฐ๋‚˜ set ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

     

    ํ”„๋กœํ† ํƒ€์ž… ์ƒ์†์€ ํ”„๋กœํผํ‹ฐ ๋ฟ๋งŒ์•„๋‹ˆ๋ผ ๋ฉ”์†Œ๋“œ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

    const animal = {
    	eats: true,
    	walk() {
    		console.log("๋™๋ฌผ์€ ๊ฑธ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.")
    	}
    }
    const rabbit = {
    	jumps:true,
    	__proto__: animal
    }
    
    rabbit.walk() // ๋™๋ฌผ์€ ๊ฑธ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    

    ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์€ ๋”์šฑ ๊ธธ์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

    const animal = {
    	eats: true,
    	walk() {
    		console.log("๋™๋ฌผ์€ ๊ฑธ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.")
    	}
    }
    
    const rabbit = {
    	jumps:true,
    	__proto__: animal
    }
    
    const longEar = {
    	earLength: 10,
    	__proto__: rabbit
    }
    
    longEar.walk() // ๋™๋ฌผ์€ ๊ฑธ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    console.log(longEar.jumps) // true
    

    ๋‹จ, ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ด๋‹์—” ๋‘ ๊ฐ€์ง€ ์ œ์•ฝ์‚ฌํ•ญ์ด ์žˆ๋‹ค.

    1. ์ˆœํ™˜ ์ฐธ์กฐ๋Š” ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค. __proto__๋ฅผ ์ด์šฉํ•ด ๋‹ซํžŒ ํ˜•ํƒœ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
    2. __proto__์˜ ๊ฐ’์€ ๊ฐ์ฒด๋‚˜ null๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค. ๋‹ค๋ฅธ ์ž๋ฃŒํ˜•์€ ๋ฌด์‹œ๋œ๋‹ค.
    3. ๊ฐ์ฒด๋Š” ๋‘ ๊ฐœ์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์†๋ฐ›์ง€ ๋ชปํ•œ๋‹ค.

    ํ”„๋กœํ† ํƒ€์ž…์€ ์ฝ๊ธฐ ์ „์šฉ์ด๋‹ค

    ํ”„๋กœํ† ํƒ€์ž…์€ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ฝ์„ ๋•Œ๋งŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    ํ”„๋กœํผํ‹ฐ๋ฅผ ์ถ”๊ฐ€, ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์ง€์šฐ๋Š” ์—ฐ์‚ฐ์€ ๊ฐ์ฒด์— ์ง์ ‘ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    ๊ฐ์ฒด rabbit์— ๋งค์„œ๋“œ walk๋ฅผ ์ง์ ‘ ํ• ๋‹นํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

    const animal = {
    	eats:true,
    	walk() {
    		console.log("๋™๋ฌผ์€ ๊ฑธ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.")
    	}
    }
    
    const rabbit = {
    	__proto__: animal
    }
    
    rabbit.walk = () => {console.log("ํ† ๋ผ๊ฐ€ ๊นก์ถฉ๊นก์ถฉ ๋’ต๋‹ˆ๋‹ค.")}
    
    rabbit.walk() // ํ† ๋ผ๊ฐ€ ๊นก์ถฉ๊นก์ถฉ ๋œ๋‹ˆ๋‹ค.
    

    rabbit.walk()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ”„๋กœํ† ํƒ€์ž…์—์žˆ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š๊ณ , ๊ฐ์ฒด rabbit์— ์ง์ ‘ ์ถ”๊ฐ€ํ•œ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋Š” setter ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ํ”„๋กœํผํ‹ฐ์— ๊ฐ’์„ ํ• ๋‹นํ•˜๋ฏ€๋กœ ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ์— ๊ฐ’์„ ํ• ๋‹น (**)ํ•˜๋ฉด ๊ฐ์ฒด(admin)์— ํ”„๋กœํผํ‹ฐ(fullName)๊ฐ€ ์ถ”๊ฐ€๋˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ setter ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด์„œ ์œ„ ์˜ˆ์‹œ์™€๋Š” ์กฐ๊ธˆ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•œ๋‹ค.

    ์•„๋ž˜ ์˜ˆ์‹œ์—์„œ admin.fullName์ด ์˜๋„ํ•œ ๋Œ€๋กœ ์ž˜ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•ด๋ณด์ž

    const user = {
    	name: "John",
    	surname:"Smith",
    
    	set fullName(value) {
    		[this.name, this.surname] = value.split(" ")
    	},
    
    	get fullName() {
    		return `${this.name} ${this.surname}`
    	}
    }
    
    const admin = {
    	__proto__: user,
    	isAdmin: true
    }
    
    console.log(admin.fullName) // "John Smith" (*)
    
    admin.fullName = "Alice Cooper" // setter ํ•จ์ˆ˜ ์‹คํ–‰
    console.log(admin.fullName) // "Alice Cooper" (**)
    console.log(user.fullName) // "John Smith"

    this๊ฐ€ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ

    this๋Š” ํ”„๋กœํ† ํƒ€์ž…์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋Š”๋‹ค. ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ์ฒด์—์„œ ํ˜ธ์ถœํ–ˆ๋“  ํ”„๋กœํ† ํƒ€์ž…์—์„œ ํ˜ธ์ถœํ–ˆ๋“  ์ƒ๊ด€์—†์ด this๋Š” ์–ธ์ œ๋‚˜ . ์•ž์— ์žˆ๋Š” ๊ฐ์ฒด์ด๋‹ค.

    this๋Š” ๊ฐ์ฒด ์ž์‹ ์˜ ํ”„๋กœํผํ‹ฐ๋‚˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์ฐธ์กฐํ•˜๊ธฐ ์œ„ํ•œ ์ž๊ธฐ์ฐธ์กฐ ๋ณ€์ˆ˜๋‹ค.
    this๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ’, ์ฆ‰ this ๋ฐ”์ธ๋”ฉ์€ ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ฐฉ์‹์— ๋”ฐ๋ผ ๋™์ ์œผ๋กœ ๊ฒฐ์ •๋œ๋‹ค.

    [this๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ’]
    - ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ์„œ ํ˜ธ์ถœ ํ•  ๋•Œ : ์ „์—ญ ๊ฐ์ฒด(๋ธŒ๋ผ์šฐ์ € - window, Node.js - global)
    - ๋ฉ”์„œ๋“œ๋กœ ํ˜ธ์ถœ : ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด(dot notation ์•ž์˜ ๊ฐ์ฒด)
    - ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ์„œ ํ˜ธ์ถœ : ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค
    const animal = {
    	walk() {
    		if(!this.isSleeping) {
              console.log("๋™๋ฌผ์ด ๊ฑธ์–ด๊ฐ„๋‹ค.")
    		} else {
              console.log("์ž๋Š” ๋™๋ฌผ์€ ๊ฑธ์„ ์ˆ˜ ์—†๋‹ค.")
            }
    	},
    	sleep() {
    		this.isSleeping = true
    	},
        awake() {
            this.isSleeping = false
        }
    }
    
    const rabbit = {
    	name :"ํ•˜์–‘ํ† ๋ผ",
    	__proto__: animal
    }
    
    // rabbit์— ์ƒˆ๋กœ์šด ํ”„๋กœํผํ‹ฐ isSleeping์„ ์ถ”๊ฐ€ํ•˜๊ณ  ๊ทธ ๊ฐ’์„ true๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.
    rabbit.sleep();
    console.log(rabbit.isSleeping) // true
    rabbit.walk() // "์ž๋Š” ๋™๋ฌผ์€ ๊ฑธ์„ ์ˆ˜ ์—†๋‹ค."
    
    rabbit.awake();
    console.log(rabbit.isSleeping) // false
    rabbit.walk() // "๋™๋ฌผ์ด ๊ฑธ์–ด๊ฐ„๋‹ค."
    console.log(animal.isSleeping)// undefined (ํ”„๋กœํ† ํƒ€์ž…์—๋Š” isSleeping์ด๋ผ๋Š” ํ”„๋กœํผํ‹ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.)
    

    for..in ๋ฐ˜๋ณต๋ฌธ

    for in ๋ฐ˜๋ณต๋ฌธ์€ ์ƒ์† ํ”„๋กœํผํ‹ฐ๋„ ์ˆœํšŒ ๋Œ€์ƒ์— ํฌํ•จ์‹œํ‚จ๋‹ค.

    const animal = {
    	eats: true
    }
    
    const rabbit = {
    	jumps: true,
    	__proto__: animal
    }
    
    console.log(Object.keys(rabbits)) // [jumps]
    
    for(let prop in rabbit) console.log(prop) // jumps, eats
    

    ๊ทธ๋ž˜์„œ ์ƒ์† ํ”„๋กœํผํ‹ฐ๋ฅผ ์ˆœํšŒ์—์„œ ์ œ์™ธํ•˜๋ ค๋ฉด obj.hasOwnProperty(key)๋ฅผ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค.

    const animal = {
    	eats: true
    }
    
    const rabbit = {
      jumps: true,
      __proto__: animal
    };
    
    for (let prop in rabbit) {
    	const isOwn = rabbit.hasOwnProperty(prop)
    	if(isOwn) {
    		console.log(`๊ฐ์ฒด ์ž์‹ ์˜ ํ”„๋กœํผํ‹ฐ : ${prop}`)
    	} else {
    		console.log(`์ƒ์† ํ”„๋กœํผํ‹ฐ : ${prop}`)
    	}
    }
    // "๊ฐ์ฒด ์ž์‹ ์˜ ํ”„๋กœํผํ‹ฐ: jumps"
    // "์ƒ์† ํ”„๋กœํผํ‹ฐ : eats"
    

    ๊ทธ๋Ÿฐ๋ฐ, hasOwnProperty()๋Š” rabbit์— ์—†๋Š” ๋ฉ”์†Œ๋“œ์ด๋‹ค. ์ด๊ฑด ์–ด๋–ป๊ฒŒ ์“ธ ์ˆ˜ ์žˆ์—ˆ๋‚˜?

    ๋ฐ”๋กœ, rabbit์˜ ํ”„๋กœํ† ํƒ€์ž… animal์˜ ํ”„๋กœํ† ํƒ€์ž…์ด Object์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. (์ฐธ๊ณ ๋กœ Object์˜ prototype์€ null์ด๋‹ค!) animal์˜ ํ”„๋กœํ† ํƒ€์ž…์ด Object์ธ ๊ฒƒ์€ animal์„ ๊ฐ์ฒด๋ฆฌํ„ฐ๋Ÿด ๋ฐฉ์‹์œผ๋กœ ์„ ์–ธํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

    ์ด๊ฒŒ ๋ฌด์Šจ๋ง์ด๋ƒ ?

    ๊ทธ๋ฆฌ๊ณ  ์ฝ˜์†”์— hasOwnProperty ๋ฉ”์†Œ๋“œ๊ฐ€ ์ฐํžˆ์ง€ ์•Š์•˜๋‹ค. ๊ทธ ์ด์œ ๋Š” hasOwnProperty๋Š” ์—ด๊ฑฐ ๊ฐ€๋Šฅํ•œ(enumerable) ํ”„๋กœํผํ‹ฐ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. Object.prototype์— ์žˆ๋Š” ๋ชจ๋“  ๋ฉ”์„œ๋“œ์˜ enumerable ํ”Œ๋ž˜๊ทธ๋Š” false์ธ๋ฐ for..in์€ ์˜ค์ง ์—ด๊ฑฐ ๊ฐ€๋Šฅํ•œ ํ”„๋กœํผํ‹ฐ๋งŒ ์ˆœํšŒ ๋Œ€์ƒ์— ํฌํ•จํ•˜๊ธฐ ๋•Œ๋ฌธ์— hasOwnProperty๋Š” ์ฝ˜์†”์— ์ถœ๋ ฅ๋˜์ง€ ์•Š์€ ๊ฒƒ์ด๋‹ค.

     

    ๐Ÿ“Œ ํ‚ค-๊ฐ’์„ ์ˆœํšŒํ•˜๋Š” ๋ฉ”์„œ๋“œ ๋Œ€๋ถ€๋ถ„์€ ์ƒ์† ํ”„๋กœํผํ‹ฐ๋ฅผ ์ œ์™ธํ•˜๊ณ  ๋™์ž‘ํ•œ๋‹ค. Object.keys, Object.values ๊ฐ™์ด ๊ฐ์ฒด์˜ ํ‚ค-๊ฐ’์„ ๋Œ€์ƒ์œผ๋กœ ์ˆœํšŒํ•˜๋Š” ๋ฉ”์„œ๋“œ ๋Œ€๋ถ€๋ถ„์€ ์ƒ์† ํ”„๋กœํผํ‹ฐ๋ฅผ ์ œ์™ธํ•˜๊ณ  ๋™์ž‘ํ•œ๋‹ค.

     

    ๋Œ“๊ธ€