[javascript] JavaScript에서 instanceof 연산자는 무엇입니까?

instanceof사람들이 JavaScript를 객체 지향 프로그래밍 언어가 아니라고 생각하는 경향이 있기 때문에 JavaScript 의 키워드는 처음 접했을 때 상당히 혼란 스러울 수 있습니다.

  • 무엇입니까?
  • 어떤 문제가 해결됩니까?
  • 적절한시기와시기는?


답변

대신에

LHS (Left Hand Side) 피연산자는 클래스의 실제 생성자 인 RHS (Right Hand Side) 피연산자로 테스트되는 실제 객체입니다. 기본 정의는 다음과 같습니다.

Checks the current object and returns true if the object
is of the specified object type.

다음은 좋은 예 이며 Mozilla 개발자 사이트 에서 직접 가져온 예 입니다 .

var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral"; //no type specified
color2 instanceof String; // returns false (color2 is not a String object)

언급 할 가치가있는 것은 instanceof객체가 클래스의 프로토 타입에서 상속되면 true 로 평가됩니다.

var p = new Person("Jon");
p instanceof Person

즉는 p instanceof Person이후 사실 p에서 상속 Person.prototype.

OP의 요청에 따라

샘플 코드와 설명이있는 작은 예제를 추가했습니다.

변수를 선언하면 특정 유형을 지정합니다.

예를 들어 :

int i;
float f;
Customer c;

위의 변수 if, 및 일부 변수를 보여줍니다 c. 유형은 integer, float및 사용자 정의 Customer데이터 타입. 위와 같은 유형은 JavaScript뿐만 아니라 모든 언어에 대한 것일 수 있습니다. 그러나 JavaScript를 사용하면 변수를 선언 할 때 유형을 명시 적으로 정의하지 않으며 var xx는 숫자 / 문자열 / 사용자 정의 데이터 유형일 수 있습니다. 따라서 객체가 instanceof위에서 지정한 객체 인지 확인하여 객체가 지정된 유형인지 확인합니다 Customer.

var c = new Customer();
c instanceof Customer; //Returns true as c is just a customer
c instanceof String; //Returns false as c is not a string, it's a customer silly!

위에서 우리는 ctype으로 선언 된 것을 보았습니다 Customer. 우리는 그것을 새로 만들고 유형인지 여부를 확인했습니다 Customer. 물론, 그것은 true를 반환합니다. 그런 다음 여전히 Customer객체를 사용하여 객체인지 확인합니다 String. 아니, 확실히 String우리는 Customer객체가 아닌 객체를 새롭게했습니다 String. 이 경우 false를 반환합니다.

정말 간단합니다!


답변

지금까지 어떤 주석에서도 다루지 않은 것으로 보이는 인스턴스의 중요한 측면이 있습니다 : 상속. instanceof를 사용하여 평가되는 변수는 프로토 타입 상속으로 인해 여러 “유형”에 대해 true를 리턴 할 수 있습니다.

예를 들어, 타입과 서브 타입을 정의 해 봅시다 :

function Foo(){ //a Foo constructor
    //assign some props
    return this;
}

function SubFoo(){ //a SubFoo constructor
    Foo.call( this ); //inherit static props
    //assign some new props
    return this;
}

SubFoo.prototype = Object.create(Foo.prototype); // Inherit prototype
SubFoo.prototype.constructor = SubFoo;

이제 몇 개의 “클래스”가 있으므로 인스턴스를 만들고 인스턴스가 무엇인지 알아볼 수 있습니다.

var 
    foo = new Foo()
,   subfoo = new SubFoo()
;

alert( 
    "Q: Is foo an instance of Foo? "
+   "A: " + ( foo instanceof Foo ) 
); // -> true

alert( 
    "Q: Is foo an instance of SubFoo? " 
+   "A: " + ( foo instanceof SubFoo ) 
); // -> false

