在 JavaScript 中有七种数据类型:算法
咱们一般是使用typeof
运算符来查看值的类型,他返回的是类型的字符串值。bash
typeof undefiend === 'undefined' // true
typeof true === 'boolean' // true
typeof 42 === 'number' // true
typeof "42" === 'string' // true
typeof { life: 42 } === 'object' // true
typeof Symbol() === 'symbol' // true
复制代码
以上六种基本类型均有同名的字符串之与之对应。而null
类型不在此列,他比较特殊,typeof 对他的处理有问题ide
typeof null === 'object' // true
复制代码
这是由于 js 在底层储存变量的时候,会在变量的机器码的低位 1~3 为储存其类型信息函数
undefiend
和null
来讲,这两个值的存储信息比较特殊,null
的全部机器码全是 0,undefeind
用-2^30
表示,由于null
的机器码全是 0 因此typeof
把null
看成对象来看,可是用instanceOf
进行判断的话null instanceof null // TypeError: Right-hand side of 'instanceof' is not an object
复制代码
null 被直接判断为不是对象, 咱们还能够经过instanceOf
来判断一个实例是否属于某种类型。例如ui
class animal{}
let cat = new animal();
cat iinstanceOf animal // true
复制代码
也支持内置类型spa
let arr = [1, 2, 3];
alert(arr instanceOf Array); // true
alert(arr instanceOf Object); // true
复制代码
注意: arr
也属于Object
,这是由于 Array 原型继承Object
之因此会这样,就涉及到instanceOf
的原理了。检查类型是否在实例的原型链上。 obj instanceOf Class
的算法大体以下prototype
Symbol.hasInstance
。则使用他class Animal {
static [Symbol.hasInstance](obj){
if(obj.canEat) return true;
}
}
let obj = { canEat: true };
alert(obj instanceOf Animal); // true
复制代码
Symbol.hasInstance
。在这种状况下,检查class.prototype
是否等于obj
原型链中的原型之一。obj.__proto__ === class.prototype
onj.__proto__.__proto__ === class.prototype
复制代码
在继承的状况下:3d
class Animal {}
class Rabbit extends Animal {}
let rabbit = new Rabbit();
alert(rabbit instaneOf Animal); // true
// rabbit.__proto__ === Rabbit.prototype
// rabbit.__proto__.__proto__ === Animal.prototype
复制代码
固然这种方法也会有原型链断裂的风险,例如:code
function Rabbt(){}
let rabbit = new Rabbit();
Rabbit.prototype = {};
console.log(rabbit instanceOf Rabbit); // false
复制代码
如今咱们一般使用Object.prototype.toString.call
方法来检测的类型:cdn
let s = Object.prototype.toString;
s.call(123); // [object, Number]
s.call(null); // [object null]
s.call(alert); // [object Function]
复制代码
固然咱们也能够去自定义一个toString
行为
let user = {
[Symbol.toStringTag]: 'user'
}
consle.log({}.toString.call(user)); // [object, User]
复制代码
将值从一种类型和另外一种类型一般称为类型转换,下面是他们转换的规则:
基本类型值的字符串化规则是:
undefined
null
true
返回"true"
, false
返回false
throw typeError
对普通对象来讲,除非本身定义[Symbol.toStringTag]
方法,不然toString()
会返回内部属性[[class]]
的值。固然若是对象本身有toString
方法,则会调用该方法使用其返回值
基本类型值的数字化规则是:
NaN
+0
true
返回1
,false
返回+0
throw TypeError
对象应用如下步骤:
ToPrimitive
转换成基本类型值ToNumber
字符串: ToNumber 应用在字符串上会去检测是否数字,若是不是数字那么结果是NaN
基本类型值的布尔化规则是:
false
false
+0, -0, NaN
,其余返回true
" "
返回false
其余返回false
true
true
当咱们须要将对象类型转换成基本类型的时候,使用ToPrimitive
算法,将其转换为基本类型 该算法容许咱们用特殊的对象方法自定义转换,这取决于上下文的提示 提示分为三种
string
: 当一个操做指望一个字符串时,用于对象到字符串的转换alert(obj)
// 使用对象当键名
another[obj] = 123 // obj 为 [object object]
复制代码
number
: 当一个操做须要一个数字的时候,用于对象到数字的转换,例如数学公式let num = Number(obj);
let n = +obj;
let delta = date1 - date2;
let greater = user1 > user2
复制代码
default
: 在少数状况下,操做不肯定指望的类型的时候,例如+
运算符能够是拼接字符串或者数学公式相加或者当一个对象==
与字符串,数字或符号进行比较时。let total = car1 + car2
// obj == string/number/symbol
if(user == 1){ ... }
复制代码
为了进行转换,JavaScript 尝试查找并调用三个对象方法
obj[Symbol.toPrimitive](hint)
若是方法存在string
,尝试obj.toString()
和obj.valueOf()
不管存在number
或default
,尝试obj.valueOf()
和obj.toString()
,不管存在ES 规范定义了抽象相等比较算法类定义==
运算符,该算法涵盖了全部的类型组合,以及他们 进行强制类型转换的方式