Javascript数据类型知识总结(超详细)

目录

基本数据类型与引用数据类型的区别

1.Number

 2.BigInt

 3.String

4.Boolean

5.Null和Undefined

6.Symbol 

7.Object 

Object内置对象

JS类型判断

JS类型转换


JS的数据类型有8种,分别是Number,String,Null,Undefined,Boolean,Symbol,BigInt,Object,前面7种属于基本数据类型,而Object属于引用数据类型。

基本数据类型与引用数据类型的区别

(1)基本数据类型

        基本数据类型的值存储在栈中 ,当申明了一个变量的时候,变量会去内存空间找对应的值,如果找到了对应的值,就直接把该值的内存地址存到变量里;如果没找到,就创建一个新的空间来存储对应的值,并且把新空间的内存地址存到变量里。js中,变量不存储任何值,而存储的是值的内存地址。基本数据类型一旦创建,就是不可变的,因为它占据的空间是固定的,修改变量的值相当于重新创建一个内存空间,变量指向内存空间的地址。

(2)引用数据类型

        当一个对象被创建时,会在内存空间中开辟一个地址,所以,创建两个一样的对象不会相等,同理创建两个空对象也不会相同。

let obj = {
	name: 'niu',
	age: 12
}
let obj2 = {
	name: 'niu',
	age: 12
}
console.log(obj === obj2);//false

因为变量存储的是对象的地址,每创建一个对象,就会开辟一个新的空间,地址就是内存空间的位置0x22,0x23。当然,对象的属性所对应的值是基本数据类型,所以按照基本数据类型的值的存储方式存储。obj不等于obj2(地址不同)

图1-1

当let obj1 = obj时,相当于obj1直接指向obj对应的地址,所以当name属性改变时,不论obj还是obj1都会发生变化。

let obj = {
	name: 'niu',
}
let obj1 = obj
obj1.name = '牛'
console.log("obj",obj);
console.log("obj1",obj1);

 先让obj2 = obj,再让obj2={ }空对象,再obj2.name = "猪八戒",此时,因为obj2又重新创建了一个对象,所以obj2又开辟出一片新的内存地址,所以无论obj2的属性怎么变都不会影响到obj。再假设一种情况,先让obj2=obj,再让obj2=null,此时会是什么情况(null对象里什么都没有,也就是说null不会存储任何内存空间的地址,也就是obj2与obj断了联系,互不影响了)。

图1-2

let obj = {
	name: 'niu',
}
let obj1 = obj
obj1 = null
console.log('obj', obj); // obj {name: 'niu'}
console.log('obj1', obj1); // obj1 null

let obj = {
	name: '孙悟空',
}
let obj1 = obj
obj1 = {}
obj1.name = "猪八戒"
console.log('obj', obj); //obj {name: '孙悟空'}
console.log('obj1', obj1); //obj1 {name: '猪八戒'}

总结:a.修改对象,其他对象指向该对象,那么所有指向它的变量都将受影响,如图1-1(因为他们使用的是同一片内存空间)。b.修改变量,如图1-2,修改的是obj2,obj2={ },修改后重新开辟空间,所以之前的对象不受影响。

1.Number

  • 在JS中所有的整数和浮点数都是Number类型
  • JS中的数值并不是无限大的,当数值超过一定范围后会显示近似值
  • 在JS中不能进行一些精度比较高的运算(二进制计算,转换后会不太准确)
  • Infinity 是一个特殊的Number类型,表示无穷
  • NaN 也是一个特殊的Number类型,表示非法的数值

Number的常用方法

  • isInteger() 判断一个数是否是整数,返回布尔值
  • isNaN()  判断一个数是否为NaN
  • toFixed(x)  把一个数保留x位小数,且转化为字符串
  • toString()  转化为字符串
  • console.log(Number.isInteger(34.345));//false
    console.log(Number.isInteger(34));//true
    console.log(isNaN(3));//false
    console.log(isNaN(3+'pw'));//true
    let num = 12.567
    console.log(num.toFixed(2));//12.57 字符串类型
    console.log(num.toFixed(1));//12.6 字符串类型
    console.log(num.toString());//12.567 字符串类型

从字符串截取数字

  • parseInt(string, radix)  截取整数 第一个参数表示要截取数字的字符串,第二个表示进制(可选,默认为10进制)
  • parseFloat(string)  截取浮点数

