Programming/JAVASCRIPT

[JAVASCRIPT]함수와 프로토타입 체이닝(2)

100winone 2019. 12. 4. 17:43

함수 호출과 this

arguments 객체

자바스크립트는 함수를 호출할 때 함수 형식에 맞춰 인자를 넘기지 않더라도 에러가 나지 않음

ex) 함수 형식에 맞춰 인자를 넘기지 않더라도 함수 호출 가능 코드

function func(arg1, arg2) {

console.log(arg1, arg2);

}

func(); // (출력) undefined undefined

func(1); // (출력) 1 undefined

func(1, 2); // (출력) 1 2

func(1, 2, 3); // (출력) 1 2

* 만약 C를 이런 방식으로 코딩하면 바로 에러를 내며 프로그램 종료

* 이러한 자바스크립트의 특성 때문에 함수 코드 작성시, 런타임 시에 호출된 인자의 개수를 확인하고 이에 따른 동작을 다르게 해줘야 하는 경우가 존재

-> 이를 가능하게 해주는 것이 arguments 객체

자바스크립트에서 함수를 호출할 때 인수들과 함께 암묵적으로 arguments 객체가 함수 내부로 전달 (유사 배열 객체)

ex) arguments 객체 예제 코드

// add() 함수

function add(a, b) {

// arguments 객체 출력

console.dir(arguments);

return a + b;

}

console.log(add(1)); // (출력) NaN

console.log(add(1, 2)); // (출력) 3

console.log(add(1, 2, 3)); // (출력) 3

 

* console.dir(arguments)를 실행시 length: 로 인자의 갯수 같이 넘어감

* arguments 객체는 매개변수 개수가 정확하게 정해지지 않은 함수를 구현하거나, 전달된 인자의 개수에 따라 서로 다른 처리를 해줘야 하는 함수를 개발하는 데 유용하게 사용할 수 있음

ex) 이런식으로 접근 가능

function sum() {

var result = 0;

 

for (var i = 0; i < arguments.length; i++) {

result += arguments[i];

}

return ;

}

console.log(sum(1, 2, 3)); // (출력) 6

console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9)); // (출력) 45

호출 패턴과 this 바인딩

* 자바스크립트에서 함수 호출할 때, 기존 매개변수로 전달되는 인자값에 더해, arguments 객체 및 this 인자가 함수 내부로 암묵적으로 전달

객체의 메서드 호출할 때 this 바인딩

* 메서드를 호출할 때, 메서드 내부 코드에서 사용된 this는 해당 메서드를 호출한 객체로 바인딩

ex) 메서드 호출 사용 시 this 바인딩

// myObject 객체 생성

var myObject = {

name: 'baek',

sayName: function() {

console.log(this.name);

}

};

//otherObject 객체 생성

var otherObject = {

name: 'bar'

};

// otherObject.sayName() 메서드

otherObject.sayName = myObject.sayName;

// sayName() 메서드 호출

myObject.sayName();

otherObject.sayName();

(출력)

baek

bar

함수를 호출할 때 this 바인딩

* 자바스크립트에서는 함수를 호출하면 , 해당 함수 내부 코드에서 사용된 this는 전역 객체에 바인딩'

ex) 전역 객체와 전역 변수의 관계를 보여주는 예제

var baek = "I'm baek"; // 전역 변수 선언

console.log(baek); // (출력) I'm baek

console.log(window.baek); // (출력) I'm baek

* 전역 변수는 전역 객체(window)의 프로퍼티로도 접근할 수 있음

ex) 함수를 호출할 때 this 바인딩을 보여주는 예제

var test = 'This is test';

console.log(window.test);

//sayHan() 함수

var sayHan = function() {

console.log(this.test); // sayHan() 함수 호출시 this는 전역 객체에 바인딩

};

sayHan();

(출력)

This is test

This is test

* 내부함수를 호출했을 경우에도 그대로 적용되므로, 내부 함수에서 this 이용시 주의!

ex) 내부 함수의 this 바인딩 동작을 보여주는 예제

// 전역 변수 value 정의

var value = 100;

// myObject 객체 생성

var myObject = {

value: 1,

func1: function() {

this.value += 1;

console.log('func1() called. this. value : ' + this.value);

func2 = function() {

that.value += 1;

console.log('fun2() called, this.value: ' + this.value);

// func3() 내부 함수

func3 = function() {

that.value += 1;

console.log('func3() called. this.value : ' + this.value);

}

 

func3(); // func3() 내부 함수 호출

}

func2() 내부 함수 호출

}

};

myObject.func1(); // func1() 메서드 호출

(출력)

func1() called - this.value : 2

func2() called - this.value : 101

func3() called - this.value : 102

* 예상과 다른 이유는 내부 함수 호출 패턴을 정의해 놓지 않기 때문

* 내부 함수도 결국 함수라 이를 호출시 함수 호출 패턴 규칙에 따라 내부 함수의 this는 전역 객체(window)에 바인딩

// 내부 함수가 this를 참조하는 자바스크립트의 한계를 극복하기위해 부모 함수(위에 경우 func1() 메서드)의 this를 내부 함수가 접근 가능한 다른 변수에 저장하는 방법 사용

* 관례상 this 값을 저장하는 변수의 이름 that 이라 칭함

ex) 내부 함수의 this 바인딩 문제를 해결한 예제

// 내부 함수 this 바인딩

var value = 100;

// myObject 객체 생성

var myObject = {

value: 1,

func1: function() {

var that = this;

this.value += 1;

console.log('func1() called. this. value : ' + this.value);

// func2() 내부 함수

func2 = function() {

that.value += 1;

console.log('fun2() called, this.value: ' + that.value);

// func3() 내부 함수

func3 = function() {

that.value += 1;

console.log('func3() called. this.value : ' + that.value);

}

 

func3(); // func3() 내부 함수 호출

}

func2() 내부 함수 호출

}

};

myObject.func1(); // func1() 메서드 호출

* func1() 에서 this를 that이라는 변수에 저장하고, 이후 내부 변수에서는 that으로 부모 함수의 this가 가리키는 객체에 접근

생성자 함수를 호출할 때 this 바인딩

* 여러가지 다른 인자를 넘김으로써 같은 형태의 서로 다른 객체를 생성할 수 있음

ex) 생성자 함수

function Person(name, age, gender, position) {

this.name = name;

this.age = age;

this.gender = gender;

}

// Person 생성자 함수를 이용해 bar 객체, baz 객체 생성

var bar = new Person('bar', 33, 'woman');

console.dir(bar);

var baz = new Person('baz', 25, 'woman');

console.dir(baz);

* 객체 리터럴 방식과 생성자 함수 방식의 차이는 프로토타입 객체(__proto__ 프로퍼티)에 있음

* 객체 리터럴 방식 프로토타입 객체 : Object.prototype

* 생성자 함수 방식 프로토타입 객체 : 생성자 함수 자체가 프로토 타입 객체가 됨

-> 예제에서는 Person.prototype