Quelle est la différence entre typeof et instanceof et quand doit-on être utilisé par rapport à l'autre?

StackOverflow https://stackoverflow.com/questions/899574

  •  23-08-2019
  •  | 
  •  

Question

Dans mon cas particulier:

callback instanceof Function

ou

typeof callback == "function"

est-il important même, quelle est la différence?

Ressource supplémentaire:

JavaScript Jardin typeof vs instanceof

Était-ce utile?

La solution

Utilisez instanceof pour les types personnalisés:

var ClassFirst = function () {};
var ClassSecond = function () {};
var instance = new ClassFirst();
typeof instance; // object
typeof instance == 'ClassFirst'; // false
instance instanceof Object; // true
instance instanceof ClassFirst; // true
instance instanceof ClassSecond; // false 

Utilisation typeof pour de simples types intégrés:

'example string' instanceof String; // false
typeof 'example string' == 'string'; // true

'example string' instanceof Object; // false
typeof 'example string' == 'object'; // false

true instanceof Boolean; // false
typeof true == 'boolean'; // true

99.99 instanceof Number; // false
typeof 99.99 == 'number'; // true

function() {} instanceof Function; // true
typeof function() {} == 'function'; // true

Utilisation instanceof pour complexe construit dans les types:

/regularexpression/ instanceof RegExp; // true
typeof /regularexpression/; // object

[] instanceof Array; // true
typeof []; //object

{} instanceof Object; // true
typeof {}; // object

Et le dernier est un peu délicat:

typeof null; // object

Autres conseils

Les deux sont similaires dans la fonctionnalité, car ils ont tous deux des informations de type de retour, mais je préfère personnellement instanceof parce qu'il est à comparer les types réels plutôt que des chaînes. Comparaison de type est moins sujette à l'erreur humaine, et il est techniquement plus rapide car il est la comparaison des pointeurs dans la mémoire plutôt que de faire des comparaisons entières de chaîne.

Une bonne raison d'utiliser typeof est si la variable peut être défini.

alert(typeof undefinedVariable); // alerts the string "undefined"
alert(undefinedVariable instanceof Object); // throws an exception

Une bonne raison d'utiliser est instanceof si la variable peut être nulle.

var myNullVar = null;
alert(typeof myNullVar ); // alerts the string "object"
alert(myNullVar  instanceof Object); // alerts "false"

Alors, vraiment, à mon avis, il dépend de quel type de données possible que vous vérifiez.

Pour rendre les choses claires, vous devez savoir deux faits:

  1. instanceof opérateur teste si le propriété prototype d'un constructeur apparaît partout dans la chaîne de prototypes d'un objet. Dans la plupart des cas, cela signifie que l'objet était créé en utilisant ce constructeur ou de son descendant. Mais aussi le prototype peut être défini explicitement par la méthode Object.setPrototypeOf() (ECMAScript 2015) ou par la propriété __proto__ (anciens navigateurs, dépréciées). Modification du prototype d'un objet est cependant pas recommandée en raison de problèmes de performance.

Ainsi est instanceof applicable uniquement aux objets. Dans la plupart des cas, vous n'utilisez pas des constructeurs pour créer des chaînes ou des nombres. Vous pouvez. Mais vous faites presque jamais.

En outre instanceof ne peut pas vérifier exactement quel constructeur a été utilisé pour créer l'objet, mais retourne vrai, même si l'objet est dérivé de la classe qui en cours de vérification. Dans la plupart des cas est le comportement souhaité, mais il est parfois pas. Donc, vous devez garder cet esprit.

Un autre problème est que les différents champs d'application ont différents environnements d'exécution. Cela signifie qu'ils ont des built-ins (différents objets global, les différents constructeurs, etc.). Cela peut entraîner des résultats inattendus.

Par exemple, [] instanceof window.frames[0].Array retournera false, parce que Array.prototype !== window.frames[0].Array et les tableaux héritent de l'ancienne.
En outre, il ne peut pas être utilisé sur la valeur non définie, car il ne pas un prototype.

  1. typeof opérateur teste si la valeur appartiennent à l'un des six types de base : " nombre ", « string », " boolean ", " objet ", " fonction " ou " undefined ". Lorsque la chaîne « objet » appartiennent tous les objets (à l'exception des fonctions, qui sont des objets, mais qui ont sa propre valeur dans l'opérateur typeof), et aussi la valeur « null » et les tableaux (pour « null » c'est un bug, mais ce bug est si vieux , il est devenu une norme). Il ne repose pas sur les constructeurs et peut être utilisé même si la valeur est définie. Mais il est ne donne pas de détails sur les objets. Donc, si vous en avez besoin, allez à instanceof.