当截取不成功时,会返回NaN,截取整数时,从头开始截取,遇到非数字则停止截取(小数点也要停止截取),截取浮点数时,遇到非数字停止截取。

            console.log(parseInt('235ddfcv')); //235
			console.log(parseInt('235d123')); //235
			console.log(parseInt('23.5d123')); //23
			console.log(parseInt('0.5d123')); //0
			console.log(parseInt('d123')); //NaN
			console.log(parseInt('456d123',16)); //72798499 16进制
			console.log(parseFloat('4.56d123')); //4.56
			console.log(parseFloat('0.56d123')); //0.56

数学运算

  • Math.abs() 求一个数的绝对值
  • Math.min() 求多个值中的最小值
  • Math.max()求多个值中的最大值
  • Math.pow()求x的y次幂
  • Math.sqrt() 求一个数的平方根
  • Math.floor() 向下取整
  • Math.ceil() 向上取整
  • Math.round() 四舍五入取整
  • Math.trunc() 直接去除小数位
  • Math.random() 生成一个0-1之间的随机数
  • Math.round(Math.random(y - x) + x) 生成一个x-y之间的随机整数

 2.BigInt

        BigInt是新加入的一个数据类型,大整数。Number类型只能安全的表示-(2^{53}-1)到2^{53}-1之间的整数,超出范围的整数都将失去精度,而BigInt支持更大范围的整数精度(大于2^{53}-1)。

        创建BigInt有两种方式

(1)直接在数字后面加n

(2)BigInt(‘9007199254740995’)

console.log(typeof 9007199254740995n); //bigint
console.log(BigInt('9007199254740995')); //9007199254740995n 

 3.String

\ 转义

\n 换行

\t 制表符

引号用法:外双内单,外单内双

字符串方法 

1)字符串本质上是一个字符数组

'hello' --> ['h','e','l','l','o'],所以它可以用length获取长度,用[index]获取某个位置的字符

2)根据索引获取

str.at() //根据索引获取字符,可以传负数,负数是从右往左获取
str.charAt() //根据索引获取字符,不能用负数

3)拼接字符串

str.concat() //连接2或多个字符串
str.repeat(number) //传入一个数字,为重复拼接次数

4)查找字符串中有无某字符

str.includes(string,start)
// 第一个参数表示要找的字符,第二个参数表示查找开始位置索引,找到了返回true,
// 找不到返回false
str.indexOf()
// 传入字符,如果找到了返回第一个字符的索引,没找到返回-1
str.lastIndexOf()
// 从后往前找,找到了返回第一个索引,找不到返回-1

5)检查字符串是否以指定内容开头和结尾

str.startsWith()
// 字符串开头是否以指定内容开头,返回布尔值
str.endsWith()
// 字符串是否以指定内容结尾,返回布尔值

6)添加指定内容使字符串保持一定长度

let str = 'hello'
str.padStart(7,'0')
// 字符串前面添加某字符到固定长度
// 第一个参数是字符串的长度,若原先的字符串长度不够,则在前面加上第二个参数
console.log(str.padStart(7,'0'));// 00hello
str.padEnd(8,'1')
// 在字符串的尾部补充到固定长度
console.log(str.padEnd(8,'1'));// hello111

7)字符串的替换

let str = 'hello hello hello'
console.log(str.replace('hello','你好')); //你好 hello hello
// 两个参数,第一个参数是被替换的字符,第二个是要替换的字符,只会替换一个
console.log(str.replaceAll('hello','你好')); //你好 你好 你好
// 和上面一样,但替换的是字符串中所有的字符 

8)截取字符串

str.slice()
// 两个参数,第一个是截取的开始位置索引,第二个是截取的结束位置索引,包含开始不包含结尾
str.substring()
// 和slice一样,但传入参数的时候,它会自动调整两个参数的位置

9)字符串切分为数组

let str = 'hello'
console.log(str.split(''));//['h', 'e', 'l', 'l', 'o']
let str2 = 'aaa$bbb$ccc$ddd'
console.log(str2.split('$'));//['aaa', 'bbb', 'ccc', 'ddd']

10)转换大小写

