Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Einführung in Operatorregeln und implizite Typkonvertierungen in JavaScript

Detaillierte Einführung in Operatorregeln und implizite Typkonvertierungen in JavaScript

巴扎黑
巴扎黑Original
2017-09-07 11:51:141223Durchsuche

Was ist die implizite Typkonvertierung von Operatorregeln in JavaScript? Dies ist eine Frage, die jeder Anfänger kennen sollte, der JavaScript lernt. Der folgende Artikel stellt Ihnen hauptsächlich die Operatorregeln und die implizite Typkonvertierung in JavaScript vor Werfen wir einen Blick auf die relevanten Informationen zur Typkonvertierung.

Vorwort

In diesem Artikel werden hauptsächlich relevante Inhalte zu JavaScript-Operatorregeln und impliziter Typkonvertierung vorgestellt und als Referenz weitergegeben. Ich werde im Folgenden nicht viel mehr sagen, werfen wir einen Blick auf die ausführliche Einführung.

Implizite Typkonvertierung

In JavaScript, wenn wir Vergleichsoperationen oder die vier arithmetischen Operationen Addition, Subtraktion, Multiplikation usw. durchführen Bei der Division lösen wir häufig den impliziten Typkonvertierungsmechanismus von JavaScript aus. Dieser Teil ist oft verwirrend. Beispielsweise wandelt die Operation console.log im Browser häufig jeden Wert in eine Zeichenfolge um und zeigt ihn dann an, während mathematische Operationen den Wert zunächst in einen numerischen Typ konvertieren (außer bei Objekten vom Typ „Datum“) und dann Operationen ausführen.

Sehen wir uns zunächst einige Sätze typischer Bedienergebnisse in JavaScript an. Wir hoffen, dass wir nach dem Lesen dieses Abschnitts jedes Element angemessen erklären können:


// 比较
[] == ![] // true
NaN !== NaN // true

1 == true // true
2 == true // false
"2" == true // flase

null > 0 // false
null < 0 // false
null == 0 // false
null >= 0 // true

// 加法
true + 1 // 1
undefined + 1 // NaN

let obj = {};

{} + 1 // 1,这里的 {} 被当成了代码块
{ 1 + 1 } + 1 // 1

obj + 1 // [object Object]1
{} + {} // Chrome 上显示 "[object Object][object Object]",Firefox 显示 NaN

[] + {} // [object Object]
[] + a // [object Object]
+ [] // 等价于 + "" => 0
{} + [] // 0
a + [] // [object Object]

[2,3] + [1,2] // &#39;2,31,2&#39;
[2] + 1 // &#39;21&#39;
[2] + (-1) // "2-1"

// 减法或其他操作,无法进行字符串连接,因此在错误的字符串格式下返回 NaN
[2] - 1 // 1
[2,3] - 1 // NaN
{} - 1 // -1

Konvertierung zwischen primitiven Typen

Zu den primitiven Typen, über die wir in JavaScript häufig sprechen, gehören numerische Typen, Zeichenfolgentypen sowie boolesche Typen und leere Typen ; und die Konvertierungsfunktionen zwischen unseren häufig verwendeten primitiven Typen sind String, Number und Boolean:


// String
let value = true;
console.log(typeof value); // boolean

value = String(value); // now value is a string "true"
console.log(typeof value); // string

// Number
let str = "123";
console.log(typeof str); // string

let num = Number(str); // becomes a number 123

console.log(typeof num); // number

let age = Number("an arbitrary string instead of a number");

console.log(age); // NaN, conversion failed

// Boolean
console.log( Boolean(1) ); // true
console.log( Boolean(0) ); // false

console.log( Boolean("hello") ); // true
console.log( Boolean("") ); // false

Schließlich können wir die folgende JavaScript-Primitivtyp-Konvertierungstabelle erhalten (einschließlich Beispiele für die Konvertierung von zusammengesetzten Typen in primitive Typen):

原始值 转化为数值类型 转化为字符串类型 转化为 Boolean 类型
false 0 "false" false
true 1 "true" true
0 0 "0" false
1 1 "1" true
"0" 0 "0" true
"1" 1 "1" true
NaN NaN "NaN" false
Infinity Infinity "Infinity" true
-Infinity -Infinity "-Infinity" true
"" 0 "" false
"20" 20 "20" true
"twenty" NaN "twenty" true
[ ] 0 "" true
[20] 20 "20" true
[10,20] NaN "10,20" true
["twenty"] NaN "twenty" true
["ten","twenty"] NaN "ten,twenty" true
function(){} NaN "function(){}" true
{ } NaN "[object Object]" true
null 0 "null" false
undefined NaN "undefined" false

ToPrimitive

在比较运算与加法运算中,都会涉及到将运算符两侧的操作对象转化为原始对象的步骤;而 JavaScript 中这种转化实际上都是由 ToPrimitive 函数执行的。实际上,当某个对象出现在了需要原始类型才能进行操作的上下文时,JavaScript 会自动调用 ToPrimitive 函数将对象转化为原始类型;譬如上文介绍的 alert 函数、数学运算符、作为对象的键都是典型场景,该函数的签名如下:


ToPrimitive(input, PreferredType?)

为了更好地理解其工作原理,我们可以用 JavaScript 进行简单地实现:


var ToPrimitive = function(obj,preferredType){
 var APIs = {
 typeOf: function(obj){
  return Object.prototype.toString.call(obj).slice(8,-1);
 },
 isPrimitive: function(obj){
  var _this = this,
   types = [&#39;Null&#39;,&#39;Undefined&#39;,&#39;String&#39;,&#39;Boolean&#39;,&#39;Number&#39;];
  return types.indexOf(_this.typeOf(obj)) !== -1; 
 }
 };
 // 如果 obj 本身已经是原始对象,则直接返回
 if(APIs.isPrimitive(obj)) {return obj;}
 
 // 对于 Date 类型,会优先使用其 toString 方法;否则优先使用 valueOf 方法
 preferredType = (preferredType === &#39;String&#39; || APIs.typeOf(obj) === &#39;Date&#39; ) ? &#39;String&#39; : &#39;Number&#39;;
 if(preferredType===&#39;Number&#39;){
 if(APIs.isPrimitive(obj.valueOf())) { return obj.valueOf()};
 if(APIs.isPrimitive(obj.toString())) { return obj.toString()};
 }else{
 if(APIs.isPrimitive(obj.toString())) { return obj.toString()};
 if(APIs.isPrimitive(obj.valueOf())) { return obj.valueOf()};
 }
 throw new TypeError(&#39;TypeError&#39;);
}

我们可以简单覆写某个对象的 valueOf 方法,即可以发现其运算结果发生了变化:


let obj = {
 valueOf:() => {
  return 0;
 }
}

obj + 1 // 1

如果我们强制将某个对象的 valueOf 与 toString 方法都覆写为返回值为对象的方法,则会直接抛出异常。


obj = {
  valueOf: function () {
   console.log("valueOf");
   return {}; // not a primitive
  },
  toString: function () {
   console.log("toString");
   return {}; // not a primitive
  }
 }

obj + 1
// error
Uncaught TypeError: Cannot convert object to primitive value
 at <anonymous>:1:5

值得一提的是对于数值类型的 valueOf() 函数的调用结果仍为数组,因此数组类型的隐式类型转换结果是字符串。而在 ES6 中引入 Symbol 类型之后,JavaScript 会优先调用对象的 [Symbol.toPrimitive] 方法来将该对象转化为原始类型,那么方法的调用顺序就变为了:

  • obj[Symbol.toPrimitive](preferredType) 方法存在时,优先调用该方法;

  • 如果 preferredType 参数为 String,则依次尝试 obj.toString() obj.valueOf()

  • 如果 preferredType 参数为 Number 或者默认值,则依次尝试 obj.valueOf() obj.toString()

[Symbol.toPrimitive] 方法的签名为:


obj[Symbol.toPrimitive] = function(hint) {
 // return a primitive value
 // hint = one of "string", "number", "default"
}

我们同样可以通过覆写该方法来修改对象的运算表现:


user = {
 name: "John",
 money: 1000,

 [Symbol.toPrimitive](hint) {
 console.log(`hint: ${hint}`);
 return hint == "string" ? `{name: "${this.name}"}` : this.money;
 }
};

// conversions demo:
console.log(user); // hint: string -> {name: "John"}
console.log(+user); // hint: number -> 1000
console.log(user + 500); // hint: default -> 1500

比较运算

JavaScript 为我们提供了严格比较与类型转换比较两种模式,严格比较(===)只会在操作符两侧的操作对象类型一致,并且内容一致时才会返回为 true,否则返回 false。而更为广泛使用的 == 操作符则会首先将操作对象转化为相同类型,再进行比较。对于 2dd284eb846c08b555a8f6139eda41ae= 0 为 true 的这种比较结果,在 ECMAScript 中还规定,如果 f73075bc4db316bc8a250ad82b87ad42= 为 true。

加法运算

对于加法运算而言,JavaScript 首先会将操作符两侧的对象转换为 Primitive 类型;然后当适当的隐式类型转换能得出有意义的值的前提下,JavaScript 会先进行隐式类型转换,再进行运算。譬如 value1 + value2 这个表达式,首先会调用 ToPrimitive 函数将两个操作数转化为原始类型:


prim1 := ToPrimitive(value1)
prim2 := ToPrimitive(value2)

这里将会优先调用除了 Date 类型之外对象的 valueOf 方法,而因为数组的 valueOf 方法的返回值仍为数组类型,则会返回其字符串表示。而经过转换之后的 prim1 与 prim2 中的任一个为字符串,则会优先进行字符串连接;否则进行加法计算。

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in Operatorregeln und implizite Typkonvertierungen in JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn