類型&值
內(nèi)置類型: 7種 (null| undefined | boolean | number| string | object | symbol)
值類型轉(zhuǎn)換
Number<->String
let a = 123;
a.toString() //‘123’
String(a) //‘123’ String() 遵循toString()規(guī)范
let c = '3.14'
Number(c) //3.14
因?yàn)閿?shù)組的valueOf()無法轉(zhuǎn)換為簡單類型值,于是轉(zhuǎn)而調(diào)用ToString()
* 結(jié)合ES5規(guī)范談字符串轉(zhuǎn)換
如果其中一個(gè)操作數(shù)為字符串或通過調(diào)用Topermitive抽象操作后,再調(diào)用 [[DefaultValue]],以數(shù)字作為上下文,執(zhí)行拼接操作;否則進(jìn)行數(shù)字加法;
「這個(gè)地方有些繞,再查下規(guī)范」

let a = {
valueOf: () => 2;
toString: (num) => '44'
}
a+ ' ' // '2'
String(a) //'44'
因此我們在定義valueOf 和toString方法時(shí)要慎重,因?yàn)闀?huì)影響強(qiáng)制類型轉(zhuǎn)換結(jié)果。
- 不建議使用封裝對(duì)象直接進(jìn)行判斷,因?yàn)榉祷氐闹凳冀K為 true
let a = new String("abc");
typeof a // "object"
a instanceof String // true
Object.prototype.toString.call(a) // "[object String]"
Number<->Boolean
// 判斷多個(gè)參數(shù)下是否唯一一個(gè)為true
const onlyOne= (args) => {
let sum = 0;
for(let i = 0,len = args.length; i < len; i++) {
sum += Number(!!args[i]);
}
return sum === 1;
}
a = true;
b = false;
p(onlyOne([a,b]))
symbol <-> anyType
ES6中出現(xiàn)的 symbol 類型不能夠轉(zhuǎn)換為Number String

