JS类型转换

JS有哪些类型

JS 类型分为值类型和引用类型,值类型包括数字、字符串、布尔、Symbol,undefined引用类型包含对象、数组

值类型

let a = 100
let a = true
let a = '12'
let a = Symbol('12')

// 使用typeof检验类型
let a = 100 // 'number'
let a = true // 'boolean'
let a = '12' // 'string'
let a = Symbol('12') // 'symbol'
let a = undefined // 'undefined'
let a = null //历史遗留问题 object

引用类型

let a = [1,2,3] //object
let a = {b:12} //object

二者唯一区别

值类型用栈模型解释存储,引用类型使用堆栈模型解释

let a = 100
let e = a
e = 200 // 用栈的角度分析: 一个key对应一个value,a的值虽然赋给e,但是二者的key是不相同的,所以二者始终是独立的,e的改变无法导致a的改变

let b = {c:200}
let d = b
d.c = 300 // 用堆栈的角度分析: 首先是堆,一个key(对象名)对应一个内存地址,然后是栈,一个内存地址对应一个属性的值。如果将b对象赋给d,也就是将整个堆复制一份,内存地址是不变的,改变了d对象的c的值,这个内存地址所对应的值也相继改变。牵一发动全身
console.log(a,b.c) //100、300


判断类型

JS类型判断有四种方法

  1. typeof操作符
  2. instanceof
  3. constructor
  4. Object.prototype.toString .call()

typeof

typeof功能:

  • 判断值类型数据
  • 判断函数类型
  • 只能判断是否是引用类型,无法深入判断

需要记住几个特殊的值:

typeof(a) = ‘undefined’ typeof(undefined) = ‘undefined’ typeof(NaN) = ‘number’ typeof(null) = ‘object’

重写typeof

  1. 定义具体的引用类型Map
  2. 考虑null、引用类型、值类型
Function.prototype.mytypeof = function(target){
var ret = typeof(target)
const typeMap = {
"[object Object]":"Object",
"[object Array]":"Array",
"[object Boolean]":"boolean",
"[object String]":"string-Object",
"[object Number]":"number-Object" // typeof(new Number(1)) = object
}
if(target == null){
return 'null'
}
if(ret === 'object'){
// 原型方法 返回类型字符串
const typeString = Object.prototype.toString.call(target)
return typeMap[typeString]
}else{
return ret
}

}

instanceof

[] instanceof Array //true

'123' instanceof String //false

new String('213') instanceof String //true

instanceOf 的原理很简单,例如 a instanceOf b 就是利用 a 的隐式原型__proto__顺着原型链向上查找,如果过程中查到隐式原型的值等于 b 的显示原型 prototype 就返回 true,否则返回 false,如果一直找不到等于 null,也返回 false

手写 instanceof

  1. 考虑左边隐式原型指向null
  2. 左边的隐式原型保证走下去
 function myInstanceof(L,R){
var R = R.prototype
L = L.__proto__
while(true){
if(L === null){
return false
}
if(L === R){
return true
}
L = L.__proto__
}
}

console.log(myInstanceof([],Array))

constructor

function F(){}
var f = new F()
f.constructor == F //true

以上就是 constructor 判断类型的原理, F 作为构造函数,定义时的 constructor 遗传给了实例 f,所以 f·constructor == F

依此可以用作类型判断的方法,特别注意不能直接写{}或者数字去调用方法,否则会报错

''.constructor == String
[].constructor == Array
new Number(12).constructor == Number

new Function().constructor == Function
new Date().constructor == Date

Object.prototype.toString.call()

toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。

