JS里的类型转化

一、数据类型

  js中拥有动态类型,就是相同的变量可以用作不同的类型:类型是值的内部特征,它定义了值的行为,以使其区别于其他值。

1.1 基本数据类型

       基本数据类型:Number.Boolean.String.Null.undefned.Symbol (ES6新增)

       基本数据类型数据直接存储在栈中,由系统自动分配。按值进行访问,内部的值不可以改变。

var str = "123hello321";
str.toUpperCase();     // 123HELLO321
console.log(str);      // 123hello321

1.2 引用数据类型        

    引用数据类型:Object (Object/Array/Function/Date/RegExp...)

    引用数据类型在栈中存储的是指针和字面量,指针指向地址值对应的是真正的数据,由系统动态分配,用完不会立即释放,需要手动赋值null,释放内存地址。

var a = { name: '余光' };
var b;
b = a;                            //b也拥有了a的name属性
a.name = "yuguang";               //向a中更改name属性,b中也能看见
b.age = 23;                       //向b中添加age属性,a中也能看见,因为他们指向同一地址值
var c = {                         //c里面的属性和a.b不共享,因为它们的地址值不一样
  name: '余光',
  age: 23
};

区别:

变量数据类型:基本类型:保存的是基本类型的数据

                         引用类型:保存的是地址值

1.3 JS中的变量是没有类型的

var a = 100; // 严格地说 变量a没有类型,它所保存的 100是数字类型的
typeof a === 'number'; // 其实检测是=>typeof 100

a = 'string'
typeof a === 'string'; // true

//变量a既是number类型又是string类型,咋回事?
//因为变量a是没有数据类型的,是他里面能存储的值是number,string类型

二、判断数据类型的方法

1、typeof

     不能区分null.Array和Object,均返回object

     因为typeof是按照”值“存储在计算机中的二进制来检测的,000开头的都是object,null是0000

console.log(typeof [12, 23]); //->"Object"

typeof undefined // 'undefined' 
typeof '10' // 'String' 
typeof 10 // 'Number' 
typeof false // 'Boolean' 
typeof Symbol() // 'Symbol' 
typeof Function // ‘function' 
typeof null // ‘Object’ 
typeof [] // 'Object' 
typeof {} // 'Object'
typeof null        // "object" (因为一些以前的原因而不是'null')
typeof undefined   // "undefined"

null === undefined // false
null  == undefined // true

null === null // true
null == null // true
!null //true

isNaN(1 + null) // false
isNaN(1 + undefined) // true

2、instanceof

     判断对象是否在另一个对象的原型链上(实例对象的隐式原型等于构造函数的显式原型)

     坏处:当在原型上定义了一个其他变量,实例化对象也会继承新定义的变量,此时用instanceof判断就会造成影响,如:

function Fn() {
}
Fn.prototype = new Array;//->Fn子类继承了Array这个父类中的属性和方法
var f = new Fn;

console.log(f instanceof Array);//->true
console.log(f.constructor == Array);//->true

    不能检测字面量创建出来的基本数据类型,即原始数据类型

3、constructor

   a. 每一个实例对象都可以查看他的构造函数,可以判断array和function类型,不会像typeof一样均返回object

console.log([] instanceof Array);//->true
console.log([] instanceof Object);//->true

console.log([].constructor === Array);//->true
console.log([].constructor === Object);//->false
constructor可以避免instanceof检测数组的时候,用Object也是true的问题

console.log({}.constructor === Object);//true
console.log([].constructor === Object);//false
console.log(/^$/ instanceof RegExp);//->true

  b. 可以判断原始数据类型和引用数据类型

<script>
  let num = 12;
  let obj = {};
  console.log(num.constructor == Number);//true
  console.log(obj.constructor == Object);//true
</script>

  c. 原型链被修改后,检测结果可能会受影响,同instanceof

  d. 最好在检测时,检测数据用括号括起来

<script>
  1.constructor === Number;    //报错,Invalid or unexceped token
  (1).constructor === Number;    //true
  {}.constructor === Number;    //报错,Invalid or unexceped token
  ({}).constructor === Number;  //true
</script>

乱入:

     对于引用数据类型来说,通过两种方式创建的对象没有区别,都是所属类的实例,原型上的方法可以继承,都是对象数据类型的值。

var ary = [];
var ary = new Array;

    对于基本数据类型来说,两种方式创建的也都是所属类的实例,但他们的类型不同。通过字面量创建的类型是基本数据类型,通过new出来的类型是对象数据类型。

var num1 = 1;
var num2 = new Number("1");
console.log(typeof num1,typeof num2);//->"number" "object" 

4、Object.prototype.toString.call(value)

    value传入的待检测的数据,借用call方法改变toString()里this的指向,Object.prototype.toString用来判断数据类型,返回的是一个JSON字符串 "[ object 数据类型]",除了Object显式原型上的toString方法可以用来判断数据类型,其他的toString方法都是将数据转化为字符串类型的。Null和undefined的toString()方法不让使用

    在JavaScript中,所有类都继承于Object,因此toString()方法应该也被继承了,但所有类在继承Object的时候,改写了toString()方法。 Object原型上的方法是可以输出数据类型的。因此我们想判断数据类型时,也只能使用原始方法。继而有了此方法:Object.prototype.toString.call(obj)

var num = 123
num.toString() // '123'

var str = 'hello'
str.toString() // 'hello'

var bool = false
bool.toString() // 'false'

var arr = [1, 2, 3]
arr.toString()  // '1,2,3'

var obj = {lang:'zh'}
obj.toString()  // '[object Object]'