let str = 'AABBccdd'
str.toUpperCase()//转换为大写
console.log(str.toUpperCase());//AABBCCDD
str.toLowerCase()//转换为小写
console.log(str.toLowerCase());//aabbccdd

11)去除空格

let str = '  abc  '
console.log(str);//'  abc  '
// 去除前后空格
console.log(str.trim());//'abc'
// 去除前面空格
console.log(str.trimStart());//'abc  '
// 去除后面空格
console.log(str.trimEnd());//'  abc'

4.Boolean

布尔值为下面的值时为false,其余情况都为true。

  • 0
  • null
  • ""
  • false
  • undefined
  • NaN

5.Null和Undefined

null

表示空对象,一般用于释放指向对象的引用地址。

undefined 

申明了却没有赋值,变量就为undefined;调用函数时,应该提供的参数没有提供,该参数等于undefined;对象没有赋值的属性,该属性的值为undefined;函数没有返回值时,默认返回undefined。

6.Symbol 

  • symbol表示独一无二的值(两个看起来一样的symbol也不相等)
let a = Symbol('abc')
let b = Symbol('abc')
console.log(a === b); //false
console.log(a == b); //false
  • symbol作为对象属性名时需用[ ]表示,通过symbol创建的属性是不希望被外界访问的属性。
let obj = {
    name: "牛马",
    [Symbol('hhhhh')]: "90"
}
console.log(obj[Symbol('hhhhh')]); //undefined
//这里访问对象用[]代替点,但是访问不到,因为Symbol('hhhhh')每次访问都是一个不一样的值
//所以需要存储Symbol('hhhhh')的值
//正确做法是
let age = Symbol('hhhhh')
let obj = {
    name: "牛马",
    [age]: "90"
}
console.log(obj[age]); //90
  • symbol不能做任何运算
let name = Symbol('name');
console.log(name + 111) //报错,不能进行运算
  • symbol的遍历
let age = Symbol('hhhhh')
let obj = {
   name: "牛马",
   [age]: "90"
}
// 遍历不到symbol
for (let i in obj) {
   console.log(i); //name
}
// 可以遍历所有属性的key,放到数组
console.log(Reflect.ownKeys(obj)); //['name', Symbol(hhhhh)]
// 遍历不到symbol的key
console.log(Object.keys(obj));//['name']
// 只能遍历到symbol
console.log(Object.getOwnPropertySymbols(obj));//[Symbol(hhhhh)]
// 遍历不到symbol的key
console.log(Object.getOwnPropertyNames(obj));//['name']
  • symbol的方法

(1)symbol.for()

(2)symbole.keyFor()

// symbol.for()的值可以相等
let a = Symbol.for('cccc')
let b = Symbol.for('cccc')
console.log(a === b); //true
// Symbol.keyFor()可以拿到symbol.for()括号里的值
let c = Symbol('dddd')
console.log(Symbol.keyFor(a)); //cccc
console.log(Symbol.keyFor(c)); //undefined
  • Symbol的作用

  对象中有Symbol.iterator 这个属性的话,这个对象就可以被 for… of 遍历,否则遍历不了。

7.Object 

创建对象

let obj = new Object()这里new可以省略

let obj = { }

            let str = 'message'
			let obj = {
				name:'牛马',
				["age"]:23,
				[Symbol('6')]:'abcd',
				[str]:'你好',
				method:{
					name:'马'
				}

			}

访问对象可以用obj.propertyName,也可以用obj[propertyName],方括号中可以是字符串,变量,symbol。

检查对象中是否含有某属性

in操作符

“propertyName”  in  obj    如果有该属性则返回true,没有返回false

对象分类 

1)内建对象 :Object,Function,Array,String,Number.......

//它们使用时需要new一下
let str = new String("hello")
let str1 = "hello" 
//用new创建和用字面量创建是一样的
//除了新加入的Symbal和BigInt不支持用new创建,其他都支持,但通常都使用字面量创建

2)宿主对象 :Dom,Bom

3)自定义对象 :程序员自己写的对象

Object内置对象

1)Object.assign( target, ...source )

对象拷贝

可传入多个参数,第一个是目标对象,拷贝后所有属性和方法都会存到target里,后面的参数可以传多个对象,如果有相同的属性则看参数位置,哪个位置越靠后,就用哪个的属性。