var s2= Symbol("not cool");
s2 + "" // TypeError
Symbol("foo") === Symbol("foo"); // false
typeof 運(yùn)算符能幫助識(shí)別symbol類型
typeof Symbol() === 'Symbol'
typeof Symbol('foo') === 'Symbol'
Boolean <-> String/Others
掌握真 / 假值的重點(diǎn)在于理解布爾強(qiáng)制類型轉(zhuǎn)換
- 規(guī)律總結(jié)
以下這些是假值:
?undefined
?null
?false
?+0、-0和NaN
?""
假值的布爾強(qiáng)制類型轉(zhuǎn)換結(jié)果為 false - 顯式調(diào)用
Boolean()進(jìn)行強(qiáng)制類型轉(zhuǎn)換
var a = "0";
var b = [];
var c = {};
var d = "";
var e = 0;
var f = null;
var g;
Boolean( a ); // true
Boolean( b ); // true
Boolean( c ); // true
Boolean( d ); // false
Boolean( e ); // false
Boolean( f ); // false
Boolean( g ); // false
- 使用 運(yùn)算符
!!顯式地將值強(qiáng)制類型轉(zhuǎn)換為布爾值, 包含一次強(qiáng)制Boolean類型轉(zhuǎn)換,將真值反轉(zhuǎn)為假值再反轉(zhuǎn)回來。
數(shù)字
判斷是否相等
設(shè)置機(jī)器精度 Number.EPSILON = Math.pow(2,-52);
Math.abs(n1 - n2) < Number.EPSILON;判斷是否為整數(shù)
Number.isInteger()
polyfill 版本
return typeof num == 'number' && num % 1 == 0x的引用還是副本
x.length = 0 x.push (4,5,6,7) 并沒有創(chuàng)建一個(gè)新數(shù)組,而是改變了當(dāng)前的數(shù)組
通過值復(fù)制傳遞復(fù)合值(如數(shù)組),就需要?jiǎng)?chuàng)建一個(gè)副本;
對(duì)象
封裝
var a = new Boolean(false);
得到的不是 false,而是一個(gè)真值
類型轉(zhuǎn)換
- 日期顯式轉(zhuǎn)換為數(shù)字
let l = new Date(); //1563943975689
let timeStamp = new Date().getTime();
// es5 中的方法
timeStamp = Date.now();
// Date.now() 的polyfill
if(!Date.now) {
Date.now = function () {
return +new Date();
}
}
- 使用~進(jìn)行 32位運(yùn)算
~x 大致等于 -(x+1)
if(~a.indexOf('xx')) {
console.log("當(dāng)前沒有找到匹配")
}
~~只適用于32位的數(shù)字
Math.floor(-49.6) // -50
~~(-49.6) // -50
- parseInt(...)
將參數(shù)強(qiáng)制處理為字符串再解析
parseInt(1/0, 19) // 18 1/0 處理為Infinity n為無效字符,只處理到I,按照19進(jìn)制 得到18 - Boolean(...)顯式轉(zhuǎn)換
4.1 最常用: !!
a = !!"0" && !!{} && !![] // true
d = !!"" && !!0 && !!null !!undefined // false
Boolean(a)
&& || 操作符
|| 返回的是對(duì)應(yīng)的值 不同于C語言中的 true | false
守護(hù)運(yùn)算符&&
function fn() {
console.log(a);
}
a && fn()
// fn在條件判斷通過時(shí)才會(huì)執(zhí)行
其他類型和布爾類型之間的相等比較
如果Type(x)是boolean類型,結(jié)果返回 ToNumber(x) == y
let x = true;
let y = "42"
x == y; // false
// x被強(qiáng)制轉(zhuǎn)換為1; 1 == '42'
null undefined 之前的強(qiáng)制類型轉(zhuǎn)換是安全的
對(duì)象與非對(duì)象之間的相等比較
對(duì)象通過 Topremitive進(jìn)行強(qiáng)制類型轉(zhuǎn)換(如 toString()、 valueOf())
- 抽象關(guān)系比較
2.1 雙方都是字符串,按照字母順序來比較
2.2 為了保證安全,應(yīng)該在關(guān)系比較中進(jìn)行顯示強(qiáng)制類型轉(zhuǎn)化;
var a = { b : 2};
var b = { b : 3};
a > b //flase
a == b //false
a < b //false
a >= b // true a<=b 被處理為 !(a>b) 小于等于其實(shí)是不大于
a <= b //true
運(yùn)算符優(yōu)先級(jí)
Javascript中的 && 和 || 運(yùn)算符返回它們其中一個(gè)操作數(shù)的值,而非 true 或者 false
數(shù)字精度
類數(shù)組:字符串和數(shù)組都是類數(shù)組,擁有l(wèi)ength和indexof(...)和concat(...)
字符串可以借用數(shù)組的方法,使用call
let dUpper = Array.prototype.map.call(a,function(v) {
return v.toUpperCase()+ '.';
}).join("");
浮點(diǎn)數(shù):設(shè)定誤差范圍 2^-52
ES6中定義了Number.EPSILON代表浮點(diǎn)數(shù)的誤差范圍
//polyfill
if(!Number.EPSILON)
{
Number.EPSILON = Math.pow(2,-52);
}
數(shù)字類型包含幾個(gè)特殊值: -Infinity +Infinity -0
特殊的數(shù)值 NaN
不是數(shù)字的數(shù)字 仍是數(shù)字類型
typeof NaN === "number"
NaN 為非自反的值 NaN !== NaN 使用內(nèi)建函數(shù)isNaN()判斷 該函數(shù)有個(gè)嚴(yán)重bug 判斷當(dāng)前數(shù)字不是NaN類型,也不是Number類型
math工具函數(shù)中 isNaN 的polyfill
if(!Number.isNaN) {
Number.isNaN = function(n) {
return typeof n === 'Number' && window.isNaN(n);
}
}
區(qū)分正負(fù)0
function isNegZero(n) {
n = Number(n);
return (n === 0) && (1/n === -Infinity)
}
ES6中出現(xiàn)了 Object.is(...) 判斷兩個(gè)值是否完全相等,能夠使用== / === ,不使用 Object.is() 因?yàn)榍罢咝矢吒ㄓ?/p>
mentor's question
- 為什么+-Infinity Boolean后為 true
根據(jù)MDN web docs
-Infinity 仍為真值, Infinity是一個(gè)全局對(duì)象的一個(gè)屬性,即它是一個(gè)全局變量.
*JavaScript 中的真值示例如下(將被轉(zhuǎn)換為 true,if 后的代碼段將被執(zhí)行)
if (true)
if ({})
if ([])
if (42)
if ("foo")
if (new Date())
if (-42)
if (3.14)
if (-3.14)
if (Infinity)
if (-Infinity)
標(biāo)志
symbol這個(gè)基本類型的作用是什么?
一種不可變的并且值唯一的基本數(shù)據(jù)類型,用于定義屬性的key, 防止在多個(gè)屬性同時(shí)作用于對(duì)象時(shí)由于屬性重復(fù)引發(fā)覆蓋。object 轉(zhuǎn)為number 類型,得到的結(jié)果
如果有對(duì)應(yīng)的數(shù)值可以轉(zhuǎn)換,得到數(shù)值,如果不能對(duì)應(yīng)轉(zhuǎn)換 NaN
let test1 = new Boolean(true) //undefined
let test2 = new Boolean(false) //undefined
Number(test1) //1
Number(test2) //0
let test3 = new Date() // Thu Aug 22 2019 10:57:06 GMT+0800 (中國標(biāo)準(zhǔn)時(shí)間)
Number(test3) //1566442626454 得到的是時(shí)間戳
let test4 = new String('999');
Number(test4) //999
let test5 = new String('999 888');
Number(test5) // NaN
let test6 = {
a: {
hahah: 'jajaja'
}
}
Number(test6) //NaN