一.JS 中一共有八种数据类型
- 基本数据类型(值类型):String 字符串、Number 数值、BigInt 大型数值、Boolean 布尔值、Null 空值、Undefined 未定义、Symbol。
- 引用数据类型(引用类型):Object 对象。
注意:内置对象 Function、Array、Date、RegExp、Error 等都是属于 Object 类型。也就是说,除了那七种基本数据类型之外,其他的,都称之为 Object 类型。
BigInt 和 Symbol 是ES6中新增的类型。
二.栈内存和堆内存
JS 中,所有的变量都是保存在栈内存中的。
基本数据类型:
基本数据类型的值,直接保存在栈内存中。值与值之间是独立存在,修改一个变量不会影响其他的变量。
引用数据类型:
对象是保存到堆内存中的。每创建一个新的对象,就会在堆内存中开辟出一个新的空间;而变量保存了对象的内存地址(对象的引用),保存在栈内存当中。如果两个变量保存了同一个对象的引用,当一个通过一个变量修改属性时,另一个也会受到影响。
三.基本数据类型:Null 和 Undefined
Null:空对象
null 专门用来定义一个空对象。例如:let a = null
,又例如 Object.create(null)
.
如果你想定义一个变量用来保存引用类型,但是还没想好放什么内容,这个时候,可以在初始化时将其设置为 null。你可以把 null 理解为:null 虽然是一个单独的数据类型,但null 相当于是一个 object,只不过地址为空(空指针)而已。
举例:
let myObj = null;
cosole.log(typeof myObj); // 打印结果:object
- Null 类型的值只有一个,就是 null。比如
let a = null
。 - 使用 typeof 检查一个 null 值时,会返回 object。
undefined:未定义类型
case1:变量已声明,未赋值时
声明了一个变量,但没有赋值,此时它的值就是 undefined
。
举例:
let name;
console.log(name); // 打印结果:undefined
console.log(typeof name); // 打印结果:undefined
- Undefined 类型的值只有一个,就是 undefind。比如
let a = undefined
。 - 使用 typeof 检查一个 undefined 值时,会返回 undefined。
case2:变量未声明(未定义)时
如果你从未声明一个变量,就去使用它,则会报错;此时,如果用 typeof
检查这个变量时,会返回 undefined
。
举例:
console.log(typeof a); // undefined
console.log(a); // 打印结果:Uncaught ReferenceError: a is not defined
case3:函数无返回值时
如果一个函数没有返回值,那么,这个函数的返回值就是 undefined。
在定义一个函数时,如果末尾没有 return 语句,那么,其实就是 return undefined
。
举例:
function foo() {}
console.log(foo()); // 打印结果:undefined
case4:调用函数时,未传参
调用函数时,如果没有传参,那么,这个参数的值就是 undefined。
举例:
function foo(name) {
console.log(name);
}
foo(); // 调用函数时,未传参。执行函数后的打印结果:undefined
实际开发中,如果调用函数时没有传参,我们可以根据需要给形参设置一个默认值:
function foo(name) {
name = name || 'xiaofeixiaPan';
}
foo();
ES6 的方式:
function foo(name = 'xioafeixiaPan') {}
foo();
Null 和 Undefined的区别
null == undefined
的结果为 true
,但是 null === undefined
的结果是 false。
- 10 + null 结果为 10。
- 10 + undefined 结果为 NaN。
规律总结:
- 任何值和 null 运算,null 可看做 0 运算。
- 任何数据类型和 undefined 运算都是 NaN。
四.基本数据类型:Number
数值范围
由于内存的限制,ECMAScript 并不能保存世界上所有的数值。
- 最大值:
Number.MAX_VALUE
,这个值为: 1.7976931348623157e+308 - 最小值:
Number.MIN_VALUE
,这个值为: 5e-324
如果使用 Number 表示的变量超过了最大值,则会返回 Infinity。
- 无穷大(正无穷):Infinity
- 无穷小(负无穷):-Infinity
注意:typeof Infinity
的返回结果是 number。
如果分子是非0值,分母是有符号0或无符号0,则会返回Infinity
或-Infinity
console.log(5/0);//Infinity
console.log(5/-0);//-Infinity
NaN
NaN:是一个特殊的数字,表示 Not a Number,非数值。比如:
console.log('abc' / 18); //结果是NaN
console.log('abc' * 'abcd'); //NaN
console.log(0/0);//NaN
console.log(0/-0);//NaN
注意:
typeof NaN
的返回结果是 number。- Undefined 和任何数值计算的结果为 NaN。NaN 与任何值都不相等,包括 NaN 本身。
console.log(NaN==NaN);//false
- 任何涉及NaN的操作始终返回NaN(如NaN/10)
isNaN()函数:
ECMAScript 提供了isNaN()函数。该函数接收一个参数,可以是任意数据类型,然后判断
这个参数是否“不是数值”。把一个值传给isNaN()后,该函数会尝试把它转换为数值。某些非数值的
值可以直接转换成数值,如字符串"10"或布尔值。任何不能转换为数值的值都会导致这个函数返回
true。
举例:
console.log(isNaN(NaN)); // true
console.log(isNaN(10)); // false,10 是数值
console.log(isNaN("10")); // false,可以转换为数值10
console.log(isNaN("blue")); // true,不可以转换为数值
console.log(isNaN(true)); // false,可以转换为数值1
类型转换
Number()、parseInt()、parseFloat()
Number
使用Number函数基本上可以转换所有类型
console.log(Number('xiaofeixiaPan')); //NaN
console.log(Number(true)); //1
console.log(Number(false)); //0
console.log(Number('9')); //9
console.log(Number([])); //0
console.log(Number([5])); //5
console.log(Number([5, 2])); //NaN
console.log(Number({})); //NaN
Number()函数基于如下规则执行转换。
布尔值,true 转换为1,false 转换为0。
数值,直接返回。
null,返回0。
undefined,返回NaN。
字符串,应用以下规则。
如果字符串包含数值字符,包括数值字符前面带加、减号的情况,则转换为一个十进制数值。因此,Number(“1”)返回1,Number(“123”)返回123,Number(“011”)返回11(忽略前面
的零)。
如果字符串包含有效的浮点值格式如"1.1",则会转换为相应的浮点值(同样,忽略前面的零)。
如果字符串包含有效的十六进制格式如"0xf",则会转换为与该十六进制值对应的十进制整
数值。
如果是空字符串(不包含字符),则返回0。
如果字符串包含除上述情况之外的其他字符,则返回NaN。
对象,调用valueOf()方法,并按照上述规则转换返回的值。如果转换结果是NaN,则调用
toString()方法,再按照转换字符串的规则转换。
parseInt
空字符串也会返回NaN(这一点跟Number()不一样,它返回0)
parseInt()函数也能识别不同的整数格式(十进制、八进制、十六进制)。
console.log(parseInt(' 99xioafeixiaPan')); //99
console.log(parseInt('18.55')); //18
let num1 = parseInt("1234blue"); // 1234
let num2 = parseInt(""); // NaN
let num3 = parseInt("0xA"); // 10,解释为十六进制整数
let num4 = parseInt(22.5); // 22
let num5 = parseInt("70"); // 70,解释为十进制值
let num6 = parseInt("0xf"); // 15,解释为十六进制整数
//parseInt()也接收第二个参数
let num = parseInt("0xAF", 16); // 175
parseFloat
parseFloat()只解析十进制值,十六进制数值始终会返回0。
第一次出现的小数点是有效的,但第二次出现的小数点就无效了,此时字符串的剩余字符都会被忽略。
let num1 = parseFloat("1234blue"); // 1234,按整数解析
let num2 = parseFloat("0xA"); // 0
let num3 = parseFloat("22.5"); // 22.5
let num4 = parseFloat("22.34.5"); // 22.34
let num5 = parseFloat("0908.5"); // 908.5
let num6 = parseFloat("3.125e7"); // 31250000
舍入操作
使用 toFixed
可对数值舍入操作,参数指定保存的小数位
console.log(1.556.toFixed(2)); //1.56
方式(隐式的类型转换):
使用一元的+来进行隐式的类型转换
例子:
var a = "123";
a = +a;
原理:和Number()函数一样
五.基本数据类型:Boolean
隐式转换
基本上所有类型都可以隐式转换为 Boolean类型。
数据类型 | true | false |
String | 非空字符串 | 空字符串 |
Number | 非0的数值 | 0 、NaN |
Array | 数组不参与比较时 | 参与比较的空数组 |
Object | 所有对象 | null |
undefined | 无 | undefined |
null | 无 | null |
NaN | 无 | NaN |
在JavaScript中,布尔值为 false
的值有如下几个:
undefined
null
false
0
NaN
-
""
或''
(空字符串)
当与boolean类型比较时,会将两边类型统一为数字1或0。
如果使用Boolean与数值比较时,会进行隐式类型转换 true转为1,false 转为0。
console.log(3 == true); //false
console.log(0 == false); //true
字符串在与Boolean比较时,两边都为转换为数值类型后再进行比较。
console.log("1" == true); //true
console.log("houdunren" == true); //false
//Number("houdunren")为NaN
显式转换
(1)使用 !!
转换布尔类型
!!
的作用是将值的类型强制转化为布尔类型。
console.log(undefined==false);//false
console.log(null==false);//false
console.log(0==false);//true
console.log(NaN==false);//false
console.log(''==false);//true
console.log("-------------------------");
console.log(!!undefined==false);//true
console.log(!!null==false);//true
console.log(!!0==false);//true
console.log(!!NaN==false);//true
console.log(!!''==false);//true
返回值强制转换
const test=value=> value && true;
console.log(test(0)); // 0
const test=value=> !!value && true;
console.log(test(0)); // false
可以看到,!!
把 value
强制转化为布尔值。
(2)使用 Boolean
函数可以显式转换为布尔类型
let hd = '';
console.log(Boolean(hd)); //false
hd = 0;
console.log(Boolean(hd)); //false
hd = null;
console.log(Boolean(hd)); //false
hd = new Date("2020-2-22 10:33");
console.log(Boolean(hd)); //true
六.0, “”, null, false, undefined的区别
console.log(false==undefined); //false
console.log(false==null); //false
console.log(undefined==0); //false
console.log(null==0); //false
console.log(""==0); //true
console.log(false==0); //true
console.log(false==""); //true
console.log(null==undefined); //true
观察可发现:0、"“和false是相等的,null和undefined是相等的,而undefined和null并不等于false对象。
可以把0、”"和false归为一类,称之为“假值”,把null和undefined归为一类,称之为“空值”。假值还是一个有效的对象,所以可以对其使用toString等类型相关方法,空值则不行。
console.log(false.toString()); // false
console.log("".length); // 0
console.log((0).toString()); // 0
console.log(undefined.toString());
// throw exception "undefined has no properties"
console.log(null.toString()); // "null has no properties"
七.基本数据类型:String
转换为String
方式一(强制类型转换):
调用被转换数据的toString()方法
例子:
var a = 123;
a = a.toString();
注意:这个方法不适用于null和undefined
由于这两个类型的数据中没有方法,所以调用toString()时会报错
方式二(强制类型转换):
调用String()函数
例子:
var a = 123;
a = String(a);
原理:对于Number Boolean String都会调用他们的toString()方法来将其转换为字符串,对于null值,直接转换为字符串"null"。对于undefined直接转换为字符串"undefined"
方式三(隐式的类型转换):
为任意的数据类型 +“”
例子:
var a = true;
a = a + "";
原理:和String()函数一样
语法:
字符串型可以是引号中的任意文本,其语法为:双引号 ""
或者单引号 ''
。
字符串的不可变性:
字符串里面的值不可被改变。虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。
代码举例:
var str = 'hello';
str = 'xiaofeixiaPan';
比如上面的代码,当重新给变量 str 赋值时,常量hello
不会被修改,依然保存在内存中;str 会改为指向xiaofeixiaPan
。
字符串的常用方法
字符串的所有方法,都不会改变原字符串(字符串的不可变性),操作完成后会返回一个新的值。
我们也可将字符串常用的操作方法归纳为增、删、改、查,需要知道字符串的特点是一旦创建了,就不可变。
增:
concat
let stringValue = "hello ";
let result = stringValue.concat("world");
console.log(result); // "hello world"
console.log(stringValue); // "hello"
删:
常见的有:
- slice()
- substr()
- substring()
都是字符串截取。
(1)slice( )
语法:
新字符串 = str.slice(开始索引, 结束索引); //两个参数都是索引值。包左不包右。
解释:从字符串中截取指定的内容。不会修改原字符串,而是将截取到的内容返回。
注意:上面的参数,包左不包右。参数举例如下:
(2, 5)
截取时,包左不包右。(2)
表示从指定的索引位置开始,截取到最后。(-3)
表示从倒数第三个开始,截取到最后。(1, -1)
表示从第一个截取到倒数第一个。(5, 2)
表示前面的大,后面的小,返回值为空。
(2).substring( )
语法:
新字符串 = str.substring(开始索引, 结束索引); //两个参数都是索引值。包左不包右。
解释:从字符串中截取指定的内容。和slice()
类似。
substring()
和slice()
是类似的。但不同之处在于:
substring()
不能接受负值作为参数。如果传递了一个负值,则默认使用 0。substring()
还会自动调整参数的位置,如果第二个参数小于第一个,则自动交换。比如说,substring(1, 0)
相当于截取的是第一个字符。
(3).substr( )
语法:
字符串 = str.substr(开始索引, 截取的长度);
解释:从字符串中截取指定的内容。不会修改原字符串,而是将截取到的内容返回。
注意,这个方法的第二个参数截取的长度,不是结束索引。
参数举例:
(2,4)
从索引值为 2 的字符开始,截取 4 个字符。(1)
从指定位置开始,截取到最后。(-3)
从倒数第几个开始,截取到最后。
备注:ECMAscript 没有对 substr()
方法进行标准化,因此不建议使用它。
改:
常见的有:
- trim()、trimLeft()、trimRight()
- repeat()
- padStart()、padEnd()
- toLowerCase()、 toUpperCase()
- replace()
(1)trim()
:去除字符串前后的空白。
举例:
//去除字符串前后的空格,trim();
let str = ' a b c ';
console.log(str);// a b c
console.log(str.length);//15
console.log(str.trim());//a b c
console.log(str.trim().length);//9
使用trimLeft
删除左边空白,使用trimRight
删除右边空白
let name = " xiaofeixiaPan ";
console.log(name);
console.log(name.trimLeft());
console.log(name.trimRight());
(2)大小写转换:toLowerCase()、toUpperCase()
举例:
var str = 'abcdEFG';
//转换成小写
console.log(str.toLowerCase());//abcdefg
//转换成大写
console.log(str.toUpperCase());//ABCDEFG
(3) repeat():重复字符串
语法:
newStr = str.repeat(重复的次数);
解释:将字符串重复指定的次数。会返回新的值,不会修改原字符串。
const name = 'xiaofeixiaPan';
console.log(name.repeat(2));//xiaofeixiaPanxiaofeixiaPan
举例2:(模糊字符串的后四位)
const telephone = '13088889999';
const mix_telephone = telephone.slice(0, -4) + '*'.repeat(4); // 模糊电话号码的后四位
console.log(telephone); // 打印结果:13088889999
console.log(mix_telephone); // 打印结果:1308888****
(4)padEnd()
复制字符串,如果小于指定长度,则在相应一边填充字符,直至满足长度条件
let stringValue = "foo";
console.log(stringValue.padStart(6)); // " foo"
console.log(stringValue.padStart(9, ".")); // "......foo"
(5) replace()
语法:
新的字符串 = str.replace(被替换的字符,新的字符);
解释:将字符串中的指定内容,替换为新的内容并返回。不会修改原字符串。
注意:这个方法,默认只会替换第一个被匹配到的字符。如果要全局替换,需要使用正则。
举例:
//replace()方法:替换
var str2 = 'Today is fine day,today is fine day !';
console.log(str2);
console.log(str2.replace('today', 'tomorrow')); //只能替换第一个today
console.log(str2.replace(/today/gi, 'tomorrow')); //这里用到了正则,才能替换所有的today
查:
- chatAt()、charCodeAt()
- indexOf()
- startsWith()、endsWith()
- includes()
- search()
(1)indexOf( )/lastIndexOf( ) :获取字符串中指定内容的索引
语法 1:
索引值 = str.indexOf(想要查询的字符串);
备注:indexOf()
是从前向后查找字符串的位置。同理,lastIndexOf()
是从后向前寻找。
解释:可以检索一个字符串中是否含有指定内容。如果字符串中含有该内容,则会返回其第一次出现的索引;如果没有找到指定的内容,则返回 -1。
因此可以得出一个重要技巧:
- 如果获取的索引值为 0,说明字符串是以查询的参数为开头的。
- 如果获取的索引值为-1,说明这个字符串中没有指定的内容。
举例 1:(查找单个字符)
const str = 'abcdea';
//给字符查索引(索引值为0,说明字符串以查询的参数为开头)
console.log(str.indexOf('c'));//2
console.log(str.lastIndexOf('c'));//2
console.log(str.indexOf('a'));//0
console.log(str.lastIndexOf('a'))//5
举例 2:(查找字符串):
const name='xiaofeixiaPan';
console.log(name.indexOf('fei'));//4
语法 2:
这个方法还可以指定第二个参数,用来指定查找的起始位置。语法如下:
索引值 = str.indexOf(想要查询的字符串, [起始位置]);
举例 3:(两个参数时,需要特别注意)
const name='xiaofeixiaPan';
let result=name.indexOf('i',2);// 从第二个位置开始查找 'i'这个字符
console.log(result);//6
案例:查找字符串"xiaofeixiaPan"中,所有 a
出现的位置以及次数。
思路:
(1)先查找第一个 a 出现的位置。
(2)只要 indexOf 返回的结果不是 -1 就继续往后查找。
(3)因为 indexOf 只能查找到第一个,所以后面的查找,可以利用第二个参数,在当前索引加 1,从而继续查找。
const name='xiaofeixiaPan';
var index=name.indexOf('i');
var num=0;
while(index!=-1){
console.log(index);
num++;
index=name.indexOf('i',index+1);
}
console.log('i 出现的次数是:'+num);
打印结果为:
1
6
8
i 出现的次数是:3
(2).search( ):获取字符串中指定内容的索引(参数里一般是正则)
语法:
索引值 = str.search(想要查找的字符串);
索引值 = str.search(正则表达式);
search()
方法里的参数,既可以传字符串,也可以传正则表达式。
解释:可以检索一个字符串中是否含有指定内容。如果字符串中含有该内容,则会返回其第一次出现的索引;如果没有找到指定的内容,则返回 -1。
举例:
const name = 'xiaofeixiaPan';
console.log(name.search('Pan')); // 打印结果:10
console.log(name.search(/Pan/i)); // 打印结果:10
备注:上方的/yi/i
采用的是正则表达式的写法,意思是,让 name去匹配字符Pan
,忽略大小写。
(3).includes( ):字符串中是否包含指定的内容
语法:
布尔值 = str.includes(想要查找的字符串, [position]);
解释:判断一个字符串中是否含有指定内容。如果字符串中含有该内容,则会返回 true;否则返回 false。
参数中的 position
:如果不指定,则默认为0;如果指定,则规定了检索的起始位置。
const name = 'xiaofeixiaPan';
console.log(name.includes('fei')); // 打印结果:true
console.log(name.includes('haha')); // 打印结果:false
console.log(name.includes('yi',7)); // 打印结果:false
(4).startsWith( ):字符串是否以指定的内容开头
语法:
布尔值 = str.startsWith(想要查找的内容, [position]);
解释:判断一个字符串是否以指定的子字符串开头。如果是,则返回 true;否则返回 false。
参数中的position:
- 如果不指定,则默认为0。
- 如果指定,则规定了检索的起始位置。检索的范围包括:这个指定位置开始,直到字符串的末尾。即:[position, str.length)
举例:
const name = 'abcdefg';
console.log(name.startsWith('a')); // 打印结果:true
console.log(name.startsWith('b')); // 打印结果:false
// 因为指定了起始位置为3,所以是在 defg 这个字符串中检索。
console.log(name.startsWith('d',3)); // 打印结果:true
console.log(name.startsWith('c',3)); // 打印结果:false
(5).endsWith():字符串是否以指定的内容结尾
语法:
布尔值 = str.endsWith(想要查找的内容, [position]);
解释:判断一个字符串是否以指定的子字符串结尾。如果是,则返回 true;否则返回 false。
参数中的position:
- 如果不指定,则默认为 str.length。
- 如果指定,则规定了检索的结束位置。检索的范围包括:从第一个字符串开始,直到这个指定的位置。即:[0, position)
- 或者你可以这样简单理解:endsWith() 方法里的position,表示检索的长度。
注意:startsWith() 和 endsWith()这两个方法,他们的 position 的含义是不同的。
举例:
const name = 'abcdefg';
console.log(name.endsWith('g')); // 打印结果:true
console.log(name.endsWith('f')); // 打印结果:false
// 因为指定了截止位置为3,所以是在 abc 这个长度为3字符串中检索
console.log(name.endsWith('c', 3)); // 打印结果:true
console.log(name.endsWith('d', 3)); // 打印结果:false
(6).获取指定位置的字符
(1)charAt(index)
语法:
字符 = str.charAt(index);
解释:返回字符串指定位置的字符。这里的 str.charAt(index)
和str[index]
的效果是一样的。
注意:字符串中第一个字符的下标是 0。如果参数 index 不在 [0, string.length) 之间,该方法将返回一个空字符串。
举例:
const name = 'xiaofeixiaPan';
console.log(name.charAt(3)); // 打印结果:o
(2) str[index]
str.charAt(index)
和str[index]
的效果是一样的,不再赘述。区别在于:str[index]
是 H5 标准里新增的特性。
(3) charCodeAt(index)
语法:
字符 = str.charCodeAt(index);
解释:返回字符串指定位置的字符的 Unicode 编码。不会修改原字符串。
在实际应用中,通过这个方法,我们可以判断用户按下了哪个按键。
代码举例:打印字符串的占位长度。
提示:一个英文占一个位置,一个中文占两个位置。
思路:判断该字符是否在 0-127 之间(在的话是英文,不在是非英文)。
const name = 'xiaofeixiaPan';
var a=name.charCodeAt(3);
console.log(a);//111
转换方法
split():字符串转换为数组 【重要】
语法:
新的数组 = str.split(分隔符);
解释:通过指定的分隔符,将一个字符串拆分成一个数组。不会改变原字符串。
备注:split()
这个方法在实际开发中用得非常多。一般来说,从接口拿到的 json 数据中,经常会收到类似于"q, i, a, n"
这样的字符串,前端需要将这个字符串拆分成['q', 'i', 'a', 'n']
数组,这个时候split()
方法就派上用场了。
代码举例 1:
var str='xiao,fei,xia,Pan';
var arr=str.split(',');
console.log(arr);//(4) ['xiao', 'fei', 'xia', 'Pan']
八.===
和==
I.==
==
和!=
都会先进行类型转换,再确定操作数是否相等
如果任一操作数是布尔值,则将其转换为数值再比较是否相等
let result1 = (true == 1); // true
如果一个操作数是字符串,另一个操作数是数值,则尝试将字符串转换为数值,再比较是否相等
let result1 = ("55" == 55); // true
如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf()
方法取得其原始值,再根据前面的规则进行比较
let obj = {valueOf:function(){return 1}}
let result1 = (obj == 1); // true
null
和undefined
相等
let result1 = (null == undefined ); // true
如果有任一操作数是 NaN
,则相等操作符返回 false
let result1 = (NaN == NaN ); // false
如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回true
let obj1 = {name:"xxx"}
let obj2 = {name:"xxx"}
let result1 = (obj1 == obj2 ); // false
总结:
- 两个都为简单类型,字符串和布尔值都会转换成数值,再比较
- 简单类型与引用类型比较,对象转化成其原始类型的值,再比较
- 两个都为引用类型,则比较它们是否指向同一个对象
- null 和 undefined 相等
- 存在 NaN 则返回 false
II. ===
全等操作符由 3 个等于号( === )表示,只有两个操作数在不转换的前提下相等才返回 true
。即类型相同,值也需相同
let result1 = ("55" === 55); // false,不相等,因为数据类型不同
let result2 = (55 === 55); // true,相等,因为数据类型相同值也相同
undefined
和 null
与自身严格相等
let result1 = (null === null) //true
let result2 = (undefined === undefined) //true
虽然null == undefined 是true(因为这两个值类似),但null === undefined 是
false,因为它们不是相同的数据类型。
总结:
除了在比较对象属性为null
或者undefined
的情况下,我们可以使用相等操作符(),其他情况建议一律使用全等操作符(=)
九.typeof和instanceof
typeof
typeof
操作符返回一个字符串
,表示未经计算的操作数的类型。
- 可以判断: undefined/ 数值 / 字符串 / 布尔值 / function
- 不能判断: null与object object与array
注意
: 运行console.log(typeof undefined)
时,得到的的也是一个字符串,同时为小写!!
–>'undefined'
// typeof返回数据类型的字符串表达
var a
//注意:typeof返回的是字符串
console.log(a, typeof a, typeof a==='undefined',a===undefined )
// undefined 'undefined' true true
console.log(undefined === 'undefined') //false
a = 4
console.log(typeof a==='number') //true
a = 'xiaofeixia'
console.log(typeof a==='string') //true
console.log(typeof a==='String') //false -->注意,返回的类型为小写
a = true
console.log(typeof a==='boolean') //true
a = null
console.log(typeof a, a===null) // 'object' true
let b={}
console.log(typeof b,typeof null)
// 'object' 'object' -->所以Typeof不能判断null与object
typeof null为
object
如果你需要在 if
语句中判断是否为 null
,直接通过===null
来判断就好
引用类型数据,用typeof
来判断的话,除了function
会被识别出来之外,其余的都输出object
typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof null // 'object'
typeof [] // 'object'
typeof {} // 'object'
typeof console // 'object'
typeof console.log // 'function'
instanceof
instanceof
运算符用于检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上。
var b1 = {
b2: [1, 'abc', console.log],
b3: function () {
return () =>{ return 'hello'}
}
}
/**使用instanceof进行对象判断*/
console.log(b1 instanceof Object, b1 instanceof Array) // true false
console.log(b1.b2 instanceof Array, b1.b2 instanceof Object) // true true
console.log(b1.b3 instanceof Function, b1.b3 instanceof Object)
// true true
/**使用typeof进行对象中某属性的判断*/
console.log(typeof b1.b2, typeof null) // 'object' 'object'
console.log(typeof b1.b3==='function') // true
console.log(typeof b1.b2[2]==='function') //true
/**调用对象与数组中某函数示例*/
b1.b2[2]('调用console.log打印hello') //调用console.log打印hello
console.log(b1.b3()()) // hello
构造函数通过new
可以实例对象,instanceof
能判断这个对象是否是之前那个构造函数生成的对象
// 定义构建函数
let Car = function() {}
let benz = new Car()
benz instanceof Car // true
let car = new String('xxx')
car instanceof String // true
let str = 'xxx'
str instanceof String // false
typeof
与instanceof
都是判断数据类型的方法,区别如下:
-
typeof
会返回一个变量的基本类型(是一个字符串),instanceof
返回的是一个布尔值 -
instanceof
可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型 - 而
typeof
也存在弊端,它虽然可以判断基础数据类型(null
除外),但是引用数据类型中,除了function
类型以外,其他的也无法判断