alert( 
    "Q: Is subfoo an instance of Foo? "
+   "A: " + ( subfoo instanceof Foo ) 
); // -> true

alert( 
    "Q: Is subfoo an instance of SubFoo? "
+   "A: " + ( subfoo instanceof SubFoo ) 
); // -> true

alert( 
    "Q: Is subfoo an instance of Object? "
+   "A: " + ( subfoo instanceof Object ) 
); // -> true

마지막 줄 보여? 함수에 대한 모든 “새”호출은 Object에서 상속 된 오브젝트를 리턴합니다. 이것은 객체 생성 속기를 사용할 때도 마찬가지입니다.

alert( 
    "Q: Is {} an instance of Object? "
+   "A: " + ( {} instanceof Object ) 
); // -> true

“클래스”정의 자체는 어떻습니까? 그들은 무엇입니까?

alert( 
    "Q: Is Foo an instance of Object? "
+   "A:" + ( Foo instanceof Object) 
); // -> true

alert( 
    "Q: Is Foo an instance of Function? "
+   "A:" + ( Foo instanceof Function) 
); // -> true

필자는 객체를 MULTIPLE 유형의 인스턴스가 될 수 있다는 것을 이해하는 것이 중요하다고 생각합니다 instanceof. 이 마지막 예에서 함수 객체 라는 것을 분명히 보여줍니다 .

상속 패턴을 사용하고 있고 오리 타이핑 이외의 방법으로 개체의 자손을 확인하려는 경우에도 중요합니다.

누군가가 탐험하는 데 도움이되기를 바랍니다 instanceof.


답변

여기에있는 다른 대답은 정확하지만 instanceof실제로 어떻게 작동 하는지 알지 못 하므로 일부 언어 변호사가 관심을 가질 수 있습니다.

JavaScript의 모든 객체에는 __proto__속성을 통해 액세스 할 수있는 프로토 타입이 있습니다. 함수에는 prototype속성 이 있습니다.이 속성은 __proto__객체에 의해 생성 된 객체 의 초기 값 입니다. 함수가 작성되면에 대한 고유 한 오브젝트가 제공됩니다 prototype. instanceof운영자는 당신에게 대답을 줄이 고유성을 사용합니다. 여기에 무슨 instanceof당신이 함수로 쓴 경우처럼 보일 수 있습니다.

function instance_of(V, F) {
  var O = F.prototype;
  V = V.__proto__;
  while (true) {
    if (V === null)
      return false;
    if (O === V)
      return true;
    V = V.__proto__;
  }
}

이것은 기본적으로 ECMA-262 판 5.1 (ES5라고도 함) 15.3.5.3 절을 설명합니다.

객체를 함수의 prototype속성에 재 할당 할 수 있으며 객체의 __proto__속성을 생성 한 후 다시 할당 할 수 있습니다 . 이것은 당신에게 흥미로운 결과를 줄 것입니다 :

function F() { }
function G() { }
var p = {};
F.prototype = p;
G.prototype = p;
var f = new F();
var g = new G();

f instanceof F;   // returns true
f instanceof G;   // returns true
g instanceof F;   // returns true
g instanceof G;   // returns true

F.prototype = {};
f instanceof F;   // returns false
g.__proto__ = {};
g instanceof G;   // returns false


답변

objectof를 선언 할 때 “new”키워드를 사용하여 instanceof를 정의한다는 점에 주목할 가치가 있다고 생각합니다. JonH의 예제에서;

var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral";
color2 instanceof String; // returns false (color2 is not a String object)

그가 언급하지 않은 것은 이것입니다.

var color1 = String("green");
color1 instanceof String; // returns false

“new”를 지정하면 실제로 문자열 생성자 함수의 종료 상태를 반환 값으로 설정하지 않고 color1 var에 복사했습니다. 새 키워드의 기능을 더 잘 보여줍니다.

function Test(name){
    this.test = function(){
        return 'This will only work through the "new" keyword.';
    }
    return name;
}

