자바스크립트는 동적 타입(dynamic typed) 언어이므로 변수에 어떤 값이 할당될 지 예측하기 어렵다.
이와 같은 이유로 자바스크립트는 타입 체크가 필요하다.
 typeof '';              // string
 typeof 1;               // number
 typeof NaN;             // number
 typeof true;            // boolean
 typeof [];              // object
 typeof {};              // object
 typeof new String();    // object
 typeof new Date();      // object
 typeof /test/gi;        // object
 typeof function () {};  // function
 typeof undefined;       // undefined
 typeof null;            // object (설계적 결함)
 typeof undeclared;      // undefined (설계적 결함)
var obj = new Object();
obj.toString(); // [object Object]
Object.prototype.toString.call('');             // [object String]
Object.prototype.toString.call(new String());   // [object String]
Object.prototype.toString.call(1);              // [object Number]
Object.prototype.toString.call(new Number());   // [object Number]
Object.prototype.toString.call(NaN);            // [object Number]
Object.prototype.toString.call(Infinity);       // [object Number]
Object.prototype.toString.call(true);           // [object Boolean]
Object.prototype.toString.call(undefined);      // [object Undefined]
Object.prototype.toString.call();               // [object Undefined]
Object.prototype.toString.call(null);           // [object Null]
Object.prototype.toString.call([]);             // [object Array]
Object.prototype.toString.call({});             // [object Object]
Object.prototype.toString.call(new Date());     // [object Date]
Object.prototype.toString.call(Math);           // [object Math]
Object.prototype.toString.call(/test/i);        // [object RegExp]
Object.prototype.toString.call(function () {}); // [object Function]
Object.prototype.toString.call(document);       // [object HTMLDocument]
Object.prototype.toString.call(argument);       // [object Arguments]
Object.prototype.toString.call(undeclared);     // ReferenceError
function getType(target) {
  return Object.prototype.toString.call(target).slice(8, -1);
}
target instanceof HTMLElement; //true or false
  const isArrayLike = function (collection) {
    // 배열 인덱스: 32bit 정수(2의 32제곱 - 1)
    // 유사 배열 인덱스: 자바스크립트로 표현할 수 있는 양의 정수(2의 53제곱 - 1)
    const MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; 
    // 빈문자열은 유사배열이다. undefined == null => true
    const length = collection == null ? undefined : collection.length;
    return typeof length === 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
   };
var student = {
  name: 'Lee',
  score: 90
};
// student에는 hasOwnProperty 메소드가 없지만 아래 구문은 동작한다.
console.log(student.hasOwnProperty('name')); // true
var student = {
  name: 'Lee',
  score: 90
}
console.log(student.__proto__ === Object.prototype); // true모든 객체는 자신의 프로토타입 객체를 가리키는 [[Prototype]] 인터널 슬롯(internal slot) 을 갖으며 상속을 위해 사용된다.
함수도 객체이므로 [[Prototype]] 인터널 슬롯을 갖는다. 그런데 함수 객체는 일반 객체와는 달리 prototype 프로퍼티도 소유하게 된다.
prototype 프로퍼티와 [[Prototype]]은 모두 프로토타입 객체를 가리키지만 관점의 차이가 있다.
[[Prototype]]
  console.log(Person.__proto__ === Function.prototype);prototype 프로퍼티
  console.log(Person.prototype === foo.__proto__);
function Person(name) {
  this.name = name;
}
var foo = new Person('Lee');
// Person() 생성자 함수에 의해 생성된 객체를 생성한 객체는 Person() 생성자 함수이다.
console.log(Person.prototype.constructor === Person);
// foo 객체를 생성한 객체는 Person() 생성자 함수이다.
console.log(foo.constructor === Person);
// Person() 생성자 함수를 생성한 객체는 Function() 생성자 함수이다.
console.log(Person.constructor === Function);
var student = {
  name: 'Lee',
  score: 90
}
// Object.prototype.hasOwnProperty()
console.log(student.hasOwnProperty('name')); // true
var person = {
  name: 'Lee',
  gender: 'male',
  sayHello: function(){
    console.log('Hi! my name is ' + this.name);
  }
};
console.dir(person);
console.log(person.__proto__ === Object.prototype);   // ① true
console.log(Object.prototype.constructor === Object); // ② true
console.log(Object.__proto__ === Function.prototype); // ③ true
console.log(Function.prototype.__proto__ === Object.prototype); // ④ true
Object literal Prototype chaining

생성자 함수로 생성된 객체의 프로토타입 체인
function Person(name, gender) {
  this.name = name;
  this.gender = gender;
  this.sayHello = function(){
    console.log('Hi! my name is ' + this.name);
  };
}
var foo = new Person('Lee', 'male');
console.dir(Person);
console.dir(foo);
console.log(foo.__proto__ === Person.prototype);                // ① true
console.log(Person.prototype.__proto__ === Object.prototype);   // ② true
console.log(Person.prototype.constructor === Person);           // ③ true
console.log(Person.__proto__ === Function.prototype);           // ④ true
console.log(Function.prototype.__proto__ === Object.prototype); // ⑤ true
.png)
function Person(name) {
  this.name = name;
}
var foo = new Person('Lee');
Person.prototype.sayHello = function(){
  console.log('Hi! my name is ' + this.name);
};
foo.sayHello();
var str = 'test';
console.log(typeof str);                 // string
console.log(str.constructor === String); // true
console.dir(str);                        // test
var strObj = new String('test');
console.log(typeof strObj);                 // object
console.log(strObj.constructor === String); // true
console.dir(strObj);
// {0: "t", 1: "e", 2: "s", 3: "t", length: 4, __proto__: String, [[PrimitiveValue]]: "test" }
console.log(str.toUpperCase());    // TEST
console.log(strObj.toUpperCase()); // TEST
function Person(name) {
  this.name = name;
}
var foo = new Person('Lee');
// 프로토타입 객체의 변경
Person.prototype = { gender: 'male' };
var bar = new Person('Kim');
console.log(foo.gender); // undefined
console.log(bar.gender); // 'male'
console.log(foo.constructor); // ① Person(name)
console.log(bar.constructor); // ② Object()
changing prototype
var MYAPP = {};
MYAPP.student = {
  name: 'Lee',
  gender: 'male'
};
console.log(MYAPP.student.name);
(function () {
  var MYAPP = {};
  MYAPP.student = {
    name: 'Lee',
    gender: 'male'
  };
  console.log(MYAPP.student.name);
}());
console.log(MYAPP.student.name);