你应该知道的JS--类型

数据类型

内置类型

在 JavaScript 中有七种数据类型:算法

  • 空值(null)
  • 未定义(undefined)
  • 布尔值(boolean)
  • 数字(number)
  • 字符串(string)
  • 对象(object)
  • 符号(symbol)

类型检测

咱们一般是使用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 为储存其类型信息函数

  • 000: 对象
  • 010: 浮点数
  • 100: 字符串
  • 110: 布尔
  • 1: 整数 可是对于undefiendnull来讲,这两个值的存储信息比较特殊,null的全部机器码全是 0,undefeind-2^30表示,由于null的机器码全是 0 因此typeofnull看成对象来看,可是用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

  1. 若是存在静态方法Symbol.hasInstance。则使用他
class Animal {
  static [Symbol.hasInstance](obj){
    if(obj.canEat) return true;
  }
}

let obj = { canEat: true };
alert(obj instanceOf Animal); // true
复制代码
  1. 大多数构造函数没有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]
复制代码

类型转换

将值从一种类型和另外一种类型一般称为类型转换,下面是他们转换的规则:

  1. ToString

基本类型值的字符串化规则是:

  • undefined -> undefined
  • Null -> null
  • Boolean -> true返回"true", false返回false
  • Number -> 'number'
  • Symbol -> throw typeError

对普通对象来讲,除非本身定义[Symbol.toStringTag]方法,不然toString()会返回内部属性[[class]]的值。固然若是对象本身有toString方法,则会调用该方法使用其返回值

  1. ToNumber

基本类型值的数字化规则是:

  • undefined -> NaN
  • Null -> +0
  • Boolean -> true返回1,false返回+0
  • Symbol -> throw TypeError

对象应用如下步骤:

  1. 调用ToPrimitive转换成基本类型值
  2. 以后再调用ToNumber

字符串: ToNumber 应用在字符串上会去检测是否数字,若是不是数字那么结果是NaN

  1. ToBoolean

基本类型值的布尔化规则是:

  • undefiend -> false
  • Null -> false
  • Number -> 除了+0, -0, NaN,其余返回true
  • String -> 除了" "返回false其余返回false
  • Symbol -> true
  • Object -> true
  1. ToPrimitive

当咱们须要将对象类型转换成基本类型的时候,使用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 尝试查找并调用三个对象方法

  1. 调用obj[Symbol.toPrimitive](hint)若是方法存在
  2. 不然,若是提示是string,尝试obj.toString()obj.valueOf()不管存在
  3. 不然,若是提示是numberdefault,尝试obj.valueOf()obj.toString(),不管存在

宽松相等(==)

ES 规范定义了抽象相等比较算法类定义==运算符,该算法涵盖了全部的类型组合,以及他们 进行强制类型转换的方式

  1. 若是 x 或 y 中有一个为 NaN,则返回 false;
  2. 若是 x 与 y 皆为 null 或 undefined 中的一种类型,则返回 true(null == undefined // true);不然返回 false(null == 0 // false);
  3. 若是 x,y 类型不一致,且 x,y 为 String、Number、Boolean 中的某一类型,则将 x,y 使用 ToNumber 函数转化为 Number 类型再进行比较;
  4. 若是 x,y 中有一个为 Object,而另外一个为字符串, 数字或符号, 则首先使用 ToPrimitive 函数将其转化为原始类型,再进行比较。
相关文章
相关标签/搜索