2015년 5월 17일 일요일

[JavaScript] Closure(클로져)

Closure(클로져) 란 무엇인가?


자바스크립트에서 클로져란(Closure) 다른 함수의 스코프(Scope)내에 있는 변수들에 접근할 수 있는 함수를 뜻한다. 아래 코드를 보자.


function closureExample(exVar){
  return function(){
    return exVar;
  };
}

var foo = closureExample("foo");
var bar = closureExample("bar");

console.log(foo());
console.log(bar());

closureExample이라는 함수는 매개변수로 exVar를 받으며, 내부에서 anonymous function(익명 함수, 람다 함수)을 선언 후 반환한다. 반환되는 함수 closureExample함수의 스코프에서 선언되었기 때문에 closureExample함수의 매개변수로 주어진 exVar이라는 변수에 접근할 수 있다. 그리고 반환된 익명 함수는 function expression 방식으로 foobar라는 변수에 어싸인되게 된다.

그렇게 foo와 bar 함수를 실행하면, closureExample함수로 전달한 매개변수에 접근하는 함수가 반환된게 된다.

이게 가능한 이유는 자바스크립트의 Execution Context가 다른 Execution Context에 의해 참조되는 한 파기되지 않기 때문이다. Execution Context 와 스코프에 대해 자세한 글을 읽어볼려면 여기를 클릭하자

조금 더 정확히 말하자면, 반환되는 익명함수는 호출된 closureExample함수내에서 선언되었기 때문에 closureExample함수의 Execution Contextvariable environment 객체를 참조하고 있는데, 자바스크립트의 가비지 콜랙터(Garbage Collector)는, 객체가 다른 인스턴스에 의해 참조되고 있는 동안은 해당 객체를 사용 중으로 판단하여 객체에 할당된 메모리를 수집하지 않는다.

closureExample 함수 내에서 선언된 익명함수 객체가 반환되면서 function expression 방식으로 foo라는 변수에 의해 참조되게 되는데, 이렇게 되면서, 해당 익명함수의 variable environment 객체는 사용 중으로 마크되며, 사용 중으로 마크된 익명함수의 execution context가 closureExample 함수의 variable environment 객체를 참조하게 되니, 마찬가지로 closureExample의 variable environment 객체도 사용중으로 마크되게 된다.

이 때문에, closureExmaple함수의 실행이 끝나 정해진값을 반환했음에도 우리는 closureExample이 호출될 때 생성된 variable environment에 계속 접근이 가능하다.



2015년 5월 13일 수요일

[JavaScript] Regular Expression(정규표현식)과 RegExp 객체

정규표현식이란 특정 패턴의 문자열을 의미하며, 이를 통해 이 문자열에서 특정 단어나, 특정 패턴을 가진 문자열을 찾아낼 수 있다.

자바스크립트는 기본 내장(Built-in)객체로 RegExp 객체를 탑재하며, RegExp 객체의 test 또는 exec 메소드를 이용해 정규표현식을 이용한 패턴 매칭이 가능하다.

정규 표현식 패턴(Regular Expression Pattern)생성하기


정규 표현식의 패턴 여러 문자들로 이루어지며 사용자는 원하는 패턴을 두개의 /(Slash)사이에 적게된다. /(Slash)는 delimiter로써 프로그래밍 언어에서 해당 패턴의 시작과 끝을 알린다. 또한 / 뒤에 정규 표현식 검색 옵션을 적을 수도 있다.


var expression = /abc/; //abc문자열을 뜻한다.
var expression = /at/; //at문자열을 뜻한다.

이에 더해서 몇가지 특수문자를 이용해 조금 더 복잡한 패턴 생성이 가능하다.

