[JS] This, Reference values, coping objects

hoje15v·2021년 12월 7일
0

JavaScript

목록 보기
31/82
post-thumbnail

강의 출처 : The Complete JavaScript Course 2022 Jonas (Udemy)

Section 8 - How JavaScript Works Behind the Scenes

This keyword

▪️ This keyword variable : Special variable that is created for every execution context(every function). Takes the value of (points to) the 'owner' of the function in which the this keyword is used.

This is not static(not always same). It depends on how the functions is called and its value is only assigned when the function is actually called.

Method -> this = object that is calling the method
Simple function -> this = undefined (strict mode 에서만! 그렇지 않을 경우 this는 window를 가리킨다.)
Arrow function -> this를 받지 않는다. 그대신 lexical this를 받음.(자신과 가장 가까운 함수의 scope에서 this값을 받아온다.)
Eventlistener -> this = DOM element that the handler is attached to

주의) This does NOT point to the function itself, and also NOT the its variable environment!

주의) Arrow function 을 object method로 쓰지말자! (this 못받으므로)

console.log(this) // window

Simple function

const calcAge = function (birthYear) {
  console.log(2037 - birthYear);
  console.log(this);
};

calcAge(1991); // 46 , undefined 출력

Arrow function

const calcAgeArrow = birthYear => {
  console.log(2037 - birthYear);
  console.log(this);
};

calcAgeArrow(1980); // window 출력 (arrow function은 this keyword를 받지 않기 때문 lexical this : window )

Method

// const jonas = {
//   year: 1991,
//   calcAge: function () {
//     console.log(this); //jonas object 자체를 출력
//     console.log(2037 - this.year); //46 출력
//   },
// };

// jonas.calcAge(); 

const matilda = {
  year: 2017,
};


matilda.calcAge = jonas.calcAge;


matilda.calcAge(); //20 => this keyword는 항상 method를 부르는 object를 가리킨다!

const f = jonas.calcAge;
f(); // this.year이 undefined로 나옴 why? f()자체가 regular function (there's no owner of this f function. 감싸고 있는 객체가 없음.)

self 와 arrow function 활용하기

method 내의 일반함수에서 this를 사용할 시 undefined가 나온다.
why? 일반함수 내에 있는 것이므로 객체 안에 있어도 this에 접근할 수 없음

이를 해결하기 위해 self 와 arrow function 활용할 수 있다.
ex) 1. Solution 1 - self

onst jonas = {
  firstName: 'Jonas',
  year: 1991,
  calcAge: function () {
    console.log(2037 - this.year);

 const self = this;

     const isMillenial = function () {
   //console.log(this.year >= 1981 && this.year <= 1996); => undefined
    console.log(self.year >= 1981 && self.year <= 1996); //true
    };
    isMillenial();
  },

  greet: () => console.log(`Hey, ${this.firstName}`),
};

jonas.greet(); // Hey, undefined (its parents this key word 이용 => global scope(window object))
// jonas={ } block scope X, 그냥 객체 그 자체임!

// 참고) var firstName = 'Matilda'; => jonas.greet() HEY, Matilda 로 출력됌. (window에 var 가 자동으로 포함되므로!)

ex) Solution 2 - arrow function
arrow function 자체가 this를 받지 않기 때문에 이를 감싸고 있는 method가 받고있는 this(객체인 jonas)를 받을 수 있는 것!
주의) method 안이 아닌 그냥 객체 안에 들어있는 arrow function 에서의 this는 window를 가리킨다는 점! 객체의 block은 그저 그 객체 자체를 가리키는 것이므로!!

onst jonas = {
  firstName: 'Jonas',
  year: 1991,
  calcAge: function () {
    console.log(2037 - this.year);
    const isMillenial = () => {
      console.log(this.year >= 1981 && this.year <= 1996); //true
    };
    isMillenial();
  },
};

arguments keyword

일반함수에만 존재한다. modern JS에서 자주 쓰이지는 않음.

const addExpr = function (a, b) {
  console.log(arguments);
  return a + b;
};
addExpr(2, 5); // arguments가 배열 형태로 출력된다.
addExpr(2, 3, 4, 55);

var addArrow = (a, b) => {
  console.log(arguments);
  return a + b;
};

//addArrow(2, 3); // Error - arguments is not defined

Primitive vs Reference values

Primitive type은 callstack에 indentifier, address, value 가 모두 저장이 되며,
Reference type은 value값이 heap 내에 reference 형태로 저장이 된다. callstack에는 identifier와 address만 저장된다.

Primitive types


let lastName = 'Williams';
let oldLastName = lastName;
lastName = 'Davis';
console.log(lastName, oldLastName); // Davis Williams

Reference types

const jessica = {
  firstName: 'Jessica',
  lastName: 'Williams',
  age: 27,
};

const marriedJesscial = jessica;
marriedJesscial.lastName = 'David';
console.log('Before marriage:', jessica); // lastName : 'David'
console.log('After marriage:', marriedJesscial); // lastName : 'David'

Copying objects

Object.assign()

const jessica2 = {
  firstName: 'Jessica',
  lastName: 'Williams',
  age: 27,
  family: ['Alice', 'Bob'],
};

const jessicaCopy = Object.assign({}, jessica2);
jessicaCopy.lastName = 'Davis';

console.log('Before marriage:', jessica2); //lastName: 'Williams'

console.log('After marriage:', jessicaCopy); //lastName: 'Davis'

jessicaCopy.family.push('Mary');
jessicaCopy.family.push('John');

console.log('Before marriage:', jessica2); //둘다 자동으로 fammily 추가됌.
console.log('After marriage:', jessicaCopy);



family object => deeply nested object (여기까진 복사하지 못함! 결국 같은 object를 가리키고 있는 것! only first-level 만 복사 가능!)

JessciaCopy is the real copy of the original => new object was in fact created in the heap and JessciaCopy is now pointing to that object. So it has a reference to that new object.
But! using this technique of object.assign only works on the first level. In other words, if we have an object inside the object, then this inner object will still be the same. So it will still point to the same place in memory. => object.assign only creates a shallow copy. shallow copy will only copy the properties in the first level.

유의) const에 할당된 변수들은 primitive value만 immutable! (reference value는 바뀔 수 있다는 점 명심하기)

profile
A front web developer & passionate learner loving learning new things and working together with people🦋

0개의 댓글