Object.prototype.toString.call('') ;   // [object String]
Object.prototype.toString.call(1) ; // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(newFunction()) ; // [object Function]
Object.prototype.toString.call(newDate()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(newRegExp()) ; // [object RegExp]
Object.prototype.toString.call(newError()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object global] window 是全局对象 global 的引用

显式类型转换

显示类型转换需要调用方法,分为以下几种

  • Number(mix): 转为数字,非数字(比如一个字符串abc)输出 NaN。

Number() 有几个特殊的值需要记住:

  • Number(null) = 0

  • Number(NaN) = NaN

  • Number(“”) = 0

  • Number(false) = 0

  • Number(undefined) = NaN

  • parseInt(string,raidx) : 转为整形数字 ,非数字输出NAN,第二个参数是基于某个进制转为十进制,比如parseInt(‘10’,16) ,把16进制为基底转为十进制数,输出16,

即使字符串中有abc还是可以转换,以最后的数字类截断字符串, parseInt(‘100px’)=> 100 ,parseInt(‘1000abc’)=>1000

  • parseFloat(string) 转为浮点

  • toString() 转为字符串,**undefinednull不能使用这个方法,因为没有原型,如果添加参数则代表转为目标进制**

111.toString(16) 以10进制转为16进制,所以如果将一个二进制数转为目标进制,则可以先使用parseInt转为十进制,然后使用toString()转为目标进制

  • String(string) 转为字符串,任何类型都会转为字符串

  • Boolean js种六种值转为false (undefined ,null ,'' ,NAN ,0,false),其他的都是true

隐式类型转换

重点: 凡是碰到运算符的首先就转换为 Number类型,不管他是不是数字,不是数字也转为Number就是NaN。

特别注意: + 两侧如果有字符串就都转为String

转换规则

  • isNaN :判断不是数字,其实就是转为Number(s),然后判断是否是数字
  • +,-,++,--%,*,/&& || !> <== !=运算符
var a = '233'
a++ a-- // ++ 首先会调用Number(a)转为数字,然后在++,即使转不成数字也会转为number类型

+ a 、- a// 都会转换为数字类型,typeof为number

a = "a" + 2
// 当加号两侧有一个东西是字符串,就会调用string将两个都变成字符串

-,%,*,/ a = '1'* 1 1 * 'a'(Number(1) * Number('a')) = NaN // a =1
// 也是先转换为number类型

&& || !

> < // “3”>"2" 比阿斯克码序号, "3" > 2,转为number比大小

== !=
// 特殊情况 undefined == null

例题

  1. 手写改造typeof
查看答案
Function.prototype.mytypeof = function(target){
var ret = typeof(target)
const typeMap = {
"[object Object]":"Object",
"[object Array]":"Array",
"[object Boolean]":"boolean",
"[object String]":"string-Object",
"[object Number]":"number-Object" // typeof(new Number(1)) = object
}
if(target == null){
return 'null'
}
if(ret === 'object'){
// 原型方法 返回类型字符串
const typeString = Object.prototype.toString.call(target)
return typeMap[typeString]
}else{
return ret
}

}

  1. 手写instanceof
查看答案
 function myInstanceof(L,R){
var R = R.prototype
L = L.__proto__
while(true){
if(L === null){
return false
}
if(L === R){
return true
}
L = L.__proto__
}
}

console.log(myInstanceof([],Array))

  1. JS判断类型有哪几种方式
查看答案

typeof、instanceof、constructor、Object.prototype.toString.call()


  1. 看题,书写答案
var num = 1 + '1' 
var num = 1 - '1'
var num = 1 * '1'
var str = false + 1
var demo = false == 1
console.log(typeof(a) && (-true+(+undefined) + ""))
console.log(11 + "11" * 2 == 33)
console.log(!!" " + !!"" + -!!false || console.log(1))
查看答案
var num = 1 + '1' //string 11
var num = 1 - '1' // 0
var num = 1 * '1' // 1

var str = false + 1 // 0+1 =1
var demo = false == 1// false
console.log(typeof(a) && (-true+(+undefined) + "")) //"undefined" && (-1+NaN+"") ==> "undefined" && "NaN" ==> "NaN"
console.log(11 + "11" * 2 == 33) // true
console.log(!!" " + !!"" + -!!false || console.log(1)) //true+false-false||1 ===> 1不会打印1

console.log(parseInt(3,8)) 
console.log(parseInt(3,2))
console.log(parseInt(3,0))
查看答案
以3为8进制转为10进制 3
以3为二进制转为10进制 NaN
不存在0进制 NaN

进制分析:

首先理解什么是进制,以我们平常数数来讲,1,2,3,,4,5到10个苹果。这里的面的数就是10进制数,1-9代表个位上的数,10是10位数,进了1。
- 比如如果是一个11进制,10也算上个位数,此时a代表10,a+1满了11进一位,所以a+1 = 10(满11进一位,个位就是0)
- 再比如16进制 9,a,b,c,d,e,f f这个数10进制代表15,再加一,f+1 = 10, 这里的10是16进制表示的16,10转为十进制(十分位1=16 16+0=16)等于16
- 再比如二进制,满二进一,二进制的11代表什么,用十进制表示就是2+1=3,1000代表什么,2的三次方