특수문자의미
일반
\1. 일반 문자 앞에 올 경우에는, \를 포함한 일반문자를 특수문자로 해석한다.
2. 특수 문자 앞에 올 경우에는, Escape Chracter 의 역할을 한다, 즉 /\\/은 일반문자 "\"를 표현하는 표현식이다.
^문자열의 시작과 일치한다.
예) /^E/는 E로 시작하는 모든 문자열과 일치한다.
$문자열의 끝과 일치한다.
예)/E$/는 E로 끝나는 모든 문자열과 일치한다.
** 선행 문자가 0번이상 반복된다. {0,}과 같은 의미를 가진다.
/ab*/는 abbbbb, a, ab, 등과 일치하며, /ab*c/는 abbbbc, ac, abc, 등과 일치한다.
Quantifiers
++ 선행문자가 1번이상 반복된다. {1,}과 같은 의미를 가진다.
/ab+/는 abbbbb, ab 등과 일치하나, a와는 일치하지 않는다.
/ab+c/는 abbbc, abc등과 일치하나 ac와는 일치하지 않는다.
?1. 선행 문자가 0번 또는 1번 존재한다. {0,1}과 같은 의미를 가진다
2. 수량자(Quantifier, *, +, ?,{})의 뒤에 올때는 선행 수량자의 최소값만큼 일치한다.
예) /a{1,4}/ 패턴을 "aaaa"라는 문구에 사용시, "aaaa" 전체와 일치하나,
/a{1,4}?/ 패턴을 사용시에는 제일 앞의 a 한글자에만 일치한다
{n}선행 문자가 양의 정수 n 회만큼 발생한다
{n,m}선행 문자가 최소 n회, 최대 m회만큼 발생한다.
m이 비게되면 무한을 뜻한다, {n,}은 최소 n회이상을 의미
Group Constructors
(x)하위 패턴을 생성하며 \1, \2 와 같이 \숫자 문구를 이용해서 패턴을 재사용 가능하다.
예) 표현식 \([1-9]{3,}?)\-\1\-\1\ 은 \([1-9]{3,}?)\-([1-9]{3,}?)\-([1-9]{3,}?)\와 같다.
표현식 \(foo) (bar) \1 \1 \2\ 은 \(foo) (bar) \(foo) \(foo) \(bar)\와 같다.
(?:x)(x)와 같이 하위패턴을 생성하나, 패턴 재사용이 불가능하다.
x(?=y)x의 뒤에 y가 올때만 x와 일치한다.
x(?!y)x의 뒤에 y가 오지 않을 때만 x와 일치한다.
(x|y)x 또는 y와 일치한다.
Character Set
[xyz]문자 세트를 생성한다. -(hypen)을 이용해서 범위를 정할 수도 있다.
/[abcdefg]/ 는 /[a-g]/와 같으며 a,b,c,d,e,f,g 한 글자와 일치 한다.
[^xyz]문자 세트를 생성한다. 단, 해당 문자가 포함되지 않을 때 일치한다.
/[a-g]/는 a,b,c,d,e,f,g가 아닌 다른 문자 1개와 일치한다.
[x-z][xyz]와 같은 표현
[^x-z][^xyz]와 같은 표현
[x-zX-A]x-z범위 사이, 또는 X-A범위 사이의 모든 문자와 일치한다
Meta Character
[\b]Backspace와 일치한다.
\b와는 다른 의미를 가지니 조심할것.
.모든 문자와 일치한다.
\bWord Boundary(단어간의 경계)를 의미한다,
단어간의 경계는 길이가 0 이므로 \b는 언제나 다른 문자와 함께 사용된다.
예) /\bace/ 는 "acehigh"의 ace와 일치하며 /high\b/는 "acehigh"의 high와 일치한다.
단, /eh\b/나 /\beh/는 "acehigh"와 부분적으로 전혀 일치하지 않으며,
이는 "eh"문구가 단어내부에 포함되어 있기 때문이다
\B\b와는 반대로 non-word boundary를 의미한다,
위의 "acehigh"에서 "/\Beh\B/를 사용했을 때 "eh"와 일치하며,
이는 "eh" 앞뒤로 단어가 이어지기 때문이다.
\cX제어문자와 일치한다.
\d0-9 사이의 숫자와 일치한다.
\D0-9 사이의 숫자와 일차하지 않는 모든 문자와 일치한다.
[^0-9]와 같다.
\fform feed와 일치한다.
\nline feed와 일치한다.
\rcarriage return와 일치한다.
\ttab(탭)과 일치한다.
\vVertical Tab(수직 탭)과 일치한다.
\sspace, form feed, line feed, carriage return, tab등의 공간 문자와 일치한다.
\Sspace, form feed, line feed, carriage return, tab, vertical tab등의
공간 문자를 제외한 모든 문자와 일치한다.
\w"_"(underscore)을 포함한 모든 숫자 + 알파벳 문자와 일치한다.
/[A-Za-z0-9_]/와 같다.
\W\w와 일치하지 않는 모든 문자와 일치한다.
\숫자()로 생성되는 하위패턴을 재사용 가능하다.
\0Null 문자와 일치한다.
\xhh2자리 16진수 코드 hh를 가진 문자와 일치한다.
\uhhhh4자리 16진수 코드 hhhh를 가진 문자와 일치한다.


또한 RegExp 패턴 검색 옵션을 정하는 총 3개의 flag가 있다

g : Global Search, 패턴 검색이 처음 일치하는 스트링에서 멈추는 것이 아니라 전체 텍스트에 적용된다.
i : ignore case, 대소문자 관계없이 검색된다
m: multiline mode, 한 줄이 끝나고 다음 줄까지도 검색이 이어진다다다

RegExp 객체 생성하기

RegExp 객체는 2가지 방법으로 생성이 가능하다.

Regular Expression Literal


var expression = /abc/g;
// "/"는 delimiter며 "/"사이에 패턴이 들어가고 그 후에 flag 표시를 하게된다.
// /abc/g는 전체 텍스트에서 "abc" 문자열을 일치한다.

RegExp Constructor


var rep1 = new RegExp('abc', 'g');
var rep2 = new RegExp(/abc/, 'gmi');
// 첫번째 파라미터로 패턴이 들어가며, 두번째 파라미터로 flag가 들어가게 된다
// 단 첫번째 경우처럼 '(single quote)로 패턴 문자열을 구성할 경우에, \(backslash)는 \\로 표현된다.
// 즉 /\d+/ 라는 패턴은 '\\d+'로 적어야 한다.

각각의 RegExp 객체는 총 6가지 프로퍼티를 가지고 있다.

  • global : 표현식이 g flag를 가졌는지를 가리키는 Boolean 값
  • ignoreCase : 표현식이 i flag를 가졌는지를 가리키는 Boolean 값
  • lastIndex : 다음 매칭이 시작될 문자의 위치를 가리키는 Integer 값, 기본값은 언제나 0이다.
  • multiline : 표현식이 m flag를 가졌는지를 가리키는 Boolean 값
  • source : Regexp에 사용된 정규 표현식, 표현식의 delimiter(/) 내부 패턴


var rep = new RegExp('foo.+', 'gi');

console.log(rep.global); //true
console.log(rep.ignoreCase); //true
console.log(rep.lastIndex); //0
console.log(rep.multiline); //false
console.log(rep.source); //foo.+

Regexp.prototype.exec()


exec()메소드는 파라미터로 주어진 문자열을 검색해 해당 표현식에 일치하는 결과값을 Array 형식으로 반환한다.

Parameter : 검색을 실행할 문자열(String)

Return : 표현식과 일치하는 문자열이 존재할 떄 Array형식으로 결과값을 반환하며, 해당 RegExp 인스턴스의 프로퍼티를 업데이트 한다.
반환되는 Array의 첫번째 인덱스에 해당 표현식과 일치하는 문자열이 저장되며, 그 후로 각각의 인덱스에 표현식에서 생성한 하위패턴['(',')'를 이용하는것]에 일치하는 문자열들이 순차적으로 저장되게 된다
표현식과 일치하는 문자열이 존재하지 않는다면, null 값을 반환한다.


var reg = /(java).*(\d{3}).*(fun)/gi

var str = "My JavaSrcipt101 class is fun. Good Class";

var result = reg.exec(str);
console.log(result);

//  reg.exec(str)메소드 실행 후 반환되는 Array 값
//
//  result[0] : 'JavaSrcipt101 class is fun',
//  result[1] : 'Java',
//  result[2] : '101',
//  result[3] : 'fun',
//  result["index"] : 3,
//  result["input"] : 'My JavaSrcipt101 class is fun. Good Class'

반환되는 Array 객체 정보

배열 인덱스(Array Index)저장되는 값예제
[0]표현식에 일치하는 문자열JavaSrcipt101 class is fun'
[1], [2], [3]....[n] 각각의 하위 패턴에 일치하는 문자열[1] : 'Java'
[2] : '101'
[3] : 'fun'
배열 객체 프로퍼티(Property)저장되는 값예제
"index"검색이 실행된 문자열에서
첫번째로 표현식이 일치하는 문자의 위치(최소 0에서 시작한다)
3
"input"검색이 실행된 문자열My JavaSrcipt101 class is fun.'

위의 형식에 일치하는 배열(Array)이 반환되며 exec() 메소드를 실행한 Regex 인스턴스는 아래와 같이 업데이트 된다.

