Maison  >  Article  >  interface Web  >  Discutons des pièges de la conversion de type JS

Discutons des pièges de la conversion de type JS

阿神
阿神original
2017-01-23 14:18:041233parcourir

Pourquoi tu dis ça ?
Une question d’entretien m’a donné la motivation de le dire.
La question est la suivante :

var bool = new Boolean(false);
if (bool) {
    alert('true');
} else {
    alert('false');
}

Le résultat est vrai ! ! !
En fait, la conversion de type, la priorité de l'opérateur, ces choses sont toutes les plus élémentaires.
Il y a une introduction détaillée dans le livre sur les rhinocéros. Mais je lis rarement les 5 premiers chapitres du livre Rhino. . .
Par exemple, concernant les priorités, de nombreux livres nous apprennent : "Il n'est pas nécessaire de mémoriser l'ordre de priorité. Si vous n'êtes pas sûr, ajoutez simplement des parenthèses."
Nous le faisons généralement lors de l'écriture de code.
Mais quelle est la réalité ? Ce genre de question vous sera posée lors de l’entretien et il vous sera demandé d’y répondre. . .
Je ne connais vraiment pas le sens de cette question. . .
Les plaintes s'arrêtent ici. Cet article tente de résoudre le problème de conversion de type et essaie de mémoriser le tableau de la page 49 du "JS Definitive Guide".
Quelles sont les fausses valeurs ?
Un total de 6 :

0或+0、-0,NaN
""
false
undefined
null

L'ordre ci-dessus est organisé en fonction des types de base.
Rien d'autre ! ! Même s'il se présente sous la forme suivante :

Infinity
'0'、'false'、" "(空格字符)
任何引用类型:[],{},function(){}

if (a && b), la bonne façon de le comprendre est : a && b évalue l'expression puis la convertit en Type booléen.
&& est une syntaxe de court-circuit. Après évaluation, ce n'est pas nécessairement un type booléen, ni converti en valeurs booléennes des deux côtés puis exploité.
Par exemple, le résultat de 2&&3 est 3, ce qui n'est pas vrai.
Donc if(a && b), ce que nous comprenons habituellement, "si a et b sont vrais en même temps", est une mauvaise façon de le décrire.
D'autres types de base sont convertis en chaînes , ce qui est fondamentalement le même que prévu :

console.log("" + null);      // "null"
console.log("" + undefined); // "undefined"
console.log("" + false);     // "false"
console.log("" + true);      // "true"
console.log("" + 0);         // "0"
console.log("" + NaN);       // "NaN"
console.log("" + Infinity);  // "Infinity"

D'autres types de base sont convertis en nombres , ce qui nécessite mémoire spéciale :

console.log(+null);          // 0
console.log(+undefined);     // NaN
console.log(+false);         // 0
console.log(+true);          // 1
console.log(+"");            // 0
console.log(+'1');           // 1
console.log(+'1x');          // NaN

Où null, le caractère vide est 0 et non défini est NaN.
Ci-dessus, les conversions de types de base sont expliquées clairement.

Jetons un coup d'œil à la conversion des types de référence en types de base.
Type de référence converti en booléen, toujours vrai
Type de référence converti en chaîne

1.优先调用toString方法(如果有),看其返回结果是否是原始类型,如果是,转化为字符串,返回。
2.否则,调用valueOf方法(如果有),看其返回结果是否是原始类型,如果是,转化为字符串,返回。
3.其他报错。

Type de référence converti en nombre

1.优先调用valueOf方法(如果有),看其返回结果是否是基本类型,如果是,转化为数字,返回。
2.否则,调用toString方法(如果有),看其返回结果是否是基本类型,如果是,转化为数字,返回。
3.其他报错。

Tout d'abord, examinons ce que renvoient les types de référence courants toString et valueOf ?

var a = {};
console.dir(a.toString());   // "[object Object]"
console.dir(a.valueOf());    // 对象本身
 
var b = [1, 2, 3];
console.dir(b.toString());   // "1,2,3"
console.dir(b.valueOf());    // 对象本身
 
var c = [[1],[2]];
console.dir(c.toString());   // "1,2"
console.dir(c.valueOf());    // 对象本身
 
var d = function() {return 2};
console.dir(d.toString());   // "function() {return 2}"
console.dir(d.valueOf());    // 对象本身

La conversion correspondante en chaînes et en nombres est donc :

var a = {};
console.dir(a + "");         // "[object Object]"
console.dir(+a);             // NaN
 
var b = [1, 2, 3];
console.dir(b + "");         // "1,2,3"
console.dir(+b);             // NaN
 
var c = [[1],[2]];
console.dir(c + "");         // "1,2"
console.dir(+c);             // NaN
 
var d = function() {return 2};
console.dir(d + "");         // "function () {return 2}"
console.dir(+d);             // NaN

Une autre situation d'erreur :

var a = {};
a.toString = function() {return {};}
console.log("" + a);         // 报错
console.log(+a)              // 报错

Les règles de conversion de type ci-dessus sont pratiquement terminées.

Enfin, parlons du mal « == »
Les questions de l'entretien sont les suivantes :

var a = false;
var b = undefined;
if (a == b) {
    alert('true');
} else {
    alert('false');
}

Je pensais que vrai allait apparaître. Oh mon Dieu ! Pourquoi est-ce faux ?
Haha. . .
Double signe égal, si les types des deux côtés sont différents, une conversion implicite se produira. La page 75 du livre Rhino le résume comme suit :

1,null和undefined,相等。
2,数字和字符串,转化为数字再比较。
3,如果有true或false,转换为1或0,再比较。
4,如果有引用类型,优先调用valueOf。
5,其余都不相等。

Par conséquent :

console.log(undefined == false); // false
console.log(null == false);      // false
console.log(0 == false);         // true
console.log(NaN == false);       // false
console.log("" == false);        // true

0 == false, ce qui est vrai selon la clause 3.
La raison pour laquelle "" == false est vrai selon l'article 3 devient "" == 0, puis selon l'article 2.
Un autre exemple dans l'article 4 :

console.log([[2]] == 2)

Le résultat ci-dessus est vrai pour les raisons suivantes :
La valeur de [[2]] est l'objet lui-même, pas le type de base.
Le résultat de la tentative d'appel de toString est '2'.
Cela devient donc une comparaison entre « 2 » et le chiffre 2. Selon l'article 2, égal. WTF !!
Enfin, utiliser "===" éliminera ces problèmes.
Cet article est terminé.

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn