πŸ’» this(JavaScript)

waterglassesΒ·2022λ…„ 10μ›” 1일
0

TIL

λͺ©λ‘ 보기
36/50
post-thumbnail

⚠️ μ •λ¦¬ν•œ λ‚΄μš©μ€ μ˜€νƒ€λ‚˜ 잘λͺ»λœ 정보가 μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. λŒ“κΈ€λ‘œ μ•Œλ €μ£Όμ‹œλ©΄ κ°μ‚¬ν•˜κ² μŠ΅λ‹ˆλ‹€.

πŸ“ƒ 였늘 κ³΅λΆ€ν•œ 것

ν•¨μˆ˜ μ‹€ν–‰μ—μ„œμ˜ this

ν•¨μˆ˜ μ‹€ν–‰μ—μ„œμ˜ thisλŠ” μ „μ—­ 객체닀

μ „μ—­ κ°μ²΄λŠ” μ‹€ν–‰ν•˜λŠ” ν™˜κ²½λ§ˆλ‹€ λ‹€λ¦…λ‹ˆλ‹€. μ›Ή λΈŒλΌμš°μ €μ—μ„œλŠ” window 객체가 μ „μ—­ 객체가 λœλ‹€.

function sum(a, b) {  
   console.log(this === window); // => true
   this.myNumber = 20; // μ „μ—­ 객체에 'myNumber'λΌλŠ” 속성을 μΆ”κ°€
   return a + b;
}

// sum()은 ν•¨μˆ˜ ν˜ΈμΆœμ΄λ‹€.
// sum()μ—μ„œμ˜ thisλŠ” μ „μ—­ 객체닀. (window)
sum(15, 16);     // => 31  
window.myNumber; // => 20

λ˜ν•œ thisκ°€ ν•¨μˆ˜ μŠ€μ½”ν”„ λ°–(μ΅œμƒλ‹¨: μ „μ—­ μ‹€ν–‰ λ¬Έλ§₯)μ—μ„œ μ‚¬μš©λ˜μ—ˆμ„ 경우, μ—¬κΈ°μ„œμ˜ this μ—­μ‹œ μ „μ—­ 객체λ₯Ό μ°Έμ‘°ν•˜κ²Œ λœλ‹€.

console.log(this === window); // => true  
this.myString = 'Hello World!';  
console.log(window.myString); // => 'Hello World!'

엄격 λͺ¨λ“œ ν•¨μˆ˜ μ‹€ν–‰μ—μ„œμ˜ this

엄격 λͺ¨λ“œμ—μ„œ ν•¨μˆ˜ μ‹€ν–‰μ—μ„œμ˜ thisλŠ” undefined이닀.

μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ 엄격 λͺ¨λ“œλŠ” ES5μ—μ„œ λ“±μž₯ν•˜μ˜€μœΌλ©°, μ½”λ“œ μ•ˆμ •μ„±κ³Ό 더 λ‚˜μ€ 였λ₯˜ 검증을 μ œκ³΅ν•˜κΈ° μœ„ν•΄ λ“±μž₯ν•˜μ˜€λ‹€. use strict λ₯Ό μ‚¬μš©ν•˜μ—¬ 엄격 λͺ¨λ“œλ₯Ό μ μš©μ‹œν‚¬ 수 μžˆλ‹€.

function multiply(a, b) {  
  'use strict'; // 엄격 λͺ¨λ“œ
  console.log(this === undefined); // => true
  return a * b;
}

// multiply() ν•¨μˆ˜λŠ” 엄격 λͺ¨λ“œλ‘œ 싀행됨
// multiply()μ—μ„œμ˜ thisλŠ” undefined
multiply(2, 5); // => 10

엄격 λͺ¨λ“œμ—μ„œλŠ” this의 값이 window μ „μ—­ 객체λ₯Ό μ°Έμ‘°ν•˜μ§€ μ•Šκ³  undefined 둜 λ§Œλ“ λ‹€.

엄격 λͺ¨λ“œλŠ” ν˜„μž¬ μŠ€μ½”ν”„ 뿐만 μ•„λ‹ˆλΌ λ‚΄λΆ€ μŠ€μ½”ν”„μ—μ„œλ„ μ μš©λ©λ‹ˆλ‹€.

function execute() {  
   'use strict'; // 엄격 λͺ¨λ“œ
   function concat(str1, str2) {
     // μ΄κ³³μ—μ„œλ„ λ§ˆμ°¬κ°€μ§€λ‘œ 엄격 λͺ¨λ“œ
     console.log(this === undefined); // => true
     return str1 + str2;
   }

   // concat() ν•¨μˆ˜λŠ” 엄격 λͺ¨λ“œ
   // concat() ν•¨μˆ˜ μ•ˆμ—μ„œμ˜ thisλŠ” undefined
   concat('Hello', ' World!'); // => "Hello World!"
}
execute();

λ‚΄λΆ€ ν•¨μˆ˜μ—μ„œμ˜ thisλ₯Ό μ‚¬μš©ν•  λ•Œ

λ‚΄λΆ€ ν•¨μˆ˜μ˜ λ¬Έλ§₯은 μ™ΈλΆ€ ν•¨μˆ˜μ˜ λ¬Έλ§₯에 μ˜μ‘΄ν•˜λŠ” 것이 μ•„λ‹ˆλΌ 였직 μ‹€ν–‰ ν™˜κ²½μ— μ’Œμš°λœλ‹€.

var numbers = {  
   numberA: 5,
   numberB: 10,
   sum: function() {
     console.log(this === numbers); // => true
     function calculate() {
       // thisλŠ” window, 엄격 λͺ¨λ“œμ˜€μœΌλ©΄ undefined
       console.log(this === numbers); // => false
       return this.numberA + this.numberB;
     }
     return calculate();
   }
};
numbers.sum(); // NaN, 엄격 λͺ¨λ“œμ˜€μœΌλ©΄ TypeError

numbers.sum()은 객체 내에 μžˆλŠ” λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” 것이닀. λ”°λΌμ„œ thisλŠ” numbers λ₯Ό 가리킨닀.

ν•˜μ§€λ§Œ calculate() λŠ” λ©”μ†Œλ“œ 싀행이 μ•„λ‹Œ ν•¨μˆ˜ 싀행이닀. 이 ν•¨μˆ˜μ—μ„œμ˜ thisλŠ” window λ₯Ό 가리킨닀.(엄격λͺ¨λ“œλΌλ©΄ undfined)

이 문제의 ν•΄κ²°μ±… 쀑 ν•˜λ‚˜λ‘œ .call λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 방법이 μžˆλ‹€.

var numbers = {  
   numberA: 5,
   numberB: 10,
   sum: function() {
     console.log(this === numbers); // => true
     function calculate() {
       console.log(this === numbers); // => true
       return this.numberA + this.numberB;
     }
     // λ¬Έλ§₯을 μˆ˜μ •ν•˜κΈ° μœ„ν•΄ .call() λ©”μ†Œλ“œλ₯Ό 적용
     return calculate.call(this);
   }
};
numbers.sum(); // => 15

λ©”μ†Œλ“œ μ‹€ν–‰μ—μ„œμ˜ this

ν•¨μˆ˜ μ‹€ν–‰κ³Ό λ©”μ†Œλ“œ 싀행은 μ„œλ‘œ λ‹€λ₯΄λ‹€. κ°€μž₯ 큰 차이점은 λ©”μ†Œλ“œ 싀행은 속성 μ ‘κ·Όμžλ₯Ό μ‚¬μš©ν•˜μ—¬ ν˜ΈμΆœν•œλ‹€.

thisλŠ” λ©”μ†Œλ“œ μ‹€ν–‰μ—μ„œ λ©”μ†Œλ“œλ₯Ό μ†Œμœ ν•˜κ³  μžˆλŠ” 객체이닀.

