반응형

call, apply, bind는 함수의 실행 컨텍스트(this)를 지정하는데 유용한 메소드이다.

this란 함수가 실행된 환경을 나타내는 것으로 보통은 함수가 실행되는 시점에 결정되며 이를 this가 함수에 바인딩된다고 한다.

여기서 바인딩 되는 this를 지정할 수 있게 해주는 것이 call, apply 이고, 바인딩되는 시점을 실행 시점으로부터 독립시켜주는 것이 bind 이다.

 

call, apply 의 경우 호출 즉시 this가 바인딩되고 함수가 실행된다. 차이점은 파라미터가 나열형(call)이냐 배열(apply)이냐 정도이다.


this를 지정한다는 것은 아무 값이나 지정할 수 있다는 의미는 아니고, 다음과 같이 생성자 체이닝으로 this를 통해 다른 메소드의 프로퍼티를 가져오는 효과를 얻을 수 있다.

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.call(this, name, price); // equivalent to `Product.apply(this, [name, price]);`
  this.category = "food";
}

const burger = new Food("burger", 10);
/*
  burger = {
    name: "burger",
    price: 10,
    category: "food",
  };
*/

Food에서 Product.call을 호출하는 순간 this는 Product가 아닌 Food로써 바인딩되므로, Food의 프로퍼티로 name, price가 설정되는 것이다.

Product와 무슨 연관이 있는거 아닌가하는 의문이 든다면, burger의 prototype을 비교해보면 된다.

burger.__proto__ === Product.prototype // false
burger.__proto__ === Food.prototype // true

반면에 위와 달리 연관성을 주입하려면 다음과 같이 작성해볼 수 있을 것이다.

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  const product = new Product(name, price);
  product.category = "food";
  return product;
}

const burger = new Food("burger", 10);

 

burger의 출력물은 동일하지만 이 경우 burger는 Product가 된다.

burger.__proto__ === Product.prototype // true
burger.__proto__ === Food.prototype // false

bind는 첫 번째 파라미터로 전달한 변수에 bind를 호출한 시점의 this를 설정한다. 호출 시 함수가 반환되는데, 이 함수를 호출하면 바인딩한 메소드가 실행된다. bind를 사용하여 위 예시를 구현하면 다음과 같다.

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  const product = Product.bind(this, name, price);
  this.category = "food";
  product();
}

const burger = new Food("burger", 10);

결과는 동일하다.

반응형
반응형

1. getter, setter 활용

const myObj = {
  this.someProperty = someValue;
  
  get someProperty() {
    return this.someProperty
  }
  
  set someProperty(newValue) {
    this.someProperty = newValue;
    alert("someProperty is changed!");
  }
};

 

2. defineProperty 활용

defineProperty 메소드는 세 번째 파라미터로 descriptor를 제공하는데, 여기에서도 getter, setter를 설정할 수 있다.

const myObj = {
  someProperty: someValue,
};

Object.defineProperty(myObj, "someProperty", {
  get() {
    return this.someProperty;
  },
  set(newValue) {
    this.someProperty = newValue;
    alert("someProperty is changed!");
  },
});

 

 

위 두 방식을 활용할 경우 myObj.someProperty 의 값이 변경되면 alert으로 이를 감지할 수 있다.

이 전에 작성했던 getter 와 setter 의 사용 글에서 언급하지 않았던 부가적인 기능으로 볼 수 있겠다.

반응형
반응형

코드를 먼저 보면 다음과 같다.

 

http.get을 통해 리모트 경로의 파일을 요청하고 응답으로 반환되는 Readable한 객체의 pipe 메소드를 통해 csv-parser를 실행시켜 주면된다.

 

참고로 readStream과 writeStream이 존재할 때 pipe는 다음과 동일하게 변경할 수 있다.

const readStream = fs.createReadStream("some file"); // response
const writeStream = fs.createWriteStream("another file");

readStream.on("data", (chunk) => {
  writeStream.write(chunk);
});
// can be ==> readStream.pipe(writeStream);

gist 예시의 pipe를 제거해보려고 했으나, 아직은 어떻게 하는지 모르겠고 csv-parser 모듈에도 그런 설명이 없어 넘어가기로 한다.

 

csv-parser 모듈의 리드미에는 로컬에 존재하는 csv파일을 기준으로 아주 쉽게 설명되어 있으나, 막상 이를 리모트 파일로 변경하려다보니 온갖 이슈(파일을 다 읽기 전에 파싱을 시작해버린다거나, 이전에 읽은 것이 남아 있다거나...)가 발생하였다.

 

stream과 pipe에 대해 대략적으로라도 알고 시작했으면 더 빨리 해결할 수 있었을텐데 하는 아쉬움이 남는다.

더 유명한 csv 파싱 모듈로 papaparse가 있는데, 이것도 마찬가지로 리모트 파일에 대한 공식 예시 코드가 없어 어려움이 있었다.

 

좀 더 파악이 되면 다시 시도해봐도 좋을 것 같다.

반응형

+ Recent posts