let obj = {a:2}
let obz = {b:3}
let ob = Object.assign(obj, obz)
console.log(ob, obj, obz); //{a: 2, b: 3} {a: 2, b: 3} {b: 3}
// ob和obj是相同的
let obj2 = Object.assign({}, obj, obz, {c : '我是牛马'})
console.log(obj2); //{a: 2, b: 3, c: '我是牛马'}
let obj3 = Object.assign({c: '你是牛马',a: 5}, obj, obz, {c: '我是牛马'})
console.log(obj3); //{c: '我是牛马', a: 2, b: 3}

2)Object.create( proto, propertiesObject )

创建对象

第一个参数为原型对象,是必传的参数,第二个参数是属性对象,也就是对象的属性是一个对象(如name:{ }),非必传参数。

// 只传入第一个参数,参数为null,创建的对象没有原型,是纯净对象
let c = Object.create(null)
console.log('c', c);
// 传入空对象
let d = Object.create({})
console.log('d', d); 
// 传入Object.prototype
let e = Object.create(Object.prototype)
console.log('e', e); 
/* 
当然,你会发现控制台打印的d和e是一样的,也就是说这两种创建方式创建出的
对象都是原型里什么都没有的对象,但他们并不相等,因为内存地址不同
*/
//传入对象{name:"张三",age:3}
let f = Object.create({name:"张三",age:3})
console.log('f',f);

从代码和图片可以看出,当只传入一个参数时,创建的对象的参数会添加到原型上去,而创建的对象依旧为空,如果需要给这个空对象创建属性,则要传入第二个参数(属性对象)。

属性对象

形式:{ name: { }, age:{ } }

name,age对象中需要传的参数如下,它们以键值对形式传入

1)value 属性值,默认为undefined

2)configurable  当它的值为true是,属性才可以被删除或者属性名才可以被修改(如删除name属性,或者修改name为names),默认为false

3)enumerable  当它的值为true是,属性才可以被遍历(枚举),默认为false

4)writable  当它的值为true是,属性的值才可以被修改,默认为false,只读

5)get  属性的getter函数,当属性被访问时,函数执行,返回一个值为属性值,默认为undefined

6)set  属性的setter函数,当改变属性值时,函数执行,函数的参数为属性改变后的值,默认为undefined

*注意:value和writable出现时不能出现get和set,这两组不相容,因为get的返回值相当于value的值,set出现代表属性值一定是可以改变的。

let a = Object.create(Object.prototype,{
	age:{
		value:17,
		configurable:true, //可删除,可修改属性名
		writable:true, // 可修改属性值
	},
	name:{
		value:"孙悟空",
		enumerable:true // 可遍历
	}
})
// *尝试这四个方法的时候要注释调其他几个,以免相互受影响
// 1.控制台打印初始a
console.log(a); //{name: '孙悟空', age: 17}
// 2.删除两个属性后打印a,发现name属性不能被删除
delete a.age
delete a.name
console.log(a); //{name: '孙悟空'}
// 3.修改两个属性的值,发现只有age被修改了
a.age = 100
a.name = "猪八戒"
console.log(a); //{name: '孙悟空', age: 100}
// 4.遍历属性,发现只能遍历到name
for(let item in a){
	console.log(item); //name
}

用Object.create()创建的对象会有属性对象的约束,通过属性对选哪个的参数规定约束条件,而普通创建方式创建的对象没有约束。

3)Object.defineProperty( object, prop, descriptor)

监听对象属性(监听单个)

一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。也是vue2的双向数据绑定原理。需要传三个参数,第一个是需要新增或修改属性的对象;第二个是属性名,需用引号;第三个是属性描述。后面两个参数相当于把属性对象拆开了。

例子1:vue2双向绑定原理

<input type="text" id="input">
<h2 id="h2"></h2>
<script>
  let input = document.getElementById('input')
  let h2 = document.getElementById('h2')
  let obj = {
    text: '',
  }
  Object.defineProperty(obj, "text", {
    get: function () { return h2.innerText }, 
    //获取值(这里h2.innerText已经被dom获取了,所以get存在与否都行)
    set: function (newValue) {  //设置值,监听属性变化
      console.log(newValue);
      h2.innerText = newValue
    }
  })
  input.addEventListener('input', function (e) {
    obj.text = e.target.value
  })
