Advanced Object in js

9343 단어 jsjs

The this Keyword in obj

const goat = {
  dietType: 'herbivore',
  makeSound() {
    console.log('baaa');
  },
  diet() {
    console.log(dietType);
  }
};
goat.diet(); 
// Output will be "ReferenceError: dietType is not defined"

Why? 왜 goat 객체는 diet 매소드를 인보킹 했을때 dietType을 접근할수 없을까. - That’s because inside the scope of the .diet() method, we don’t automatically have access to other properties of the goat object. 객체 안에서의 매소드는 같은 객체의 프로퍼티 dietType을 리퍼런스를 할수 없다 허나, this.를 쓴다면 가능

const goat = {
  dietType: 'herbivore',
  makeSound() {
    console.log('baaa');
  },
  diet() {
    console.log(this.dietType);
  }
};
goat.diet(); // herbivore

객체안의 this 키워드는 그 객체의 프로퍼티를 접근 할수있게 한다.
The this keyword references the calling object which provides access to the calling object’s properties. In the example above, the calling object is goat and by using this we’re accessing the goat object itself, and then the dietType property of goat by using property dot notation.

Arrow Functions and this keyword

const goat = {
  dietType: 'herbivore',
  makeSound() {
    console.log('baaa');
  },
  diet: () => {
    console.log(this.dietType);
  }
};
 
goat.diet(); // Prints undefined


출처: https://kim-solshar.tistory.com/57 [김솔샤르의 인사이트]

Arrow functions inherently bind, or tie, an already defined this value to the function itself that is NOT the calling object. In the code snippet above, the value of this is the global object, or an object that exists in the global scope, which doesn’t have a dietType property and therefore returns undefined.

애로우 함수에 this 는 항상 자신을 둘러싸고 있는 상위 환경의 this 그대로 계승하는 Lexical this를 따른다.

  • 애로우 함수를 객체 매소드로 사용을 못한다. - this가 글로벌 객체를 가리키게 된다.
  • 애로우 함수는 생성자 함수로 사용을 못한다. - 생성자 함수로 생성자 함수를 만들순 없다. 왜냐하면 arrow function에는 prototype이 없기 때문.
const Foo = () => { console.log(this); } 

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

출처: https://kim-solshar.tistory.com/57 [김솔샤르의 인사이트]
  • 매소드를 프로토타입에 할당할때 애로우 함수를 쓰면 문제가 생긴다.(this 로 프로토 타입 프로퍼티를 액세스 할때 undefined나올수 있다)
const person = { name: 'Lee', }; 

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

person.sayHi(); // Hi undefined

//출처: https://kim-solshar.tistory.com/57 [김솔샤르의 인사이트]
  • addEventListener의 콜백함수를 arrow function으론 안된다.- ㅁrrow function은 부모 scope의 this를 계승하므로 이 경우 this는 window를 가리키게 되는 것이다. 일반 함수로 고쳐주자.
const box = document.getElementById('box'); 