Maintenant, nous allons parler d'une chose délicate. Que faire si vous utilisez constructeur pour créer un type primitif?

let num = new Number(5);
console.log(num instanceof Number); // print true
console.log(typeof num); // print object
num++; //num is object right now but still can be handled as number
//and after that:
console.log(num instanceof Number); // print false
console.log(typeof num); // print number

On dirait que la magie. Mais ce n'est pas. Il est ce qu'on appelle la boxe (valeur primitive d'emballage par objet) et unboxing (extraction de la valeur primitive enveloppé de l'objet). Ce type de code semble être « un peu » fragile. Bien sûr, vous pouvez simplement éviter de créer type primitif avec les constructeurs. Mais il y a une autre situation possible, quand la boxe peut vous frapper. Lorsque vous utilisez Function.call () ou Function.apply () sur un type primitif.

function test(){
  console.log(typeof this);
} 
test.apply(5);

Pour éviter cela, vous pouvez utiliser le mode strict:

function test(){
  'use strict';
  console.log(typeof this);
} 
test.apply(5);

màj: Depuis 2015 ECMAScript, il y a un type plus appelé symbole, qui a son propre typeof == "symbole" .

console.log(typeof Symbol());
// expected output: "symbol"

Vous pouvez lire à ce sujet sur MDN: ( Symbole , typeof ).

J'ai découvert un comportement vraiment intéressant (lire comme « horrible ») dans Safari 5 et Internet Explorer 9. J'utilisais cela avec beaucoup de succès dans Chrome et Firefox.

if (typeof this === 'string') {
    doStuffWith(this);
}

Puis-je tester dans IE9, et il ne fonctionne pas du tout. Grosse surprise. Mais dans Safari, il est intermittent! Je commence le débogage, et je trouve que Internet Explorer est toujours retour false. Mais la chose la plus étrange est que Safari semble faire une sorte d'optimisation dans sa machine virtuelle JavaScript où il est true premier temps, mais false à chaque fois que vous frappez reload!

Mon cerveau a explosé presque.

Alors maintenant, je suis installé sur ce point:

if (this instanceof String || typeof this === 'string')
    doStuffWith(this.toString());
}

Et maintenant tout fonctionne très bien. Notez que vous pouvez appeler "a string".toString() et renvoie juste une copie de la chaîne, i.e..

"a string".toString() === new String("a string").toString(); // true

Je vais utiliser les deux à partir de maintenant.

instanceof fonctionne également lorsque callback est un sous-type de Function, je pense

D'autres importantes différences pratiques:

// Boolean

var str3 = true ;

alert(str3);

alert(str3 instanceof Boolean);  // false: expect true  

alert(typeof str3 == "boolean" ); // true

// Number

var str4 = 100 ;

alert(str4);

alert(str4 instanceof Number);  // false: expect true   

alert(typeof str4 == "number" ); // true

instanceof en Javascript peut être squameuse - Je crois que les cadres principaux tentent d'éviter son utilisation. Différentes fenêtres est l'une des façons dont il peut briser -. Je crois que les hiérarchies de classe peuvent confondre et

Il y a de meilleures façons pour vérifier si un objet est un certain type intégré (ce qui est généralement ce que vous voulez). Créer des fonctions d'utilité et de les utiliser:

function isFunction(obj) {
  return typeof(obj) == "function";
}
function isArray(obj) {
  return typeof(obj) == "object" 
      && typeof(obj.length) == "number" 
      && isFunction(obj.push);
}

Et ainsi de suite.

instanceof ne fonctionnera pas pour les primitives, par exemple "foo" instanceof String retournera false alors typeof "foo" == "string" retournera true.

autre typeof main ne sera probablement pas faire ce que vous voulez, quand il s'agit d'objets personnalisés (ou classes, tout ce que vous voulez les appeler). Par exemple:

function Dog() {}
var obj = new Dog;
typeof obj == 'Dog' // false, typeof obj is actually "object"
obj instanceof Dog  // true, what we want in this case

Il se trouve que les fonctions sont les deux primitives « fonction » et les instances de « fonction », qui est un peu étrange étant donné que cela ne fonctionne pas comme pour les autres types primitifs, par exemple.

(typeof function(){} == 'function') == (function(){} instanceof Function)

(typeof 'foo' == 'string') != ('foo' instanceof String)

Je recommande d'utiliser le callback.isFunction() de prototype.

Ils ont compris la différence et vous pouvez compter sur leur raison.

Je suppose que d'autres cadres JS ont des choses aussi.

instanceOf ne fonctionnerait pas sur les fonctions définies dans d'autres fenêtres, je crois. Leur fonction est différent de votre window.Function.

Lors de la vérification d'une fonction, il faut toujours utiliser typeof.

Voici la différence:

var f = Object.create(Function);

console.log(f instanceof Function); //=> true
console.log(typeof f === 'function'); //=> false

f(); // throws TypeError: f is not a function

Ceci est la raison pour laquelle il ne faut jamais utiliser instanceof pour vérifier une fonction.

différence pratique significative:

var str = 'hello word';

str instanceof String   // false

typeof str === 'string' // true

Ne me demandez pas pourquoi.

Performance

typeof est plus rapide que instanceof dans les situations où les deux sont applicables.

En fonction de votre moteur, la différence de performance en faveur de typeof pourrait être autour de 20% . ( Votre kilométrage peut varier )

Voici un test de référence pour Array:

var subject = new Array();
var iterations = 10000000;

var goBenchmark = function(callback, iterations) {
    var start = Date.now();
    for (i=0; i < iterations; i++) { var foo = callback(); }
    var end = Date.now();
    var seconds = parseFloat((end-start)/1000).toFixed(2);
    console.log(callback.name+" took: "+ seconds +" seconds.");
    return seconds;
}

// Testing instanceof
var iot = goBenchmark(function instanceofTest(){
     (subject instanceof Array);
}, iterations);

// Testing typeof
var tot = goBenchmark(function typeofTest(){
     (typeof subject == "object");
}, iterations);

var r = new Array(iot,tot).sort();
console.log("Performance ratio is: "+ parseFloat(r[1]/r[0]).toFixed(3));

Résultat

instanceofTest took: 9.98 seconds.
typeofTest took: 8.33 seconds.
Performance ratio is: 1.198

Ceci est juste des connaissances complémentaires à toutes les autres explications ici -. Je suis pas qui suggère d'utiliser .constructor partout

TL; DR: Dans les situations où typeof est pas une option, et quand vous savez que vous ne se soucient pas de la chaîne prototype , Object.prototype.constructor peut être une solution viable ou encore meilleure alternative que instanceof:

x instanceof Y
x.constructor === Y

Il a été dans la norme depuis 1.1, donc pas de soucis sur la compatibilité ascendante.

Muhammad Umer brièvement parlé dans un commentaire quelque part ici aussi. Il fonctionne sur tout avec un prototype - donc pas tout null ou undefined:

// (null).constructor;      // TypeError: null has no properties
// (undefined).constructor; // TypeError: undefined has no properties

(1).constructor;                 // function Number
''.constructor;                  // function String
([]).constructor;                // function Array
(new Uint8Array(0)).constructor; // function Uint8Array
false.constructor;               // function Boolean()
true.constructor;                // function Boolean()

(Symbol('foo')).constructor;     // function Symbol()
// Symbols work, just remember that this is not an actual constructor:
// new Symbol('foo'); //TypeError: Symbol is not a constructor

Array.prototype === window.frames.Array;               // false
Array.constructor === window.frames.Array.constructor; // true

En outre, selon votre cas d'utilisation, il peut être beaucoup plus vite que instanceof (la raison étant probable qu'il ne dispose pas de vérifier l'ensemble de la chaîne de prototype). Dans mon cas je besoin d'un moyen rapide de vérifier si une valeur est un tableau typé:

function isTypedArrayConstructor(obj) {
  switch (obj && obj.constructor){
    case Uint8Array:
    case Float32Array:
    case Uint16Array:
    case Uint32Array:
    case Int32Array:
    case Float64Array:
    case Int8Array:
    case Uint8ClampedArray:
    case Int16Array:
      return true;
    default:
      return false;
  }
}

function isTypedArrayInstanceOf(obj) {
  return obj instanceof Uint8Array ||
    obj instanceof Float32Array ||
    obj instanceof Uint16Array ||
    obj instanceof Uint32Array ||
    obj instanceof Int32Array ||
    obj instanceof Float64Array ||
    obj instanceof Int8Array ||
    obj instanceof Uint8ClampedArray ||
    obj instanceof Int16Array;
}

https://run.perf.zone/view/isTypedArray -constructor-vs-instanceof-1519140393812

Et les résultats:

Chrome 64.0.3282.167 (64-bit, Windows)

Firefox 59.0b10 (64 bits, Windows)

Hors curiousity, je l'ai fait une référence de jouet rapide contre typeof; étonnamment, il ne fonctionne pas bien pire, et il semble même un peu plus rapide dans Chrome:

let s = 0,
    n = 0;

function typeofSwitch(t) {
    switch (typeof t) {
        case "string":
            return ++s;
        case "number":
            return ++n;
        default:
            return 0;
    }
}