</script>

例子2:添加与修改对象属性

let o = {}
// 添加
Object.defineProperty(o, "a", {
  value : 37,
  writable : true,
  enumerable : true,
  configurable : true
});
console.log(o.a); //37
let bValue = 10
Object.defineProperty(o, "b", {
  get(){return bValue},
  set(newValue){
	bValue = newValue
  },
  enumerable : true,
  configurable : true
});
console.log(o.b); //10
// 修改
// 有set可以修改,当属性值发生变化时,操作值,通过get返回给属性,也就是监听属性值,如o.b
// 有writable:true时也可以修改,如o.a
// 通过直接赋值的属性也可以进行修改,如o.c
o.b = 3
o.c = "你好"
o.a = 0
o.c = "nihao"
console.log(o.b,o.c,o.a); //3 nihao 0

4)Object.defineProperties( obj, propertiesObject )

显而易见,它是Object.defineProperty()的复数形式,就是监听多个属性的变化,第一个参数是被监听的对象,第二个参数是属性对象,里面可以有多个属性。用法和前面一样。

5)Object.keys( obj )

遍历对象的属性名

传入一个对象(也可以是字符串或者数组,但是在遍历字符串或数组的时候,索引就相当于属性名,而值就相当于属性值),遍历对象的属性名,返回一个属性名组成的数组,遍历不到Symbol()属性。

let obj = {
  a:1,
  b:2,
  c:3,
  [Symbol()]:4
}
let result = Object.keys(obj)
console.log(result);//['a', 'b', 'c']

6)Object.values( obj )  

遍历对象的属性名

传入一个对象(也可以是字符串或者数组),遍历对象的属性值,返回一个属性值组成的数组,遍历不到Symbol()属性。

let obj = {
  a:1,
  b:2,
  c:3,
  [Symbol()]:4
}
let result = Object.values(obj)
console.log(result);//[1, 2, 3]

7)Object.entries( obj )

遍历对象的键值对

传入一个对象(也可以是字符串或者数组),遍历其键值对,返回一个数组,数组里是键值对形式的数组,遍历不到Symbol()属性。

let obj = {
  a:1,
  b:2,
  c:3,
  [Symbol()]:4
}
let result = Object.entries(obj)
console.log(result); // [['a', 1],['b', 2],['c', 3]]
// 如果想单独拿到key或者value
result.forEach(([key,value])=>{
  console.log(key,value); // a 1, b 2, c 3
})
console.log(Object.entries(['e','f','g'])); //[['0', 'e'],['1', 'f'],['2', 'g']]
console.log(Object.entries('efg')); //[['0', 'e'],['1', 'f'],['2', 'g']]

8)Object.freeze( obj )

冻结对象

传入的对象和返回的是同一个对象,但对其做了冻结:对象就再也不能被修改,也不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,该对象的原型也不能被修改。当然,数组也是对象,所以数组也可以被冻结,从而无法被修改。

let obj = {
  name: "孙悟空",
  age: 900,
  child:{
    name: "孙猴"
  }
}
Object.freeze(obj)
obj.name = "猪八戒"
obj.age = 800
obj.child.name = "牛马"
console.log(obj); //name: '孙悟空', age: 900, child: {name: '牛马'}

我们从代码中发现,当对象里还有对象时,里面的对象属性依然可以被修改,所以Object.freeze()为浅冻结,这点要注意。

9)Object.prototype.hasOwnProperty( )

原型方法,判断对象中是否有某属性,调用形式:obj.hasOwnProperty( "prop" )

第一个参数是对象,在前面,第二个参数是对象的属性,写的时候得用引号。只要属性存在(包括属性值是null,undefined),则返回true,不存在返回false。它和in操作符都是判断对象中是否存在某属性,不同的是in会在原型上找,而它不会。

let obj = {
  name: "nihao",
  xxx: null,
  yyy: undefined
}
console.log(obj.hasOwnProperty('name')); //true
console.log(obj.hasOwnProperty('xxx')); //true
console.log(obj.hasOwnProperty('yyy')); //true
console.log(obj.hasOwnProperty('toString')); //false toString是原型上的方法

10)Object.is(value1, value2)

比较两个值是否为同一个值