box.addEventListener('click', () => { console.log(this); //window });

출처: https://kim-solshar.tistory.com/57 [김솔샤르의 인사이트]


이미지 출처: Dmtri Pavlutin

Privacy for object in js

When discussing privacy in objects, we define it as the idea that only certain properties should be mutable or able to change in value.

Certain languages have privacy built-in for objects, but JavaScript does not have this feature. Rather, JavaScript developers follow naming conventions that signal to other developers how to interact with a property. One common convention is to place an underscore _ before the name of a property to mean that the property should not be altered.

const person = {
  _firstName: 'John',
  _lastName: 'Doe',
  get fullName() {
    if (this._firstName && this._lastName){
      return `${this._firstName} ${this._lastName}`;
    } else {
      return 'Missing a first name or a last name.';
    }
  }
}
 
// To call the getter method: 
person.fullName; // 'John Doe'
  • Getters can perform an action on the data when getting a property.
  • Getters can return different values using conditionals.
  • In a getter, we can access the properties of the calling object using this.
  • The functionality of our code is easier for other developers to understand.

Another thing to keep in mind when using getter (and setter) methods is that properties cannot share the same name as the getter/setter function. If we do so, then calling the method will result in an infinite call stack error. One workaround is to add an underscore before the property name like we did in the example above.

Setters for object in js

Along with getter methods, we can also create setter methods which reassign values of existing properties within an object.

const person = {
  _age: 37,
  set age(newAge){
    if (typeof newAge === 'number'){
      this._age = newAge;
    } else {
      console.log('You must assign a number to age');
    }
  }
};

Nonetheless, even with a setter method, it is still possible to directly reassign properties. For example, in the example above, we can still set ._age directly:

person._age = 'forty-five'
console.log(person._age); // Prints forty-five

Factory Functions 공장함수

There are times where we want to create many instances of an object quickly. Here’s where factory functions come in.

A factory function is a function that returns an object and can be reused to make multiple object instances.

const monsterFactory = (name, age, energySource, catchPhrase) => {
  return { 
    name: name,
    age: age, 
    energySource: energySource,
    scare() {
      console.log(catchPhrase);
    } 
  }
};

const ghost = monsterFactory('Ghouly', 251, 'ectoplasm', 'BOO!');
ghost.scare(); // 'BOO!'

Getter 와 Setter 는 왜써야 하는가

물론 두 getter, setter 객체 속성 접근 매소드들을 사용한다 할지라도 직접적으로 다른 개발자들이 객체값을 할당/변경 할수 있다. 허나, 그렇게 되면 피치못할 불상사(예기치 못한 결과나 에러)가 프로젝트에서 생길수 있으므로 getter 와 setter을 사용해 다른 개발자들한테 코드 의도를 알려줄수 있다.( 즉, 이 객체는 getter 랑 setter 를 쓰고 있으니 함부로 그 객체 값을 바꿔지 않을거에요 뉘앙스를 줄수 있다)

const dailyMenuSystem = {
	dish: '햄버거', 
	price: 0,
}

Property Value Shorthand

ES6 introduced some new shortcuts for assigning properties to variables known as destructuring.

In the previous exercise, we created a factory function that helped us create objects. We had to assign each property a key and value even though the key name was the same as the parameter name we assigned to it.

const monsterFactory = (name, age) => {
  return { 
    name,
    age 
  }
};

Destructured Assignment

const vampire = {
  name: 'Dracula',
  residence: 'Transylvania',
  preferences: {
    day: 'stay inside',
    night: 'satisfy appetite'
  }
};

// Too much keystrokes
const residence = vampire.residence; 
console.log(residence); // Prints 'Transylvania' 
// basic destructured assignment
const { residence } = vampire; 
console.log(residence); // Prints 'Transylvania'

// Renaming variables when destructring obj
const {residence: address} = vampire;

Review 2

  • The object that a method belongs to is called the calling object.
  • The this keyword refers to the calling object and can be used to access properties of the calling object.
  • Methods do not automatically have access to other internal properties of the calling object.
  • The value of this depends on where the this is being accessed from.
  • We cannot use arrow functions as methods if we want to access other internal properties.
  • JavaScript objects do not have built-in privacy, rather there are conventions to follow to notify other developers about the intent of the code.
  • The usage of an underscore before a property name means that the original developer did not intend for that property to be directly changed.
  • Setters and getter methods allow for more detailed ways of accessing and assigning properties.
  • Factory functions allow us to create object instances quickly and repeatedly.
  • There are different ways to use object destructuring: one way is the property value shorthand and another is destructured assignment.

Useful Refs:
getters/setters === access property by javascript.info

공장 / 생성자 / 클래스 by fromnowwon

Factory functions vs Constructors by https://chamikakasun.medium.com/javascript-factory-functions-vs-constructor-functions-585919818afe

Destructuring assignment

좋은 웹페이지 즐겨찾기