JS-기본3

dev.dave·2023년 7월 29일

Javascript

목록 보기
148/167

세번째 편

this

일단 this는 함수호출할때 어떻게 호출하냐 어떤방식으로 호출하냐로 정해진다

this 는 스코프를 가리키지않는다

상위 글로벌은 다 윈도우다

함수에서 this 는 인터프린터시점에 만들어지지않고 , 실행할때 만들어진다

함수를 실행시키면 this 랑 argument 가 만들어진다

함수안에서!!!! 함수 안에서다!
this 는 a.b.c.d() 이렇게 실행순서가 되어있다고 가정할때
쩜의 앞에 놈이 this 이다

이게 뭔말이냐면

어디서 실행했냐가 중요한것이다고, 어디서 실행시킨놈이 this이다

d()함수를 실행시킨놈은 c이다 그러므로 c가 this인 것이다

실행시킨 놈이 this이고 그게 바로 쩜 앞에 놈이란 말이다.


obj.a = cnosole.log(this) 이거는 this는 윕도우이다.

객체안에 들어가있다고해서 다른게 아니다


var obj = {
fn: function () {
console.log(this);
}
}
setTimeout(obj.fn , 100);

이거는 this가 뭐가 나올것같은가?

윈도우가 나온다 !
왜냐면

api 함수들을 쓰게되면 그 괄호안에 obj.fn 이렇게 넣는다고 해서 이게 실행이라는 뜻이아니다
obj.fn () 이렇게 되는게 실행을 하는거고,
저 셋타임아웃 함수인자로넘겨주는 괄호안에는 그냥 말그대로 넘겨주는 역할만 하는용도이다.

그래서 실제로 셋타임함수가 실행이 되는거지 저 obj.fn이 실행이되는게 아니기 떄문에 윈도우가 나오는거다

==============

var someone = {
name : 'codejong',
who : function() {
console.log(this);
}
};

someone.who(); // 이건 코드종이나온다

그러나

var mywho = someone.who;
mywho(); //이건 윈도우가 나온다

그리고

var btn = document.getElementById('btn');
btn.addEventListener('click', someone.who); // 이건 여기서 this는 버튼이 나온다 왜?

그냥 이벤트리스너 괄호안의 인자로 넘겨주는값이니까

그냥 값으로 넘겨줄뿐 실행은 되지않고 여기서 실행이 되는건 버튼이 실행이되고 값을 넘겨주는일을 하는것이다.

그 자체가 실행이 되야 this의 값은 그 부르는 객체가 될수 있지만

그저 값으로 넘겨주는 인자값으로 사용될떄는 그냥 그 api가 실행이될뿐이다.
마치 이코드는
btn.addEventListener('click', someone.who); === btn.addEventListener('click', mywho);

이렇게 볼수있다


var bindwho = mywho.bind(someone);
bindwho();
//여기서 this는 진짜 someone 이 나온다 왜? 바인드로 묶어주었기떄문이다.


this 의 값은 this를 사용하는 해당 함수를 어떻게 실행하느냐에 따라 바뀐다.

함수를 실행하는 방법엔 크게 4가지가 있습니다

(this를 이용하는) 해당함수를 이 4가지중 어떤 방식으로 실행하느냐에 따라 this의 값은 바뀝니다.


<함수 실행 방법 4가지>
1. foo(); 일반 함수 실행 방법(실행되는 부분을 찾아라) // window (참고로 스트릭트모드에서는 undefiend 나옴

예)

var age = 100;

function foo(){
var age = 99;
bar();
}

function bar(){
console.log(this.age); // 여기서 this는 윈도우를 가르킨다 왜?
}

foo();

왜냐면
일단 this.age를 실행시킨 함수를 찾아가보자
어디인가?
foo함수안에 bar() 여기서 실행이된다 근데
근데 문제는 일반함수 실행 하듯 실행했다 그래서 window로 되는거다.


<함수 실행 방법 4가지>
2. dot notation 방식 (점 방식)
ken.foo(); // 이런 방식임

예)

var age = 100;

var ken = {
age : 35,
foo : function foo (){
console.log(this.age);
}
};

ken.age();

여기서 this는 ken 객체를 가리킨다. (쩜 앞에있는 부분을 가르킨다)

또다른예)

var age = 100;

var ken = {
age : 25,
foo : function bar (){
console.log(this.age);
}
};

var wan = {
age : 31,
foo : ken.foo
};