传入两个参数,都是要比较的值,如果是同一个,返回true,否则返回false。如果满足以下任意条件则两个值相等:

  • 都是 undefined
  • 都是 null
  • 都是true或都是false
  • 都是相同长度、相同字符、按相同顺序排列的字符串
  • 都是相同对象(意味着都是同一个对象的值引用)
  • 都是数字且
    • 都是 +0
    • 都是 -0
    • 都是 NaN
    • 都是同一个值,非零且都不是 NaN

Object.is(),==,=== 三个都是判断是否相等,==会在类型不同的时候强制转换类型,再进行判断。用等号判断的时候,+0和-0是相等的,而Object.is()不相等;用等号判断NaN是不相等的,而Object.is()相等。

console.log(Object.is(NaN,NaN)); //true
console.log(Object.is(null,null)); //true
console.log(Object.is(undefined,undefined)); //true
console.log(Object.is(+0,-0)); //false
console.log(Object.is(0,-0)); //false
console.log(NaN == NaN); //false
console.log(NaN === NaN); //false
console.log(+0 == -0); //true
console.log(+0 === -0); //true
console.log('' == false); //true

11)Object.getOwnPropertyNames(obj)

获取属性名

传入一个对象,返回自身可枚举和不可枚举的属性名组成的数组,但不包括symbol。

let arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr))
//['0', '1', '2', 'length']

//不可枚举属性
let obj = Object.create({}, {
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false //不可枚举,for...in...遍历不到
  }
});
obj.foo = 1;
console.log(Object.getOwnPropertyNames(obj)); // ["foo", "getFoo"]

12)Object.getOwnPropertySymbols(obj)

获取symbol属性名

传入一个对象,只获取对象的symbol属性名,返回一个由symbol属性名组成的数组。

let obj = {
	[Symbol("a")]:666,
	[Symbol.for("b")]:888,
	c:999
}
console.log(Object.getOwnPropertySymbols(obj));
// [Symbol(a), Symbol(b)]

13)Object.prototype.isPrototypeOf( )

判断一个对象是否存在于另一个对象的原型链上

写法:prototypeObj.isPrototypeOf(object),参数object表示在该对象的原型链上搜寻,返回一个布尔值,prototypeObj如果为 undefined 或 null,会报错。

function Foo1() {}
function Bar2() {}
function Baz3() {}
Bar2.prototype = Object.create(Foo1.prototype);
Baz3.prototype = Object.create(Bar2.prototype);
let baz3 = new Baz3();
console.log(Baz3.prototype.isPrototypeOf(baz3)); // true
console.log(Bar2.prototype.isPrototypeOf(baz3)); // true
console.log(Foo1.prototype.isPrototypeOf(baz3)); // true
console.log(Object.prototype.isPrototypeOf(baz3)); // true 对象的原型链必有Object

14)Object.getPrototypeOf( )

返回指定对象的原型

Object.getPrototypeOf(object),传入一个object,返回其原型。

let proto = {};
let obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true
let reg = /a/;
Object.getPrototypeOf(reg) === RegExp.prototype; // true
let obj2 = new Object();
Object.prototype === Object.getPrototypeOf( obj2 );// true
Object.prototype === Object.getPrototypeOf( {} );// true

JS类型判断

1)typeof

写法有两种,typeof( 表达式 )或者typeof 变量名

typeof的返回值为字符串,用typeof判断null和数组,new的对象,普通对象的时候返回'object',能判断出函数,返回'function'

console.log(typeof "niu");//string
console.log(typeof("niu"));//string
console.log(typeof "");//string
console.log(typeof 345);//number
console.log(typeof Infinity);//number
console.log(typeof true);//boolean
console.log(typeof Symbol('x'));//symbol
console.log(typeof null);//object
console.log(typeof sss);//undefined
console.log(typeof undefined);//undefined
console.log(typeof {});//object
console.log(typeof []);//object
console.log(typeof function(){});//function
console.log(typeof new Map());//object

2)instanceof

写法是:a instanceof b

判断a是否为b的实例,返回一个boolean值,如果a是b的实例则返回true,反之。instanceof只能用来判断对象和函数,不能用来判断字符串和数字等基本数据类型。

往深了理解,instanceof用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上。object instanceof constructor,object是实例对象,constructor是构造函数。