var myDog = Object.create({  
  sayName: function() {
     console.log(this === myDog); // => true
     return this.name;
  }
});
myDog.name = 'Milo';  
// λ©”μ†Œλ“œ μ‹€ν–‰. μ—¬κΈ°μ„œμ˜ thisλŠ” myDog.
myDog.sayName(); // => 'Milo'

ES6의 class μ˜ˆμ•½μ–΄μ—μ„œμ˜ thisλŠ” μΈμŠ€ν„΄μŠ€ μžμ‹ μ„ 가리킨닀.

class Planet {  
  constructor(name) {
    this.name = name;    
  }
  getName() {
    console.log(this === earth); // => true
    return this.name;
  }
}

var earth = new Planet('Earth');  
// λ©”μ†Œλ“œ μ‹€ν–‰. μ—¬κΈ°μ„œμ˜ thisλŠ” earth.
earth.getName(); // => 'Earth'

μƒμ„±μž ν•¨μˆ˜μ—μ„œμ˜ this

μƒμ„±μž μ‹€ν–‰μ—μ„œμ˜ thisλŠ” μƒˆλ‘­κ²Œ λ§Œλ“€μ–΄μ§„ 객체이닀.

function Foo () {  
  console.log(this instanceof Foo); // => true
  this.property = 'Default Value';
}
// μƒμ„±μž μ‹€ν–‰
var fooInstance = new Foo();  
fooInstance.property; // => 'Default Value'

μ—¬κΈ°μ„œ 잠깐, λ§Œμ•½ newλ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ ν•¨μˆ˜ 싀행이 λ˜λ―€λ‘œ thisλŠ” window객체λ₯Ό κ°€λ¦¬ν‚€κ²Œ λœλ‹€.

function Vehicle(type, wheelsCount) {  
  this.type = type;
  this.wheelsCount = wheelsCount;
  return this;
}
// Function invocation
var car = Vehicle('Car', 4);  
car.type;       // => 'Car'  
car.wheelsCount // => 4  
car === window  // => true

call(), apply()와 bind()

callκ³Ό apply

κ°„μ ‘ 싀행인 .call()κ³Ό .apply() λ©”μ†Œλ“œμ—μ„œλŠ” 첫 번째 맀개 λ³€μˆ˜λ‘œ thisλ₯Ό λ°›λŠ”λ‹€.

두 λ©”μ„œλ“œλŠ” λ„˜κ²¨λ°›λŠ” 인자의 ν˜•μ‹λ§Œ λ‹€λ₯Ό 뿐, thisλ₯Ό νŠΉμ • 객체에 λ°”μΈλ”©ν•˜μ—¬ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” 역할을 ν•œλ‹€.

callκ³Ό apply의 κ°€μž₯ 큰 차이점은 callλ©”μ„œλ“œλŠ” 인수λ₯Ό κ·ΈλŒ€λ‘œ λ„˜κΈΈ 수 μžˆμ§€λ§Œ applyλ©”μ„œλ“œλŠ” ν•¨μˆ˜μ— 전달할 μΈμžλ“€μ„ λ°°μ—΄ ν˜•νƒœλ‘œ μ „λ‹¬ν•΄μ•Όν•œλ‹€λŠ” 것이닀.

bind

비인딩 ν•¨μˆ˜λŠ” 일반 ν•¨μˆ˜μ— .bind() λ©”μ„œλ“œκ°€ 적용된 것을 μ˜λ―Έν•œλ‹€. bind λ©”μ„œλ“œμ˜ 첫 번째 μΈμžλ‘œλŠ” 바인딩 ν•¨μˆ˜μ— μ μš©ν•  thisλ₯Ό λ°›λŠ”λ‹€. 그리고 ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” 것이 μ•„λ‹ˆλΌ μƒˆλ‘œμš΄ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•œλ‹€.

function multiply(number) {  
  'use strict';
  return this * number;
}
// λ¬Έλ§₯을 μ§€μ •ν•΄μ„œ 바인딩 ν•¨μˆ˜λ₯Ό 생성
var double = multiply.bind(2);  
// 바인딩 ν•¨μˆ˜λ₯Ό μ‹€ν–‰
double(3);  // => 6  
double(10); // => 20