var foo = ken.foo;

ken.foo(); // this값은 ken (dot notation 방식)
wan.foo(); // this 값은 wan (dot notation 방식)
foo(); // window (일반함수 방식)

====================

<함수 실행 방법 4가지>

3. 함수들이 같고있는 매소드들을 쓰는 방법  (function.prototype.call ,function.prototype.bind , function.prototype.apply)콜 , 바인드 , 어플리 
  • call / apply / bind 의 다른점은 인자 (프로퍼티)를 사용하는방법을 다루려고 하는것이다.

*this는 기본적으로 window라고 했었죠. 몇 가지 방법으로 window를 다른 것으로 바꿀 수 있는데요. call, apply, bind에서 첫 번째 인자로 다른 것을 넣어주는 게 this를 바꾸는 방법 중 하나입니다.

*메소드들을 쓰는 예로, 함수의 arguments를 조작할 때 사용합니다. arguments는 함수라면 처음부터 갖고 있는 숨겨진 속성인데요. 바로 함수에 들어온 인자를 배열 형식으로(배열은 아닙니다. 유사 배열이라고 부릅니다.) 반환합니다.

*call 의 쓰임새는...일단 함수에서 arguments 를 반환하면 유사배열로 나오는데 진짜 배열이 아니므로 배열로바꿔주려면 join()을 써야되는데
그냥 쓰면 에러나서 Array.prototype.join.call(arguments) 이런식으로 쓰면 에러가 안나고 진짜 배열로 출력이되는거다 그래서
즉, call 을 왜쓰냐면 arguments를 배열로 만들떄 쓰는거다

*배열의 프로토타입에 있는 join 함수를 빌려 쓰는겁니다. this는 arguments를 가리키게 하고요. join 외에도 slice, concat 등등 모든 메소드를 이 방식으로 사용할 수 있습니다.

예)

var age = 100;

function foo(){
console.log(this.age);
}

var ken = {
age : 34
};

var bar = foo.bind(ken);

bar(); // 34

여기서 foo.bind(ken) 에서 함수가 바로 실행이되는게 아니고 bar에 담아줘서 bar()을 실행하게 해야 실행이된다.

*bind 함수는 함수가 가리키는 this만 바꾸고 호출하지는 않는 겁니다. 즉 bind 는 call이나 apply와 비슷하지만 호출은 하지 않지 않고 함수만 반환하는 겁니다.

<함수 실행 방법 4가지>

  1. new 카워드

새로운거

새로운 객체가 생성되 생긴다

빈 객체가 새롭게 생기는거다 어디에도 this에도!

함수 실행 앞에 new 를 붙이면 그 함수는 빈객첵가 추가로 할당이되어 생긴다 this가 있으면 this에도 빈 객체가 할당이 된다.
빈 객체로 함수가 실행이 된다

예 1)

function foo(){
console.log(this);
}

new foo();

new 가 되면 실제로

new foo 함수 안에

this = {

};

이렇게 빈 객체가 생성이 되고

그다음

원래 foo함수 안에 있던 내용들이 새로운 foo함수에 할당이 된다

this = {
name : '바닐라코딩'
}
이런식으로 객체로 할당이 된다

그리고 이 함수에 자동적으로 리턴이 생기는 데 return this; 이렇게 이 함수를 리턴시킨다

정확히는

function (){
this.name = 'ken'
return this

}

이건 다른코드인데
이런식으로도 순서는 이렇게 된다

var Person = function (name) {

// 객체 리터럴로 새로운 객체를 생성한다.
// var this = {};

// 프로퍼티와 메서드를 추가한다.
this.name = name;
this.say = function () {
return 'I am ' + this.name;
};
// this를 반환한다.
// return this;
};


원래 say는 이렇게 되어진다
Person.prototype.say = function () { return 'I am ' + this.name; };

그리고
빈 객체가 아니라
// var this = Object.create(Person.prototype);

이렇게 생성된다

=============

  • 생성자 함수

function Person (name,age){
this.name = name;
this.age = age;
}

//called "instance"
var ken = new Person ('ken huh',34); //생성자함수
var wan = new Person ('wan huh',30);

console.log(ken);
console.log(wan);

============================

profile
🔥개인 메모 / 다른블로그 자료 참조 / 다른블로그 자료 퍼옴 (출처표기) /여기저기서 공부 했던 내용 개인메모 & 참고 / 개인 기록 용도 블로그 입니다.🔥

0개의 댓글