var fn = function(){}
fn.toString()  // 'function(){}'

null.toString()  // Cannot read property 'toString' of null

undefined.toString() // Cannot read property 'toString' of undefined

三、数据类型转化

3.1 强制类型转化

    number()  string()  boolean() 

    将数据强制转化为数值,字符串和布尔类型

    特殊情况:

  undefined        null          ' '         0
Boolean()      false       false       false       false
String()
Number()       NAN          0         0

         0

undefined和null用string()进行强制类型转化时,不会报错;但是用toString()方法会报错

3.2 隐式类型转化

      隐式转化主要涉及到三种类型:

         a. toPrimitive()

         b. toNumber()

         c. toString()

 a. toPrimitive()

     ToPrimitive(input, PreferredType?)

     input是输入的值,PreferredType?可选值,可以为number或string,默认是number类型(Date除外,默认是string)。

     过程:先判断input数据类型,如果是原始(基础)数据类型,则直接返回,如果不是,判断PreferredType的值,

     若是Number,先调用valueof(),查看返回值,如果返回值依然不是原始数据类型,则调用toString(),若是则返回,若不是,则抛出err。

     若是String,则先调用toString(),检查返回值类型,若是原始数据类型则返回,若不是,则调用valueof(),在判断返回值类型,若不是则抛出err。

     valueof()在处理boolean/string/number这三类构造函数创造的基本数据类型时,会返回其原始值,其他类型都会返回对象本身。

var num = new Number('123');
num.valueOf(); // 123

var str = new String('12df');
str.valueOf(); // '12df'

var bool = new Boolean('fd');
bool.valueOf(); // true
var a = new Array();
a.valueOf() === a; // true

var b = new Object({});
b.valueOf() === b; // true

      toString()会把除了下列的数据类型都返回该数据类型,JSON字符串

var num = new Number('123sd');
num.toString(); // 'NaN'

var str = new String('12df');
str.toString(); // '12df'

var bool = new Boolean('fd');
bool.toString(); // 'true'

var arr = new Array(1,2);
arr.toString(); // '1,2'

var d = new Date();
d.toString(); // "Wed Oct 11 2017 08:00:00 GMT+0800 (中国标准时间)"

var func = function () {}
func.toString(); // "function () {}"

 乱入Date对象

        Date对象的valueof方法会返回自1970年1月1日来的毫秒数,toString()会返回字符串形式表达的事件

  

b. toNumber()

参数结果
undefinedNAN
null0
booleantrue为1,false为0
string有字符串解析为数字,例如:‘324’转换为324,‘qwer’转换为NaN
number不改变
object先进行 ToPrimitive(obj, Number)转换得到原始值,在进行ToNumber转换为数字

c. toString()

参数结果
undefined

                                                        ‘undefined'

null'null'
booleantrue为'true',false为'false'
string不改变
number数字改为字符串,如1改为’1‘
object先进行 ToPrimitive(obj, String)转换得到原始值,在进行ToString转换为字符串

1、转换成string:+(字符串拼接)

2、转化成Number:+,-,*,/,%,<,>等关系运算符

3、转化成Boolean:!

小栗子

js面试题大坑——隐式类型转换

({} + {}) = ?

1、进行ToPrimitive转换,由于没有指定PreferredType类型,{}会使默认值为Number,进行 
   ToPrimitive(input, Number)运算。
2、所以会执行valueOf方法,({}).valueOf(),返回的还是{}对象,不是原始值。
3、继续执行toString方法,({}).toString(),返回"[object Object]",是原始值。
   故得到最终的结果,"[object Object]" + "[object Object]" = "[object Object][object Object]"
   再来一个指定类型的例子

2 * {} = ?

1、首先*运算符只能对number类型进行运算,故第一步就是对{}进行ToNumber类型转换。
2、由于{}是对象类型,故先进行原始类型转换,ToPrimitive(input, Number)运算。
3、所以会执行valueOf方法,({}).valueOf(),返回的还是{}对象,不是原始值。
4、继续执行toString方法,({}).toString(),返回"[object Object]",是原始值。
5、转换为原始值后再进行ToNumber运算,"[object Object]"就转换为NaN。
故最终的结果为 2 * NaN = NaN

1、===

      1.先判断===两边的类型是否相同,若不同返回false

      2.若相同,再判断值是否相同

2、==

      用==判断两数据是否相等时,会自动作类型转化

    

主要分为两类,x、y类型相同时,和类型不相同时。

类型相同时,没有类型转换,主要注意NaN不与任何值相等,包括它自己,即NaN !== NaN。

类型不相同时,

1、x,y 为null、undefined两者中一个,返回true

2、x、y为Number和String类型时,则转换为Number类型比较。

3、有Boolean类型时,Boolean转化为Number类型比较。

4、一个Object类型,一个String或Number类型,将Object类型进行原始转换后,按上面流程进行原始值比较

小栗子

[] == !{}

1、! 运算符优先级高于==,故先进行!运算。
2、!{}运算结果为false,实际上[],{}转化成布尔类型都为true
3、涉及到布尔类型的比较,将他先转化成number,!{}转成0
4、[]会返回空串''
   故结果为 '' == 0比较。
5、根据上面第5条,等式左边x = ToNumber('') = 0。
所以结果变为: 0 == 0,返回true,比较结束。

空数组的toString 会返回空串'',而空对象的toString会返回'[object Object]'
空数组和空对象转化成Boolean都是true
0,null,undefined,'',NAN,转成Boolean都是false,其余的都是true

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值