你不知道的JavaScript--Item3 隱式強制轉換
JavaScript的資料型別分為六種,分別為null,undefined,boolean,string,number,object。
object是引用型別,其它的五種是基本型別或者是原始型別。我們可以用typeof方法列印來某個是屬於哪個型別的。不同型別的變數比較要先轉型別,叫做型別轉換,型別轉換也叫隱式轉換。隱式轉換通常發生在運算子加減乘除,等於,還有小於,大於等。。
typeof '11' //string
typeof(11) //number
'11' < 4 //false
1、基本型別的轉換
下面先講加減乘除:
1. 字串加數字,數字就會轉成字串。
2. 數字減字串,字串轉成數字。如果字串不是純數字就會轉成NaN。字串減數字也一樣。兩個字串相減也先轉成數字。
3. 乘,除,大於,小於跟減的轉換也是一樣。
//隱式轉換 + - * == /
// +
10 + '20' //'2010'
// -
10 - '20' //-10
10 - 'one' //NaN
10 - '100a' //NaN
// *
10*'20' //200
'10'*'20' //200
// /
20/'10' //2
'20'/'10' //2
'20'/'one' //NaN
4、加法操作順序是敏感的
類似這樣的混合表示式有時令人困惑,因為 JavaScript 對操作順序是敏感的。例如,表示式:
1+2+"3"; //"33"
由於加法運算是自左結合的(即左結合律),因此,它等同於下面的表示式:
(1+2)+"3"; //"33"
與此相反,表示式:
1+"2"+3; //"123"
的計算結果為字串“123”。左結合律相當於是將表示式左側的加法運算包裹在括號中。
5、再來看看一組 ==
1.undefined等於null
2.字串和數字比較時,字串轉數字
3.數字為布林比較時,布林轉數字
4.字串和布林比較時,兩者轉數字
// ==
undefined == null; //true
'0' == 0; //true,字串轉數字
0 == false; //true,布林轉數字
'0' == false; //true,兩者轉數字
null == false; //false
undefined == false; //false
7個false值:false,0,-0,“”,NaN,null以及undefined,所有其他值都是truth
6、NaN,不是一個數字
NaN 是一個特殊值,說明某些算術運算(如求負數的平方根)的結果不是數字。方法 parseInt() 和 parseFloat() 在不能解析指定的字串時就返回這個值。對於一些常規情況下返回有效數字的函式,也可以採用這種方法,用 Number.NaN 說明它的錯誤情況。
Math.sqrt(-2)
Math.log(-1)
0/0
parseFloat('foo')
對於很多JavaScript的初學者來說,它的第一個陷阱是呼叫typeof時返回結果的通常是你想不到的:
console.log(typeof NaN); // 'Number'
這情情況下,NaN並不意味著是一個數字,它的型別是數字。明白嗎?
因為typeof 返回的是字串,有六種:“number”、”string”、”boolean”、”object”、”function”、”undefined
保持冷靜,因為下面還有很多混亂的地方。讓我們比較兩個NaN:
var x = Math.sqrt(-2);
var y = Math.log(-1);
console.log(x == y); // false
也許這是因為我們沒有使用嚴格等價(===)操作?顯然不是。
var x = Math.sqrt(-2);
var y = Math.log(-1);
console.log(x === y); // false
直接比較兩個NaN呢?
console.log(NaN === NaN); // false
因為有很多方法來表示一個非數字,所以一個非數字不會等於另一個為NaN的非數字,它還是有一定道理的。
但是當然,解決方案現在已經有了。讓我們認識一下全域性函式isNaN:
console.log(isNaN(NaN)); // true
唉,不過 isNaN() 也有它自己的很多缺陷呀:
console.log(isNaN('hello')); // true
console.log(isNaN(['x'])); // true
console.log(isNaN({})); // true
這樣又產生 了很多不同的解決方案。其中一個是利用 了NaN的非反射性質(例如, 看看 Kit Cambridge 的筆記)
var My = {
isNaN: function (x) { return x !== x; }
}
不過幸運的是,在即將到來的ECMAScript 6中, 有一個Number.isNaN() 方法提供可靠的NaN值檢測。
換句話說,只有在引數是真正的NaN時,才會返回true
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN(Math.sqrt(-2))); // true
console.log(Number.isNaN('hello')); // false
console.log(Number.isNaN(['x'])); // false
console.log(Number.isNaN({})); // false
2、引用型別的轉換
基本型別間的比較相對簡單。引用型別和基本型別的比較就相對複雜一些,先要把引用型別轉成基本型別,再按上述的方法比較。
1、引用型別轉布林全是true。
比如空陣列,只要是物件就是引用型別,所以[]為true。引用型別轉數字或者字串就要用valueOf()或者toString();物件本身就繼承了valuOf()和toString(),還可以自定義valueOf()和toString()。根據不同的物件用繼承的valueOf()轉成字串,數字或本身,而物件用toString就一定轉為字串。一般物件預設呼叫valueOf()。
1.物件轉數字時,呼叫valueOf();
2.物件轉字串時,呼叫toString();
先看看下面的例子:
0 == []; // true, 0 == [].valueOf(); ---> 0 == 0;
'0' == []; // false, '0' == [].toString(); ---> '0' == '';
2 == ['2']; // true, 2 == ['2'].valueOf(); ---> 2 == '2' ---> 2 == 2;
'2' == [2]; // true, '2' == [2].toString(); ---> '2' =='2';
[] == ![]; //true, [].valueOf() == !Boolean([]) -> 0 == false ---> 0 == 0;
物件轉成數字時,呼叫valueOf(),在這之前先呼叫的是toString();所以我猜valueOf方法是這樣的。So上面的例子 0 == []要改成下面更合理。無論如何,[]最後是轉成0的。
var valueOf = function (){
var str = this.toString(); //先呼叫toString(),轉成字串
//...
}
0 == []; // true, 0 == [].valueOf(); -> 0 == '0' -> 0 == 0;
自定義的valueOf()和toString();
自定義的valueOf()和toString()都存在,會預設呼叫valueOf();
如果只有toString(),則呼叫toString();
var a = [1];
a.valueOf = function (){ return 1;}
a.toString = function (){ return '1';}
a + 1; // 2, valueOf()先呼叫
去掉valueOf()就會呼叫toString()。
var a = [1];
a.valueOf = function (){ return 1;}
a.toString = function (){ return '1';}
a + 1; // 2, 先呼叫valueOf()
//去掉valueOf
delete a.valueOf;
a + 1; // '11', 呼叫toString()
如果返回其它會怎麼樣呢?
var a = [1];
a.valueOf = function (){return ;}
a.toString = function (){return 1 ;};
1 - a; //NaN
其它物件 呼叫valueOf()轉成不同的型別:
var a = {};
a.valueOf(); //Object {}
var a = [];
a.valueOf(); //[] 自己本身
var a = new Date();
a.valueOf(); //1423812036234 數字
var a = new RegExp();
a.valueOf(); // /(?:)/ 正則物件
引用型別之間的比較是記憶體地址的比較,不需要進行隱式轉換,這裡不多說。
[] == [] //false 地址不一樣
var a = [];
b = a;
b == a //true
2、顯式轉換
顯式轉換比較簡單,可以直接用類當作方法直接轉換。
Number([]); //0
String([]); //”
Boolean([]); //true
還有更簡單的轉換方法。
3 + ” // 字串’3’
+’3’ // 數字3
!!’3’ // true
相關文章
- 從[] == ![] 看隱式強制轉換機制
- 你所忽略的js隱式轉換JS
- 【轉】css樣式自動換行(強制換行)CSS
- 第五篇:你“ 看不見 ” 的隱式轉換
- js顯式轉換和隱式轉換JS
- javascript 隱式轉換JavaScript
- sql隱式轉換SQL
- Oracle 隱式轉換Oracle
- java隱式轉換Java
- 強制型別轉換型別
- 沿著平滑的曲線學會 JavaScript 中的隱式強制型別轉換(基礎篇)JavaScript型別
- Scala - 隱式轉換和隱式引數
- Scala隱式轉換與隱式引數
- 【隱式轉換】注意隱式轉換將導致索引無法使用索引
- Scala Essentials: 隱式轉換
- [] == ![],走進==隱式轉換的世界
- 強制型別轉換之(==)型別
- Day08——強制轉換
- PHP 型別轉換&&型別強制轉換PHP型別
- C++ 的強制型別轉換C++型別
- JavaScript中的強制型別轉換JavaScript型別
- Java資料型別的顯式轉換和隱式轉換Java資料型別
- 沿著平滑的曲線學會 JavaScript 中的隱式強制型別轉換(實戰應用篇)JavaScript型別
- scala中隱式轉換之隱式轉換呼叫類中本不存在的方法
- java型別轉換與強制型別轉換(轉)Java型別
- JavaScript隱式型別轉換JavaScript型別
- mysql隱式轉換問題MySql
- MySQL 隱式型別轉換MySql型別
- 【C++】禁止隱式轉換C++
- Spark中的三種隱式轉換Spark
- MySQL和Oracle中的隱式轉換MySqlOracle
- C++隱式型別的轉換C++型別
- 資料型別的隱式轉換資料型別
- 有趣的JavaScript隱式型別轉換JavaScript型別
- C++強制型別轉換C++型別
- 造型與強制型別轉換型別
- JS在if中的強制型別轉換JS型別
- 引用型別變數的強制轉換型別變數