Quelle est la différence entre typeof et instanceof et quand faut-il utiliser l'un par rapport à l'autre?

394

Dans mon cas particulier:

callback instanceof Function

ou

typeof callback == "function"

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

Ressource supplémentaire:

JavaScript-Garden typeof vs instanceof

farinspace
la source
2
J'ai trouvé ma réponse ici comme une solution facile à utiliser
CrandellWS
1
Il y a une autre façon de vérifier le type en utilisant Object.prototype.toString ecma-international.org/ecma-262/6.0/…
rab
1
utilisez simplement la .constructorpropriété à la place.
Muhammad Umer
Si vous vous interrogez sur les performances , consultez ma réponse ci-dessous . typeof est plus rapide lorsque les deux sont applicables (à savoir les objets).
Martin Peter

Réponses:

540

Utilisez instanceofpour 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 

Utilisez typeofpour les types simples 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 instanceofpour les types intégrés complexes:

/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
Szymon Wygnański
la source
11
Cette réponse montre clairement pourquoi instaceof ne doit pas être utilisé pour les types primitifs. Il est assez évident que vous n'avez pas d'option en ce qui concerne les types personnalisés, ainsi que l'avantage pour les types «d'objet». Mais qu'est-ce qui rend les fonctions regroupées avec des "types intégrés simples"? Je trouve étrange comment une fonction se comporte comme un objet, mais son type est «fonction», ce qui rend possible l'utilisation de «typeof». Pourquoi découragez-vous par exemple d'en faire autant?
Assimilater
4
@Assimilater, vous pouvez également utiliser instanceof avec des fonctions, mais je considère que ces 3 règles sont très simples à retenir et oui, les fonctions sont une exception :)
Szymon Wygnański
2
une autre partie délicate -> 'exemple de chaîne' instanceof String; // false mais nouveau String ('exemple de chaîne') instanceof String; // true
Luke
2
@Luke est généralement une mauvaise idée d'utiliser une "nouvelle chaîne" comme celle-ci. qui crée un "objet chaîne" plutôt qu'une primitive chaîne. voir la section ici developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Colin D
4
Use instanceof for complex built in types- ceci est toujours sujet à erreur. Mieux vaut utiliser ES5 Array.isArray()et al. ou les cales recommandées.
OrangeDog
122

Les deux sont similaires dans la fonctionnalité car ils renvoient tous les deux des informations sur le type, mais je préfère personnellement instanceofcar il compare les types réels plutôt que les chaînes. La comparaison de types est moins sujette aux erreurs humaines, et elle est techniquement plus rapide car elle compare les pointeurs en mémoire plutôt que de faire des comparaisons de chaînes entières.

Soviut
la source
8
il y a des situations où instanceof ne fonctionnera pas comme prévu et typeof fonctionne bien ... developer.mozilla.org/En/Core_JavaScript_1.5_Reference/…
farinspace
55
instanceof fonctionne avec des objets dans la même fenêtre. Si vous utilisez iframe / frame ou popup-windows, chaque (i) frame / window a son propre objet "function" et instanceof échouera si vous essayez de comparer un objet d'un autre (i) frame / window. typeof fonctionnera dans tous les cas car il retourne la chaîne "function".
certains
14
jsperf.com/typeof-function-vs-instanceof/3 J'ai essayé sur Chrome et FF3.X, l'approche "typeof" est plus rapide.
Morgan Cheng
10
C'est tout simplement faux. Ils ne sont pas identiques. Ils ne fonctionnent pas tous les deux dans les mêmes situations, en particulier sur différentes machines virtuelles et navigateurs JavaScript.
Justin Force
8
Votre réponse dit "les deux sont essentiellement identiques en termes de fonctionnalités". Respectueusement, c'est manifestement faux. Comme indiqué et expliqué dans ma réponse, aucune des options ne fonctionne dans toutes les situations, en particulier sur les navigateurs. La meilleure approche consiste à utiliser les deux avec un || opérateur.
Justin Force
103

Une bonne raison d'utiliser typeof est si la variable n'est pas définie.

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

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

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

Donc, vraiment, à mon avis, cela dépendrait du type de données possibles que vous vérifiez.

Kenneth J
la source
11
+1 note également que instanceofne peut pas se comparer aux types primitifs, typeof peut.
Tino
3
Dans Chrome 29.0.1541.0, dev undefined instanceof Objectrenvoie false et ne lève pas d'exception. Je ne sais pas à quel point ce changement est récent, mais il est instanceofplus attrayant.
Cypress Frankenfeld
7
undefined instanceof Objectne lève pas d'exception car, eh, undefinedest défini. La constante existe dans l'espace de noms. Lorsqu'une variable n'existe pas (à cause d'une faute de frappe par exemple), instanceof lèvera une exception. L'utilisation de typeof sur une variable inexistante donne par contre «indéfini».
2015
31

Pour clarifier les choses, vous devez connaître deux faits:

  1. L' opérateur instanceof teste si la propriété prototype d'un constructeur apparaît n'importe où dans la chaîne de prototypes d'un objet. Dans la plupart des cas, cela signifie que l'objet a été créé en utilisant ce constructeur ou l'un de ses descendants. Mais le prototype peut également être défini explicitement par la Object.setPrototypeOf()méthode (ECMAScript 2015) ou par la __proto__propriété (anciens navigateurs, obsolètes). Il n'est cependant pas recommandé de modifier le prototype d'un objet en raison de problèmes de performances.

Ainsi instanceof ne s'applique qu'aux objets. Dans la plupart des cas, vous n'utilisez pas de constructeurs pour créer des chaînes ou des nombres. Vous pouvez. Mais vous ne le faites presque jamais.

De plus, instanceof ne peut pas vérifier exactement quel constructeur a été utilisé pour créer l'objet, mais renvoie true, même si l'objet est dérivé de la classe qui est vérifiée. Dans la plupart des cas, c'est le comportement souhaité, mais parfois ce n'est pas le cas. Vous devez donc garder cet esprit.

Un autre problème est que différentes étendues ont des environnements d'exécution différents. Cela signifie qu'ils ont des éléments intégrés différents (objet global différent, constructeurs différents, etc.). Cela peut entraîner des résultats inattendus.

Par exemple, [] instanceof window.frames[0].Arrayreviendra false, car Array.prototype !== window.frames[0].Arrayet les tableaux héritent de l'ancien.
De plus, il ne peut pas être utilisé sur une valeur non définie, car il n'a pas de prototype.

  1. L' opérateur typeof teste si la valeur appartient à l' un des six types de base : " nombre ", " chaîne ", " booléen ", " objet ", " fonction " ou " non défini ". Où la chaîne "objet" appartient à tous les objets (sauf les fonctions, qui sont des objets, mais qui ont sa propre valeur dans l'opérateur typeof), ainsi que la valeur et les tableaux "null" (pour "null", c'est un bogue, mais ce bogue est tellement ancien , c'est donc devenu un standard). Il ne repose pas sur des constructeurs et peut être utilisé même si la valeur n'est pas définie. Mais cela ne donne aucun détail sur les objets. Donc, si vous en aviez besoin, allez à instanceof.

Parlons maintenant d'une chose délicate. Et si vous utilisez un 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 de la magie. Mais ce n'est pas. C'est ce qu'on appelle la boxe (envelopper la valeur primitive par objet) et unboxing (extraire la valeur primitive enveloppée de l'objet). Ce type de code semble être "un peu" fragile. Bien sûr, vous pouvez simplement éviter de créer un type primitif avec des constructeurs. Mais il y a une autre situation possible, lorsque 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);

upd: Depuis ECMAScript 2015, il existe un autre type appelé Symbol, qui a son propre typeof == "symbol" .

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

Vous pouvez en lire plus sur MDN: ( Symbol , typeof ).

Vladimir Liubimov
la source
2
if an object is created by a given constructor Ceci est une erreur. o instanceof Cretournera vrai si o hérite de C.prototype. Vous en avez parlé plus loin dans votre réponse, mais ce n'est pas très clair.
oyenamit
1
incorrect ... du livre: " github.com/getify/You-Dont-Know-JS " une instance de Foo; // true L'opérateur instanceof prend un objet simple comme opérande de gauche et une fonction comme opérande de droite. La question instanceof réponses est: dans toute la chaîne [[Prototype]] d'un, est-ce que l'objet pointé arbitrairement par Foo.prototype apparaît jamais?
Deen John
1
J'ai édité la réponse, pour être plus correct. Merci pour vos commentaires.
Vladimir Liubimov
En outre, une explication du problème de boxe / unboxing a été ajoutée.
Vladimir Liubimov
15

J'ai découvert un comportement vraiment intéressant (lu 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);
}

Ensuite, je teste dans IE9, et cela ne fonctionne pas du tout. Grosse surprise. Mais dans Safari, c'est intermittent! Je commence le débogage, et je trouve que Internet Explorer est toujours de retour false. Mais le plus étrange est que Safari semble faire une sorte d'optimisation dans sa machine virtuelle JavaScript où c'est truela première fois, mais à false chaque fois que vous appuyez sur recharger!

Mon cerveau a presque explosé.

Alors maintenant, je me suis installé sur ceci:

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 il retourne juste une copie de la chaîne, c'est-à-dire

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

Je vais donc utiliser les deux à partir de maintenant.

Justin Force
la source
8

Autres différences pratiques importantes:

// 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
Amjad Farajallah
la source
7

instanceoffonctionne aussi quand callbackest un sous-type de Function, je pense

newacct
la source
4

instanceofen Javascript peut être floconneux - je crois que les principaux frameworks essaient d'éviter son utilisation. Différentes fenêtres sont l'une des façons dont elles peuvent se briser - je crois que les hiérarchies de classes peuvent également les confondre.

Il existe de meilleures façons de tester si un objet est d'un certain type intégré (ce qui est généralement ce que vous voulez). Créez des fonctions utilitaires et utilisez-les:

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

Etc.

levik
la source
2
Au cas où vous ne le sauriez pas: typeof n'a pas besoin de parenthèses car c'est un mot-clé et non une fonction. Et à mon humble avis, vous devez utiliser === au lieu de ==.
certains
5
@some Vous avez raison sur typeof mais dans ce cas il n'y a pas besoin de ===, il n'est nécessaire que lorsque la valeur comparée peut être égale sans avoir le même type. Ici, ça ne peut pas.
Nicole
@some typeof retourne-t-il jamais autre chose qu'une chaîne?
Kenneth J
Donc, isArray serait faux pour, disons, un objet pile avec une méthode push et un attribut de longueur numérique. Dans quelles circonstances (instance de Array) aurait-il tort?
Chris Noe
@ChrisNoe Le problème se pose avec des objets partagés entre plusieurs cadres: groups.google.com/forum/#!msg/comp.lang.javascript/XTWYCOwC96I/…
3

instanceofne fonctionnera pas pour les primitives, par exemple "foo" instanceof Stringretournera falsealors que typeof "foo" == "string"reviendra true.

D'un autre côté typeof, vous ne ferez probablement pas ce que vous voulez en ce qui concerne les objets personnalisés (ou les classes, peu importe comment vous les appelez). 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 à la fois des primitives «fonction» et des instances de «Fonction», ce qui est un peu étrange étant donné que cela ne fonctionne pas comme ça pour d'autres types de primitives, par exemple.

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

mais

(typeof 'foo' == 'string') != ('foo' instanceof String)
Omnimike
la source
3

Je recommanderais d'utiliser des prototypes callback.isFunction() .

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

Je suppose que d'autres frameworks JS ont aussi de telles choses.

instanceOfne fonctionnerait pas sur les fonctions définies dans d'autres fenêtres, je crois. Leur fonction est différente de la vôtre window.Function.

alamar
la source
3

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

C'est pourquoi il ne faut jamais utiliser instanceofpour rechercher une fonction.

vitaly-t
la source
Je peux affirmer que c'est typeoffaux - fc'est tout ce qui suit: un Object(un objet) et un Function(une fonction). Sauf pour moi, cela a plus de sens à utiliser instanceofcar sachant que c'est une fonction, je sais que c'est aussi un objet, car toutes les fonctions sont des objets dans ECMAScript. L'inverse n'est pas vrai - sachant de typeofcela fest en effet un objectje n'ai aucune idée que c'est aussi une fonction.
amn
@amn Pour moi, c'est une instance cassée de Function. Il obtient des attributs comme length, nameet callde Function, mais tous sont obsolètes. Pire encore, il ne peut pas être appelé et TypeErrordit: f is not a function.
maaartinus
2

Différence pratique significative:

var str = 'hello word';

str instanceof String   // false

typeof str === 'string' // true

Ne me demandez pas pourquoi.

Barney
la source
11
Car voici strune primitive chaîne, pas un objet chaîne. Il en va de même pour les primitives numériques et les primitives booléennes, ce ne sont pas des instances de leurs homologues "construits", les objets String, Number et Boolean. JavaScript convertit automatiquement ces trois primitives en objets lorsque cela est nécessaire (comme l'utilisation d'une méthode sur la chaîne de prototypes de l'objet). D'un autre côté de votre différence pratique, instanceof est mieux pour vérifier les tableaux depuis typeof [] == "object" // true.
Andy E
2

Performance

typeofest plus rapide que instanceofdans les situations où les deux sont applicables.

Selon votre moteur, la différence de performances en faveur de typeofpourrait être de l'ordre 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
Martin Peter
la source
1
typeof subject == "array" devrait retourner false. le type de sujet est "objet".
Shardul
pourquoi typeof est plus rapide? Javascript est-il en train d'interner les chaînes littérales?
Gregory Magarshak
La raison en est: suit instanceof toujours la chaîne de prototype de l'objet, donc la pénalité de performance dépendra de la distance dans laquelle la classe de prototype est la classe, instanceofest testée. Ainsi, pour une chaîne d'héritage courte, la pénalité sera plus faible (comme [] instanceof Array,, {} instanceof Object), et pour longtemps - plus grande. Donc, si les deux obj instanceof SomeClasset typeof obj !== 'string'signifient la même chose du point de vue de votre code hypothétique (par exemple, si vous effectuez simplement un test ifet que vous ne passez pas switchpar plusieurs classes, etc.), vous feriez mieux d'en choisir un deuxième, en termes de performances,
ankhzet
2

C'est juste une connaissance complémentaire à toutes les autres explications ici - je ne suggère pas d'utiliser .constructorpartout.

TL; DR: Dans les situations où ce typeofn'est pas une option, et quand vous savez que vous ne vous souciez pas de la chaîne prototype , Object.prototype.constructorpeut être une alternative viable ou encore meilleure que instanceof:

x instanceof Y
x.constructor === Y

Il est dans la norme depuis la version 1.1, donc ne vous inquiétez pas de la compatibilité descendante.

Muhammad Umer l'a brièvement mentionné dans un commentaire quelque part ici aussi. Il fonctionne sur tout avec un prototype - donc tout n'est pas nullou 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, cela peut être beaucoup plus rapide que instanceof(la raison étant probablement qu'il n'a pas à vérifier la chaîne de prototype entière). Dans mon cas, j'avais besoin d'un moyen rapide pour 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 bits, Windows)

Instance de matrice typée vs constructeur - 1,5 fois plus rapide dans Chrome 64.0.3282.167 (64 bits, Windows)

Firefox 59.0b10 (64 bits, Windows)

Typof Array typé vs constructeur - 30 fois plus rapide dans Firefox 59.0b10 (64 bits, Windows)

Par curiosité, j'ai fait une comparaison rapide de jouets contre typeof; étonnamment, il ne fonctionne pas beaucoup moins bien, et il semble encore 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-constructor-string-or-number-1519142623570

REMARQUE: L'ordre dans lequel les fonctions sont répertoriées bascule entre les images!

Chrome 64.0.3282.167 (64 bits, Windows)

Type de chaîne / nombre vs constructeur - 1,26 fois plus rapide dans Chrome 64.0.3282.167 (64 bits, Windows)

Firefox 59.0b10 (64 bits, Windows)

REMARQUE: L'ordre dans lequel les fonctions sont répertoriées bascule entre les images!

Type de chaîne / nombre vs constructeur - 0,78x plus lent dans Firefox 59.0b10 (64 bits, Windows)

Emploi
la source
1

Utilisez instanceof car si vous changez le nom de la classe, vous obtiendrez une erreur de compilation.

Robert
la source
1

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"

xgqfrms
la source
Que dois-je faire, puis-je obtenir UA (navigator.userAgent)?
xgqfrms
0

Venant d'une éducation OO stricte, j'irais

callback instanceof Function

Les cordes sont sujettes à mon horrible orthographe ou à d'autres fautes de frappe. De plus, je sens que ça se lit mieux.

Keplerf1
la source
0

Bien que instanceof puisse être un peu plus rapide que typeof , je préfère le second en raison 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
Suprido
la source
0

Un autre cas est que vous ne pouvez collationner qu'avec instanceof- cela renvoie vrai ou faux. Avec typeofvous pouvez obtenir le type de quelque chose fourni

Jarosław Wlazło
la source
0

avec les 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 9 ms tandis que 'string' instanceof String prendra 19 ms

Khalid Rafik
la source
0

Bien sûr, cela compte ........!

Passons en revue ces exemples: dans notre exemple, nous allons déclarer la fonction de deux manières différentes.

Nous utiliserons les deux function declarationet Function Constructor . Nous verrons comment typeofet instanceofse comportera dans ces deux scénarios différents.

Créer une fonction en utilisant la déclaration de fonction:

function MyFunc(){  }

typeof Myfunc == 'function' // true

MyFunc instanceof Function // false

Une explication possible de ce résultat différent est que, comme nous avons fait une déclaration de fonction, nous typeofpouvons comprendre qu'il s'agit d'une fonction.Parce que typeofvérifie si l'expression sur quel typeof fonctionne, dans notre cas, la méthode d'appel implémentée ou non . S'il implémente une méthode, c'est une fonction, sinon pas. Pour plus de précision, vérifiez la spécification ecmascript pour typeof .MyFunc Call

Créer une fonction à l'aide du constructeur de fonction:

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

typeof MyFunc2 == 'function' // true

MyFunc2 instanceof Function // true

Ici , typeofaffirme que MyFunc2est une fonction aussi bien que la instanceofoperator.We savent déjà typeofvérifier si MyFunc2mis en œuvre la Callméthode ou not.As MyFunc2est une fonction et il met en œuvre la callméthode, voilà comment typeofsait que c'est un function.On d' autre part, nous avons utilisé function constructorpour créer MyFunc2, il devient une instance de Function constructor. C'est pourquoi instanceofse résout également à true.

Qu'est-ce qui est plus sûr à utiliser?

Comme nous pouvons le voir dans les deux cas, l' typeofopérateur peut affirmer avec succès que nous avons affaire à une fonction ici, elle est plus sûre que instanceof. instanceoféchouera en cas de function declarationparce que function declarationsne sont pas une instance de Function constructor.

Meilleur entrainement :

Comme l'a suggéré Gary Rafferty , la meilleure façon devrait être d'utiliser à la fois 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
AL-zami
la source
toute critique constructive concernant cette réponse sera appréciée.
AL-zami
0

Pour être très précis, instanceof doit être utilisé lorsque la valeur est créée via le constructeur (généralement des types personnalisés), par exemple

var d = new String("abc")

alors que typeof pour vérifier les valeurs créées juste par des affectations pour par exemple

var d = "abc"
Sambhav
la source
0

pas besoin de vous submerger avec une tonne d'exemples ci-dessus, gardez juste à l'esprit deux points de vue:

  1. typeof var;est un opérateur unaire retournera le type d'origine ou le type racine de var. de sorte qu'il sera de retour types primitifs ( string, number, bigint, boolean, undefined, et symbol) ou de objecttype.

  2. dans le cas d'objets de niveau supérieur, comme des objets intégrés (String, Number, Boolean, Array ..) ou des objets complexes ou personnalisés, tous sont de objecttype racine, mais le type d'instance basé sur eux est variable (comme la classe OOP concept d'héritage), ici a instanceof A- un opérateur binaire - vous aidera, il passera par la chaîne du prototype pour vérifier si le constructeur de l'opérande droit (A) apparaît ou non.

donc à chaque fois que vous voulez vérifier "type racine" ou travailler avec une variable primitive - utilisez "typeof", sinon utilisez "instanceof".

nullest un cas spécial, qui est apparemment primitif, mais qui est en effet un cas spécial pour objet. Utiliser a === nullpour vérifier null à la place.

d'autre part, functionest également un cas spécial, qui est un objet intégré mais typeofretournefunction

comme vous pouvez le voir, vous instanceofdevez passer par la chaîne de prototype en attendant, typeofvérifiez simplement le type de racine une fois afin qu'il soit facile de comprendre pourquoi typeofest plus rapide queinstanceof

Lam Phan
la source
0

Selon la documentation MDN sur typeof , les objets instanciés avec le "nouveau" mot-clé sont de type "objet":

typeof 'bla' === 'string';

// The following are confusing, dangerous, and wasteful. Avoid them.
typeof new Boolean(true) === 'object'; 
typeof new Number(1) === 'object'; 
typeof new String('abc') === 'object';

La documentation sur instanceof indique que:

const objectString = new String('String created with constructor');
objectString instanceOf String; // returns true
objectString instanceOf Object; // returns true

Donc, si l'on veut vérifier par exemple que quelque chose est une chaîne, peu importe comment elle a été créée, l'approche la plus sûre serait d'utiliser instanceof.

Laszlo Sarvold
la source