let a = new Array()
console.log(a instanceof Array);//true
console.log(a instanceof Object);//true
// 这里a也是Object的实例的原因是,Array的原型链指向Object。
function Person(){};
let b = new Person()
console.log(b instanceof Person);//true
console.log(b instanceof Array);//false
console.log(b instanceof Object);//true
console.log(({})  instanceof Object);//true
let myDate = new Date();
console.log(myDate instanceof Date);//true
let simpleStr = "This is a simple string"
console.log(simpleStr instanceof String);//false 基本数据类型不能判断,不是实例对象
let myString  = new String()
console.log(myString instanceof String);//true
// 原型
function C(){}
let o = new C()
console.log(o instanceof C);//true
C.prototype = {}//改变构造函数原型
console.log(o instanceof C);//false
o.__proto__ = {}//改变对象原型
console.log(o instanceof C);//false

3)constructor

constructor是什么:当一个函数 F被定义时,JS引擎会为F添加 prototype 原型,然后再在 prototype上添加一个 constructor 属性,并让其指向 F 的引用,当执行 let z = new F() 时,F 被当成了构造函数,z 是F的实例对象,此时 F 原型上的 constructor 传递到了 z 上,因此 z.constructor === F。

 写法就是a.constructor === Type,判断a是否是某类型,constructor对于对象类型的延伸都能准确判断,如Array,Data等。constructor除了不能判断null和undefined,其他都能判断,返回一个布尔值。

console.log((1).constructor === Number); // true
console.log(true.constructor === Boolean); // true
console.log(''.constructor === String); // true
console.log(NaN.constructor === Number); // true 
console.log(function () { }.constructor === Function); // true
console.log({}.constructor === Object); // true
console.log([].constructor === Array); // true
console.log(new Date().constructor === Date); // true
console.log(new Error().constructor === Error); // true
console.log(new RegExp().constructor === RegExp); // true
console.log(Symbol().constructor === Symbol); // true
console.log( new Map().constructor === Map); // true
console.log( new Set().constructor === Set); // true

4)Object.prototype.toString.call( )

目前最完美的类型判断方法

传入一个任意的类型,返回一个"[ object Type ]",对于 Object 对象,直接调用 toString() 就能返回 [object Object] ,call可以省略。

Object.prototype.toString({}) ; // [object Object]
Object.prototype.toString.call({}) ; // [object Object]
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(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object global] window 是全局对象 global 的引用

JS类型转换

因为基本数据类型的值是不变的,类型转换的时候,是重新开辟空间创建新的类型的值,也就是对原先的值不会产生影响。

1.其他类型转字符串

1)toString( )  不能转换null和undefined,因为这两没有toString方法

2)String( ) 没有限制

3)字符串加法(隐式转换)将要加的值先转换为字符串,再进行字符串拼接

let a = 23
a.toString()
console.log(typeof a, a);//number 23
a = a.toString()
console.log(typeof a, a);//string 23
let b = true
b = b.toString()
console.log(typeof b, b);//string true
let c = null
c = String(c)
console.log(typeof c, c);//string null
let d = 1 + '2'
console.log(typeof d,d);//string 12
let e = true + ''
console.log(typeof e,e);//string true

2.其他类型转number

1)Number( )

字符串转number:

        如果字符串是合法数字,直接转为对应的数字

        如果字符串不是合法数字,则转为NaN

        如果字符串是空串或者是纯空格的字符串,转为0

布尔值转number:

        true为1,false为0

null转化为0

undefined转化为NaN

2)parseInt( )与parseFloat( )  它两是切分字符串为number,前面有介绍

3)隐式转换之加减运算

除了字符串加法外,其他运算都是先转化为number类型再进行计算。

console.log(2 + null); //2+0=2
console.log(2 + undefined); //2+NaN=NaN
console.log(2 + true); //2+1=3
console.log(2 + false); //2+0=2
console.log(2 - "1"); //2-1=1
console.log(+"1"); // 1
console.log(-"1"); // -1

3.其他类型转Boolean

除了0,null,undefined,NaN,"",false为false,其余都为true,注意:空字符串是false,但空字符串有空格则返回true。

console.log(Boolean(""));//false
console.log(Boolean(" "));//true
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值