var test = new Test('test');
test.test(); // returns 'This will only work through the "new" keyword.'
test // returns the instance object of the Test() function.

var test = Test('test');
test.test(); // throws TypeError: Object #<Test> has no method 'test'
test // returns 'test'

“new”를 사용하면 함수 내의 “this”값이 선언 된 var에 할당되고, 사용하지 않으면 반환 값이 할당됩니다.


답변

다음과 같이 오류 처리 및 디버깅에 사용할 수 있습니다.

try{
    somefunction();
} 
catch(error){
    if (error instanceof TypeError) {
        // Handle type Error
    } else if (error instanceof ReferenceError) {
        // Handle ReferenceError
    } else {
        // Handle all other error types
    }
}


답변

//Vehicle is a function. But by naming conventions
//(first letter is uppercase), it is also an object
//constructor function ("class").
function Vehicle(numWheels) {
    this.numWheels = numWheels;
}

//We can create new instances and check their types.
myRoadster = new Vehicle(4);
alert(myRoadster instanceof Vehicle);


답변

무엇입니까?

자바 스크립트는 프로토 타입 언어로 ‘상속’에 프로토 타입을 사용합니다. instanceof생성자 함수의 경우 운전자는 테스트 prototypepropertype이에 존재 __proto__객체의 체인. 이것은 다음을 수행한다는 것을 의미합니다 (testObj가 함수 객체라고 가정).

obj instanceof testObj;
  1. 객체의 프로토 타입이 생성자의 프로토 타입과 같은지 확인하십시오 : obj.__proto__ === testObj.prototype >> if this is true instanceofreturn true.
  2. 프로토 타입 체인을 올라갈 것입니다. 예를 들면 다음과 같습니다. obj.__proto__.__proto__ === testObj.prototype >> if is is true instanceofreturn true.
  3. 전체 객체 프로토 타입이 검사 될 때까지 2 단계를 반복합니다. 아무 객체의 프로토 타입 체인이 일치하지 않을 경우 testObj.prototype다음 instanceof연산자를 반환합니다 false.

예:

function Person(name) {
  this.name = name;
}
var me = new Person('Willem');

console.log(me instanceof Person); // true
// because:  me.__proto__ === Person.prototype  // evaluates true

console.log(me instanceof Object); // true
// because:  me.__proto__.__proto__ === Object.prototype  // evaluates true

console.log(me instanceof Array);  // false
// because: Array is nowhere on the prototype chain

어떤 문제가 해결됩니까?

객체가 특정 프로토 타입에서 파생되는지 편리하게 확인하는 문제를 해결했습니다. 예를 들어, 함수가 다양한 프로토 타입을 가질 수있는 객체를 수신 할 때. 그런 다음 프로토 타입 체인의 메소드를 사용하기 전에 instanceof연산자를 사용 하여 이러한 메소드가 오브젝트에 있는지 여부를 확인할 수 있습니다 .

예:

function Person1 (name) {
  this.name = name;
}

function Person2 (name) {
  this.name = name;
}

Person1.prototype.talkP1 = function () {
  console.log('Person 1 talking');
}

Person2.prototype.talkP2 = function () {
  console.log('Person 2 talking');
}


function talk (person) {
  if (person instanceof Person1) {
    person.talkP1();
  }

  if (person instanceof Person2) {
    person.talkP2();
  }


}

const pers1 = new Person1 ('p1');
const pers2 = new Person2 ('p2');

talk(pers1);
talk(pers2);

여기서 talk()함수에서 프로토 타입이 객체에 있는지 먼저 확인합니다. 그런 다음 적절한 방법을 선택하여 실행합니다. 이 검사를 수행하지 않으면 존재하지 않는 메소드가 실행되어 참조 오류가 발생할 수 있습니다.

적절한시기와시기는?

우리는 이미 이것을 극복했습니다. 객체의 프로토 타입을 확인해야 할 때 사용하십시오.