Подтвердить что ты не робот

Какая разница между isPrototypeOf и instanceof в Javascript?

В моем собственном более старом коде я использую следующее:

Object.prototype.instanceOf = function( iface )
{
 return iface.prototype.isPrototypeOf( this );
};

Тогда я делаю (например)

[].instanceOf( Array )

Это работает, но, похоже, следующее будет делать то же самое:

[] instanceof Array

Теперь, конечно, это всего лишь очень простой пример. Поэтому мой вопрос:

Является ли a instanceof b ВСЕГДА так же, как b.prototype.isPrototypeOf(a)?

4b9b3361

Ответ 1

Да, они делают то же самое, оба пересекают цепочку прототипов, ища конкретный объект в ней.

Различие между ними - это то, что они есть, и то, как вы их используете, например. isPrototypeOf - это функция, доступная для объекта Object.prototype, она позволяет вам проверить, находится ли конкретный объект в цепочке прототипов другого, поскольку этот метод определен в Object.prototype, он доступен для всех объектов.

instanceof является оператором и ожидает два операнда, объект и конструктор, он будет проверять, существует ли свойство переданной функции prototype в цепочке объекта (через [[HasInstance]](V) внутренняя операция, доступная только в объектах Function).

Например:

function A () {
  this.a = 1;
}
function B () {
  this.b = 2;
}
B.prototype = new A();
B.prototype.constructor = B;

function C () {
  this.c = 3;
}
C.prototype = new B();
C.prototype.constructor = C;

var c = new C();

// instanceof expects a constructor function

c instanceof A; // true
c instanceof B; // true
c instanceof C; // true

// isPrototypeOf, can be used on any object
A.prototype.isPrototypeOf(c); // true
B.prototype.isPrototypeOf(c); // true
C.prototype.isPrototypeOf(c); // true

Ответ 2

Является a instanceof b ВСЕГДА тем же, что и b.prototype.isPrototypeOf(a)?

Нет, a instanceof b не всегда будет вести себя так же, как b.prototype.isPrototypeOf(a).

В ответе CMS указывалось, что они отличаются друг от друга (один является оператором, а другой - встроенным методом, доступным для объекта Object.prototype). Это верно, однако есть и некоторые частные случаи, для которых a instanceof b приведет к TypeError во время b.prototype.isPrototypeOf(a) будет работать нормально, и наоборот.

Разница № 1

Ожидается, что правая часть instanceof будет функцией конструктора.

Если b не является функцией:

  • a instanceof b приведет к TypeError.

  • b.prototype.isPrototypeOf(a) будет работать просто отлично.

const b = {
    prototype: {}
};
const a = Object.create( b.prototype );

console.log( b.prototype.isPrototypeOf(a) );    // true
console.log( a instanceof b );                  // TypeError: Right-hand side of 'instanceof' is not callable

Ответ 3

Приоритет и правдивость операторов различаются, поскольку один является выражением, а другой - вызовом метода. Следует подчеркнуть, что оба пересекают цепочку прототипов, поэтому вы не можете предположить, что между сопоставимым прототипом и рассматриваемым объектом существует взаимно однозначное соответствие:

var i = 0;

function foo()
{
console.log("foo");
console.log(i++ + ": " + Object.prototype.isPrototypeOf(Object) ) //true
console.log(i++ + ": " + Function.prototype.isPrototypeOf(Function) ) //true

console.log(i++ + ": " + Function.prototype.isPrototypeOf(Function) ) //true
console.log(i++ + ": " + Function.prototype.isPrototypeOf(Object) ) //true

console.log(i++ + ": " + RegExp.prototype.isPrototypeOf( RegExp(/foo/) ) ) //true
console.log(i++ + ": " + Object.prototype.isPrototypeOf( RegExp(/foo/) ) ) //true
console.log(i++ + ": " + Function.prototype.isPrototypeOf( RegExp(/foo/) ) ) //false
console.log(i++ + ": " + Object.prototype.isPrototypeOf(Math) ) //true
console.log(i++ + ": " + Math.isPrototypeOf(Math) ) //false
}

function bar()
{
console.log("bar");
console.log(i++ + ": " + (Object instanceof Object) ) //true

console.log(i++ + ": " + (Function instanceof Function) ) //true
console.log(i++ + ": " + (Function instanceof Object) ) //true

console.log(i++ + ": " + (RegExp(/foo/) instanceof RegExp) ) //true
console.log(i++ + ": " + (RegExp(/foo/) instanceof Object)  ) //true
console.log(i++ + ": " + (RegExp(/foo/) instanceof Function) ) //false
console.log(i++ + ": " + (Math instanceof Object) ) //true
console.log(i++ + ": " + (Math instanceof Math) ) //error
}
try
  {
  foo()
  }
catch(e)
  {
  console.log(JSON.stringify(e));
  }
finally
  {
  try
    {
    bar();
    }
  catch(e)
    {
    console.log(JSON.stringify(e));
    }
  }