Regex 인스턴스의 프로퍼티(Property)저장되는 값예제
lastIndex다음 검색을 실행할 문자열의 인덱스
일치하는 문자열의 마지막 문자의 인덱스 + 1이 된다.
만약 g 플래그를 사용하지 않는다면 언제나 0이 된다.
29
"fun" 뒤에오는
마침표 문자 (.) 의 인덱스
ignoreCasei 플래그의 사용여부true
globalg 플래그의 사용여부true
multilinem 플래그의 사용여부false
source검색에 사용한 표현식(java).*(\d{3}).*(fun)

RegExp.prototype.test()


test() 메소드는 파라미터로 주어진 문자열에 표현식에 일치하는 문자열이 존재하는지를 확인한 후 그 결과값을 true 또는 false의 Boolean 값으로 반환한다.

Parameter : 검색을 실행할 문자열(String)

Return : 표현식과 일치하는 문자열이 존재할때는 true 값을 반환하며, 아닐시는 false 값을 반환한다


var reg = /[A-Za-z]/;

var str = "My JavaSrcipt101 class is fun. Good Class";

var resultStr = reg.test(str);

console.log(resultStr); //true

var num = "4132";

var resultNum = reg.test(num);

console.log(resultNum); //false

2015년 5월 6일 수요일

[JavaScript] 자바스크립트 프로토타입(Prototype) 객체 이해하기

프로토타입(Prototype)이란?


프로토타입(Prototype), 이름에서 알 수 있듯 프로토타입이란 객체의 기본형인 객체를 뜻한다. 모든 객체는 프로토타입 객체를 가지며 프로토타입의 프로퍼티에 접근이 가능하다. 또한 이 프로토타입 객체도 객체인만큼 포로토타입 객체를 가진다. 즉 가기장 기본 Object 객체를 제외한 모든 객체들은 프로토타입 객체를 가지며 모든 객체의 최상위 프로토타입은 기본 Object.prototype 객체가 된다. 즉, 모든 객체들은 1개의 객체 인스턴스와 해당 인스턴스의 속성들을 공유하며 상속한다는 말이 된다.

이 프로토타입(Prototype)이 중요한 이유는 OOP의 상속 컨셉을 자바스크립트에서 구현할 수 있게하기 때문이다. 만약 객체가 뭔지 모른다면, 우선 이 글(클릭하기)을 읽고 와주기를 바란다.

우선 객체의 프로토타입은 ECMAScript 에서 지원하는 표준 메소드인 Object.getPrototypeOf() 메소드를 통해 접근할 수 있으며, 이 메소드는 프로토타입을 얻어(get)오는 메소드이므로 이메소드를 통해서 프로토타입을 수정하는것은 불가능하다.

*하지만 곧 ECMAScript 6에서 Object.setPrototypeOf() 메소드가 생긴다.

위의 표준 메소드와 별개로 Chrome, Internet Explorer, Mozilla FireFox 등에서는 __proto__따프로퍼티를 이용해 객체의 프로토타입에 접근할 수 있다.


var ob1 = {};
var ob2 = {};

console.log(ob1.__proto__); //Object
console.log(Object.getPrototypeOf(ob2)); //Object
console.log(ob1.__proto__ == Object.getPrototypeOf(ob2)); //true
//기본으로 생성되는 객체는 모두 같은 Object 프로토타입 객체 인스턴스을 참조한다.

여기서 ob1과 ob2 객체에 프로토타입을 설정해준다면


var protoObj = {
  getFirstName: function() {
    return this.firstName;
  }
}
var ob1 = {};
var ob2 = {};
ob1.__proto__ = protoObj;
ob2.__proto__ = protoObj;

ob1.firstName = "Jason";
ob2.firstName = "Natali";
console.log(ob1.getFirstName()); //Jason
console.log(ob2.getFirstName()); //Natali

protoObj.getFirstName = function(){
  return "Function changed";
};

console.log(ob1.getFirstName()); //Function changed
console.log(ob2.getFirstName()); //Function changed
console.log(ob1.__proto__==ob2.__proto__); //true
console.log(protoObj.__proto__ == Object.prototype); //true

이렇게 다른 언어의 객체 상속과 같은 결과를 낳게 된다. 또한 두 객체 모두 같은 프로토타입 객체 인스턴스를 참조하고 있으므로 주어진 프로토타입 객체의 수정은 해당 프로토타입 객체를 참조하는 모든 객체에 적용된다.

위 객체들의 최종 관계도를 UML 다이어그램으로 나타내자면 아래와 같다.

프로토타입 객체 인스턴스와 객체 인스턴스들의 관계도