// note: no test for null or undefined here
function constructorSwitch(t) {
    switch (t.constructor) {
        case String:
            return ++s;
        case Number:
            return ++n;
        default:
            return 0;
    }
}

let vals = [];
for (let i = 0; i < 1000000; i++) {
    vals.push(Math.random() <= 0.5 ? 0 : 'A');
}

https://run.perf.zone / view / typeof-vs-constructeur-string ou numéro-1519142623570

NOTE: L'ordre dans lequel les fonctions sont répertoriées Commute entre les images

Chrome 64.0.3282.167 (64-bit, Windows)

Firefox 59.0b10 (64 bits, Windows)

NOTE: L'ordre dans lequel les fonctions sont répertoriées Commute entre les images

Utilisez instanceof parce que si vous modifiez le nom de la classe, vous obtiendrez une erreur de compilation.

var newObj =  new Object;//instance of Object
var newProp = "I'm xgqfrms!" //define property
var newFunc = function(name){//define function 
	var hello ="hello, "+ name +"!";
	return hello;
}
newObj.info = newProp;// add property
newObj.func = newFunc;// add function

console.log(newObj.info);// call function
// I'm xgqfrms!
console.log(newObj.func("ET"));// call function
// hello, ET!

console.log(newObj instanceof Object);
//true
console.log(typeof(newObj));
//"object"

Issu d'une éducation stricte OO Je vais pour

callback instanceof Function

Les chaînes sont sujettes à soit mon orthographe terrible ou d'autres fautes de frappe. De plus, je pense qu'il lit mieux.

Malgré instanceof peut être un peu plus rapide, puis typeof , je préfère deuxième à cause d'une telle magie possible:

function Class() {};
Class.prototype = Function;

var funcWannaBe = new Class;

console.log(funcWannaBe instanceof Function); //true
console.log(typeof funcWannaBe === "function"); //false
funcWannaBe(); //Uncaught TypeError: funcWannaBe is not a function

Un autre cas est que vous ne pouvez collationner avec instanceof - il retourne vrai ou faux. Avec typeof vous pouvez obtenir le type de condition quelque chose

avec des performances à l'esprit, vous feriez mieux d'utiliser typeof avec un matériel typique, si vous créez un script avec une boucle de 10 millions d'itérations l'instruction: typeof str == 'string' prendra 9ms tandis que 'string' instanceof chaîne prendra 19ms

Bien sûr, il importe ........!

Marchons avec cette grâce examples.In notre exemple, nous allons déclarer la fonction de deux manières différentes.

Nous allons utiliser deux function declaration et Fonction Constructor . Nous allons se comment typeof et instanceof se comporte dans ces deux scénarios différents.

Créer une fonction à l'aide déclaration de fonction:

function MyFunc(){  }

typeof Myfunc == 'function' // true

MyFunc instanceof Function // false

Explication possible pour un tel résultat différent est, comme nous l'avons fait une déclaration de fonction, typeof peut comprendre qu'il est un function.Because typeof vérifie si l'expression ou non qui est typeof opération sur, dans notre cas MyFunc mis en œuvre Appel Méthode ou non . Si elle met en œuvre Call méthode est un function.Otherwise pas .pour contrôle de clarification spécification ECMAScript pour typeof .

fonction créée à l'aide de la fonction constructeur:

var MyFunc2 = new Function('a','b','return a+b') // A function constructor is used 

typeof MyFunc2 == 'function' // true

MyFunc2 instanceof Function // true

ici typeof affirme que MyFunc2 est une fonction aussi bien que la instanceof operator.We savent déjà typeof vérifier si MyFunc2 mis en œuvre Call méthode ou not.As MyFunc2 est une fonction et il met en oeuvre call méthode , voilà comment typeof sait que c'est un function.On d'autre part, nous avons utilisé function constructor pour créer MyFunc2 , il devient une instance de Function constructor .That's pourquoi instanceof Déclare aussi true .

Quoi de plus sûr à utiliser?

Comme on peut le voir dans les deux cas typeof opérateur peut affirmer avec succès que nous avons affaire à une fonction ici, il est plus sûr que instanceof . instanceof échouera en cas de function declaration parce que function declarations ne sont pas une instance de Function constructor .

Les meilleures pratiques:

Gary Rafferty suggéré, la meilleure façon devrait utiliser les deux typeof et instanceof ensemble.

  function isFunction(functionItem) {

        return typeof(functionItem) == 'function' || functionItem instanceof Function;

  }

  isFunction(MyFunc) // invoke it by passing our test function as parameter
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top