ν™”μ‚΄ν‘œ ν•¨μˆ˜μ—μ„œμ˜ this

ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” ν•¨μˆ˜κ°€ μ–΄λ–»κ²Œ ν˜ΈμΆœλ˜μ—ˆλŠ”μ§€μ— 따라 this에 바인딩할 객체가 λ™μ μœΌλ‘œ κ²°μ •λœλ‹€. ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ this μ–Έμ œλ‚˜ μƒμœ„ μŠ€μ½”ν”„μ˜ thisλ₯Ό 가리킨닀

class Point {  
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  log() {
    console.log(this === myPoint); // => true
    setTimeout(()=> {
      console.log(this === myPoint);      // => true
      console.log(this.x + ':' + this.y); // => '95:165'
    }, 1000);
  }
}
var myPoint = new Point(95, 165);  
myPoint.log();

μžμ£Όν•˜λŠ” μ‹€μˆ˜ - ν™”μ‚΄ν‘œ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ„œλŠ” μ•ˆλ˜λŠ” 경우

1. prototype

function Period (hours, minutes) {  
  this.hours = hours;
  this.minutes = minutes;
}
Period.prototype.format = () => {  
  console.log(this === window); // => true
  return this.hours + ' hours and ' + this.minutes + ' minutes';
};
var walkPeriod = new Period(2, 30);  
walkPeriod.format(); // => 'undefined hours and undefined minutes'

format은 ν™”μ‚΄ν‘œ ν•¨μˆ˜κ³ , 전역에 μ •μ˜ λ˜μ—ˆκΈ° λ•Œλ¬Έμ— μ—¬κΈ°μ„œμ˜ thisλŠ” μƒμœ„ μ»¨ν…μŠ€νŠΈμΈ μ „μ—­ 객체 windowλ₯Ό κ°€λ¦¬ν‚€κ²Œ λœλ‹€.

2. λ©”μ†Œλ“œ

// Bad
const person = {
  name: 'Lee',
};

Object.prototype.sayHi = () => console.log(`Hi ${this.name}`);

person.sayHi(); // Hi undefined

3. μƒμ„±μž ν•¨μˆ˜

const Foo = () => {};

// ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” prototype ν”„λ‘œνΌν‹°κ°€ μ—†λ‹€
console.log(Foo.hasOwnProperty('prototype')); // false

const foo = new Foo(); // TypeError: Foo is not a constructor

ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” μƒμ„±μž ν•¨μˆ˜κ°€ 가지고 μžˆμ–΄μ•Ό ν•  prototype ν”„λ‘œνΌν‹°κ°€ μ—†λ‹€.

4. addEventListener ν•¨μˆ˜μ˜ 콜백 ν•¨μˆ˜

// Bad
var button = document.getElementById('myButton');

button.addEventListener('click', () => {
  console.log(this === window); // => true
  this.innerHTML = 'Clicked button';
});

addEventListener ν•¨μˆ˜μ˜ 콜백 ν•¨μˆ˜λ₯Ό ν™”μ‚΄ν‘œ ν•¨μˆ˜λ‘œ μ •μ˜ν•˜λ©΄ thisκ°€ μƒμœ„ μ»¨νƒμŠ€νŠΈμΈ μ „μ—­ 객체 windowλ₯Ό 가리킨닀.

πŸ”₯ λŠλ‚€μ 

this μ–΄λŠ κ²½μš°μ— μ–΄λ–»κ²Œ μ μš©λ˜λŠ”μ§€ ν•˜λ‚˜ν•˜λ‚˜ 체크할 수 μžˆμ—ˆλ‹€. ν™”μ΄νŒ…~

Refer

profile
맀 μˆœκ°„ μ„±μž₯ν•˜λŠ” κ°œλ°œμžκ°€ 되렀고 λ…Έλ ₯ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

0개의 λŒ“κΈ€