【js数据类型相关知识】七零八碎的数据类型相关的知识

181 阅读4分钟

javascript数据类型

  • 7种基本类型: null,undefined,boolean,number,string,object,symbol
  • 其中基本类型:null,undefined,boolean,number,string
  • 引用类型object又包括:function、array、date等。

判断数据类型的几种方式

方式一:typeof

如下面所示:

  1. typeof可以直接判断出 number、string、undefined、boolean、symbol这几种类型。
  2. 对于null会被“误判”成object类型。
  3. 可以判断出object类型中的function类型
console.log(typeof 100);//number
console.log(typeof 'name');//string
console.log(typeof undefined);//undefined
console.log(typeof false);//boolean
console.log(typeof null);//object
const foo = function () { }
console.log(typeof foo);//function
console.log(typeof {});//object
console.log(typeof []);//object
const now = new Date();//object
console.log(typeof now);
console.log(typeof Symbol("foo"))//symbol

方式二 instanceof 多用于原型链的判断

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

function Dog(){
}
let dog = new Dog();
console.log(dog instanceof Dog)//true

instanceof的原理是一层一层向上查找原型链

function myInstanceofFun(Lobj, RconsFunc) {
   if (typeof Lobj == 'object') {//排除基本类型
       return false;
   }
   while (true) {
       if (Lobj === null) {//let o = new Object() o.__proto__.__proto__===null
       return false;
   }
  if (Lobj._proto_ === RconsFunc.prototype) {
       return true;
  }
    Lobj = Lobj._proto_; //
  }
}

方式三 Object.prototype.toString

可以判断出所有的类型,但是判断结果不是标准格式,需要自己转换

console.log(Object.prototype.toString.call(100));//[object Number]
console.log(Object.prototype.toString.call('name'));//[object String]

console.log(Object.prototype.toString.call(undefined));//[object Undefined]

console.log(Object.prototype.toString.call(false));//[object Boolean]

console.log(Object.prototype.toString.call(null));//[object Null]

const foo = function () { }
console.log(Object.prototype.toString.call(foo))//[object Function]
console.log(Object.prototype.toString.call({}))//[object Object]
console.log(Object.prototype.toString.call([]))// [object Array]
const now = new Date();//[object Date]

console.log(Object.prototype.toString.call(now))
console.log(Object.prototype.toString.call(Symbol("foo")))//数据类型判断.html:30 [object Symbol]

Object.prototype.toString的原理

先看看各种数据类型的toString()方法
var num = 123;
console.log(num.toString());//123
var str = 'hello';
console.log(str.toString());//hello
var bool = false;
console.log(bool.toString());//false
var arr = [1,2,3];
console.log(arr.toString());//1,2,3
var obj ={}
console.log(obj.toString());//[object Object]
var fn = function(){};
console.log(fn.toString());//function(){}
console.log(null.toString());
console.log(undefined.toString());//Uncaught TypeError: Cannot read property 'toString' of null

如上面所示,除了对象类型调用toString()方法能正确返回[object Object]格式的类型。除了null undefined调用toString()会报错,其他的返回的都不是[object xxxx]格式,说明其他的类型调用的并不是object.prototype上面的toString()。

以数组为例子
var arr = [];
console.log(arr)

看看他的原型链:arr.prototype

image.png arr.prototype.prototype上也存在toString()方法 image.png

现在写一段代码将数组上原型的toString()方法删除

var arr = [];
console.log(arr)
delete Array.prototype.toString;
console.log(arr)
console.log(arr.toString())//[object Array]

image.png

现在调用arr.toString()就可以得到正确的[object xxx]类型了。

基本类型

基本类型是不存在构造函数和原型的,那他的toString()方法是哪里来的呢?

let num = new Number(1);
console.log(num)

77X58`JO1GPBKW0Y($J7VSY.png

image.png

总结:
  • toString()实际上是对象上的方法。像数组、函数、时间等对象的原型上也有toString()方法。 这个方法重写了Object上面的toString()方法。基本类型没有toString()方法,但是却可以调用,是因为在使用toString()的时候会将基本类型包装成Number、String和Boolean对象。

  • Object.prototype.toString.call()方法的作用为了避免调用重写的toString方法

数据类型转换

分为显示类型转换和隐式类型转化。显示类型比较好理解,这里暂不考虑。

1. 情况一:基础类型做加减运算

根据两两组合基础类型有5种,每两两组合共有10种组合情况

//1.number+string
console.log(1 + '1'); //11
//2.number+boolean
console.log(1 + true);// 2
console.log(1 + false);//1
//3.number+undefined
console.log(1 + undefined); //NaN
//4.number+null
console.log(1 + null);// 1
//5.string + boolean
console.log("1" + true);//1true
//6.string + undefined
console.log("1" + undefined); //1undefined
//7.string + null
console.log("1" + null);//1null
//8.boolean + null
console.log(true + null);//1
//9.boolean + undefined
console.log(true + undefined);// NaN
//10 null+undefined
console.log(null + undefined);// NaN
  • string类型和其他类型相加======其他数据类型都会转为string类型
  • 其他情况都会转化为number类型
  • undefined会转化为NaN 1. 情况二:含有复杂类型做加减运算

计算规则:会将复杂类型转换为基本类型之后在做运算

console.log({}+true)//[object Object]true

复杂类型转化为原始类型的时候会执行Symbol.toPrimitive函数。该函数被调用时,会被传递一个字符串参数 hint ,表示要转换到的原始值的预期类型。 hint 参数的取值是 "number""string" 和 "default" 中的任意一个。然后根据传入的预期类型判断该调用该对象上的valueOf方法还是toString方法

const foo = {
toString(){
return 'foo'
},
valueOf(){
return 1
}
}
alert(foo);
console.log(1+foo);

alert(foo)输出:

image.png

console.log(1+foo)输出

image.png

类型转换总结 根据上面的情况来看复杂类型最终在计算的时候也会根据实际情况转化为原始类型然后再做加减操作。 大致可以分为两种情况:

1. 如果+运算符两边都是number类型

  • 一般情况直接相加

  • 特殊情况一:两边存在NaN,则计算结果为NaN

  • 特殊情况二:Infinity + Infinity ==Infinity

  • 特殊情况三:-Infinity + (-Infinity) == -Infinity

  • 特殊情况四:Infinity + (-Infinity) == NaN 1. 如果+运算符两边存在字符串类型

  • 如果两边都是字符串,则做字符串拼接

  • 如果两边都是有一个为字符串,则另一个值转换为字符串,再做字符串拼接

  • 如果两边存在对象,执行toPrimitive函数,调用valueOf或者toString获取值,然后转为基本类型再进行字符串拼接。

关于函数参数传递问题 参考冴羽大佬文章

总结如下:

  • 函数参数为基本类型的时候,函数体内复制了一份数据,任何操作都不会影响实际值
  • 函数参数是引用类型,函数体内修改参数的某个属性值时,原来的参数的该属性值也会被修改
  • 函数参数是引用类型,函数体内直接该引用的地址,不会修改原参数。