앞서 말했듯, 모든 사용자 생성 객체는 생성될 때 Object.prototype 객체를 프로토타입으로 가진다.
그리고 ob1과 ob2는 같은 protoObj 인스턴스를 프로토타임으로 가지니, protoObj 인스턴스에 생기는 변화는 obj1과 obj2에 모두 적용된다.

그리고 Object.prototype에는


Object.prototype.constructor
Object.prototype.hasOwnProperty()
Object.prototype.isPrototypeOf()
Object.prototype.propertyIsEnumerable()
Object.prototype.toLocaleString()
Object.prototype.toString()

와 같이 생성되는 객체에 기본으로 탑재되는 메소드들이 프로퍼티로 저장되 있다.

*참고로 Object.prototype 객체 프로퍼티들의 속성은
Writable : false
Enumerable : false
Configurable : false
이니 어떤 방법을 써서도 코드 프로퍼티 리스트나 프로퍼티 수정이 불가능하다.


그렇다면 Object.prototype에서 Object란 무었일까? 이를 이해하기 위해서는 우선 constructor에 대해 알아야하니 모른다면 이 글(클릭하기)을 읽고 오자.

프로토타입과 생성자 함수(Constructor)


우리가 Constructor 라 부르는 함수들은 function 객체로 여러가지 프로퍼티를 가지는데, 그 중 prototype 이라는 프로퍼티가 존재한다. 이 prototype이라는 프로퍼티는 해당 생성자 함수에 의해 성성되는 객체들에 부여되는 프로토타입 객체를 참조한다.

*참고로 이 prototype 프로퍼티는 함수(Function) 객채의 프로퍼티이고, Object.getPrototypeOf 메소드로 얻어지는 프로토타입 객체는 함수(Function) 객체의 프로토타입이다. 자바스크립트에서는 함수도 객체라는것을 잊지 말자


function Foo(){};

var foo = new Foo();
var too = new Foo();

console.log(foo.__proto__ == Foo.prototype); //true
console.log(foo.__proto__ == Object.getPrototypeOf(Foo)); //false
console.log(Object.getPrototypeOf(Foo) == Function.prototype); //true
console.log(foo.__proto__ == too.__proto__); //true
console.log(Foo == Foo.prototype.constructor); //true

함수 Foo의 프로토타입 객체가 바로 Function.prototype 객체이며, 이는 Foo.prototype 프로퍼티가 참조하는 객체와는 다른 객체이다.

그리고 해당 함수의 prototype 프로퍼티가 참조하는 객체의 constructor 프로퍼티는 해당 함수를 참조한다.
관계도를 그린다면 아래와 같이 된다.

Constructor Foo로 생성되는 객체 인스턴스들과 프로토타입의 관계도

생성자 함수 Foo에 의해 생성된 객체 footoo는 모두 함수 Fooprototype 프로퍼티가 참조하는 객체 Foo.prototype을 프로토타입으로 두고 있다. 즉 Foo.prototype의 수정은 footoo 객체 모두에 영향을 끼치게 된다.

*단, 아래의 경우처럼 프로토타입을 새로이 어싸인(Assign)할 경우에는 해당 객체가 참조하는 프로토타입만이 바뀔 뿐, 원 프로는는토타입이나 같은 프로타입을 가진 다른 객체들은 아무런 영향을 받지 않는다.


function Foo() {};

var foo = new Foo();
var too = new Foo();

var newPrototype = new Object();

foo.__proto__ = newPrototype;

console.log(Foo.prototype == foo.__proto__); //false
console.log(Foo.prototype == too.__proto__); //true
console.log(foo.__proto__ == too.__proto__); //false

위의 코드가 실행되면 관계도는 아래처럼 변한다.

생성된 객체에 새로운 프로토타입 어싸인(Assign) 후 관계도

객체 foo에 새로이 어싸인된 프로토타입은 constructor로 기본 Object 함수를 참조하고 있는데, 이는 newPrototype이 사용자에 의해 생성된, 즉 Object() 생성자 함수를 이용해 생성되었기 때문이다.

저 constructor도 프로퍼티 이기 때문에
foo.__proto__.constructor, 또는 newPrototype 객체 생성시 newPrototype.constructor 프로퍼티를 이용해 원하는 생성자 함수를 어싸인해주면 된다.

Property Lookup(프로퍼티 검색)과 프로퍼티 overriding


어떤 객채이든 프로퍼티 검색은 해당 객체의 본체에서부터 시작된다. 아래의 코드를 보자.


var fooProto = {
  write: function() {
    return "write";
  },
  read: function() {
    return "read";
  }
};

function Foo() {
  this.write = function() {
    return "No write";
  }
}
Foo.prototype = fooProto;

foo = new Foo();

console.log(foo.write()); //No write
console.log(foo.read()); //read

too = new Foo();
too.read = function() {
  return "No read";
}

console.log(too.write()); //No write
console.log(too.read()); //No read

delete too.read; //too.read 프로퍼티 삭제

console.log(too.read()); //read

객체의 프로퍼티 호출이 일어나게 되면 자바스크립트 엔진은 가장 먼져 호출이 된 해당 객체(base object)에서 프로퍼티를 검색한다. 그리고, 만약 찾지 못하면 해당 객체의 프로토타입 객체에서 프로퍼티를 검색하고, 그리고도 찾지못다면 프로토타입의 프로토타입 객체까지 검색을 이어간다. 이 검색은 프로퍼티가 발견되거나, 또는 더 이상 검색을 이어갈 프로토타입이 없을 때(Object.prototype까지 도달할 떄)까지 계속 이어진다. 즉 하위 객체에 해당 프로퍼티가 존재한다면 프로퍼티 Overriding이 가능하다는 것이다.

이 때문에 위의 코드에서도 foo.write() 메소드는 Foo함수에서 정의한대로 실행되고, foo.read() 메소드는 Foo함수 생성자의 프로토타입 프로퍼티가 참조하는 fooProto 객체에서 정의한대로 실행되는 것이다. 이는 too.write(), too.read()의 실행결과에서도 잘 알 수 있다.

또 위의 코드를 보면 too.read 프로퍼티를 삭제하게되면 too.read() 메소드가 프로토타입 객체에서 정의한대로 작동한다. 즉, 프로토타입 객체를 직접 호출하지 않고는 하위 객체에서 프로토타입의 프로퍼티를 수정하는 것이 불가능하다.

Object.prototype.hasOwnProperty() 메소드와 in Operator(연산자)


hasOwnProperty() 메소드는 해당 객체에  파라미터로 주어진 이름을 가진 프로퍼티가 있는지를 확인한다.

앞서 말했듯, 자바스크립트 엔진은 프로퍼티 호출이 발생하면, 해당 객체에서 먼져 프로퍼티를 검색한 후, 찾지 못한다면 프로토타입으로 검색을 이어간다. 이 때문에, 특정 프로퍼티가 호출되어도 개발자들은 해당 프로퍼티가 프로토타입에 속한 프로퍼티인지, 하위 객체에 속한 프로퍼티인지 알 수 없게 되는데, hasOwnProperty() 메소드는 그 점을 해결해주는 메소드 이다.

사용법은 간단하다. 확인을 원하는 객체와 프로퍼티 이름으로 메소드를 호출하면 Boolean(true||false) 값을 리턴한다.

hasOwnProperty()와는 달리 in 연산자는 해당 객체에서 간접적으로 접근이 가능한 모든 프로퍼티에 대해 true 값을 반환단다.


var fooProto = {
  a: "Letter A",
  b: "Letter B",
};

function Foo() {
  this.b = "Letter B";
  this.c = "Letter C";
}

Foo.prototype = fooProto;

foo = new Foo();

console.log(foo.hasOwnProperty("a")); //false
console.log("a" in foo); //true
console.log(foo.hasOwnProperty("b")); //true
console.log("b" in foo); //true
console.log(foo.hasOwnProperty("c")); //true
console.log("c" in foo); //true

Object.prototype.isPrototypeOf() 메소드


isPrototypeOf 메소드는 해당 객체가 파라미터로 주어진 객체의 프로토타입인지를 확인하는 메소드 이다.

물론 Object.getPrototypeOf() 메소드 또는 __proto__ 프로퍼티와 '=' 연산자(equal operand)를 이용해서도 확인이 가능하지만, 이 방법을 대체할 수 있게 해주는 메소드 이다.


var fooProto = {
  a: "Letter A",
  b: "Letter B",
};

function Foo() {
  this.b = "Letter B";
  this.c = "Letter C";
}

Foo.prototype = fooProto;

foo = new Foo();

console.log(foo.isPrototypeOf(fooProto)); //false

//아래 3가지 확인법들은 모두 같은 결과를 반환한다.
console.log(fooProto.isPrototypeOf(foo)); //true
console.log(fooProto == Object.getPrototypeOf(foo)); //true
console.log(fooProto == foo.__proto__); //true