javascript中一种有9种数据类型,有7种简单数据类型(也称为基本数据类型):undefined、null、boolean、number 和string、symbol、bigint,还有2种复杂数据类型——Objectfunction

# 1、undefined

undefined 类型只有一个值,即特殊的undefined。根据工作中总结,只要有这几种情况下会出现undefined

1.定义变量,但是没有初始化时,如var a;

2.调用某个函数时,实参个数小于形参个数时,未实参化的形参在函数调用过程中的值是undefined

3.调用某个对象还没有添加的属性时,也会返回undefined

var obj={}   
console.log(obj.name);//undefined
1
2

4.调用某个没有返回值的函数,也会返回undefined;

function Person(name,age){
    this.name=name;
    this.age=age;
}
var p=Person("李四",23);//此时的p=undefined;       
1
2
3
4
5

5.对未初始化的变量执行 typeof 操作符会返回 undefined 值;

6.对未声明的变量执行 typeof 操作符同样也会返回 undefined 值。

var message; // 这个变量声明之后默认取得了 undefined 值   
//未初始化的变量
alert(typeof message);     // "undefined"  
//未申明的变量
alert(typeof age);         // "undefined"   
1
2
3
4
5

# 2、Null 类型

  是第二个只有一个值的数据类型,这个特殊的值是 null。从逻辑角度来看,null值表示一个空对象指针,保存对象的变量还没有真正保存对象。而这也正是使用 typeof 操作符检测 null值时会返回object的原因。这几种情况下会出现null的情况。

1、手动设置变量的值或者对象某一个属性值为null(在初始化对象时,手动设置对象为null。在作用域中不再需要使用某个对象时,把null赋值给那个变量解除引用,以释放内存)

2、在javascript的DOM元素获取中,如果没有获取到指定的元素对象,结果一般是null。

var d=document.getElementById("d");
console.log(d);//当没有id为"d"的标签时返回null
1
2

3、Object.prototype._proto_的值也是null。(每一个对象都有__proto__属性,指向对应的构造函数的prototype属性,但是因为Object是所有类的基类,其没有对应的构造函数,所有Object.prototype._proto_值为空);

console.log("a".__proto__);
//指向的是String的prototype属性
//String {"", length: 0, constructor: ƒ, anchor: ƒ, big: ƒ, blink: ƒ, …}
1
2
3

4、在正则捕获的时候,如果没有捕获到结果,默认也是null。

注意:实际上,undefined 值是派生自 null值的。undefined转为数值为NAN,而null转为数值却为0

alert(typeof null);//object
alert(null == undefined);弹出的是true 
alert(Number(undefined));//NAN
alert(Number(null))//0
1
2
3
4

# 3、Boolean类型

  这个类型需要注意的值它的两个字面量true和false是区分大小写的。还要注意其他类型转换为此类型的情况。

数据类型 转换为true的值 转换为false的值
String 任何非空字符串 空字符串("")
Number 任何非零数值(包括无穷大) 0和NAN
Object 任何对象 null
undefined 没有为true的情况 undefined

注意:

  • js存在6种假值。分别是 ""、0、null、undefined、false、和NAN。
  • +true返回的是1。一元加号会尝试将 boolean 类型转换为数字类型。 true被转换为1,false被转换为0。
  • +"1"返回的是NAN。

# 4、Number

注意点1: Number的浮点数值在进行算术计算时精确度远远不如正数,所以不要去计算两个浮点数相加的结果是否等于另一个浮点数。

if(0.1+0.2==0.3){
    alert("相等")
}
1
2
3

  这种情况永远都不会弹出"相等"的。因为浮点数的精度太高,0.1+0.2的值不一定精确的等于0.3。

注意点2: NaN,即非数值(Not a Number)是一个特殊的数值,这个数值用于表示一个本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误了)。

NaN 本身有两个非同寻常的特点。

  • 1、任何涉及 NaN 的操作(例如 NaN/10)都会返回 NaN,这个特点在多步计算中有可能导致问题。

  • 2、NaN 与任何值都不相等,包括 NaN 本身。

  针对 NaN 的这两个特点,ECMAScript定义了 isNaN()函数。这个函数接受一个参数,该参数可以 是任何类型,而函数会帮我们确定这个参数是否“不是数值”。任何不能被转换为数值的值都会导致这个函数返回 true。用ES6Object.is(NAN,NAN)比较时返回true

isNAN(null) //false 先Number(null)在判断
isNAN("12px") //true 先Number(null)在判断
1
2

注意点3: 数值转换   有三个函数可以将非数值转换为数值:Number()parseInt()parseFloat()Number()可以用于转换任何数据类型,而另外两个只能将字符串转换为数值。

# 4.1 Number()函数的转换规则如下所示

  • 如果是 Boolean 类型,truefalse 分别转换为1和0.
    Number(true);//1
    Number(false);//0
    
    1
    2
  • 如果是null 值,返回0
  • 如果是 undefined,返回 NAN
    Number(null);//0
    Number(undefined);//NAN
    
    1
    2
  • 如果是 String 类型,需要考虑以下情况。
    • 1、如果字符串中只包含数字,则直接将其转换为10进制数值,并且会忽略前导0。如"123"会变成123,"011"会变成11,"1.1"会变成1.1。
    Number("0123") //123
    Number("11.2")// 11
    
    1
    2
    • 2、字符串中包含有效的十六进制格式,则会将其转换为相同大小的10进制整数值。
    Number("0xA") //10
    
    1
    • 3、如果字符串为空的,则将其转换为0。
    Number("") //0
    
    1
    • 4、除上面三种情况外,都会转换为NAN。
    Number('10px')//NAN
    
    1
  • 如果是Object类型,则调用对象那个的 valueOf(),依照前面的规则转换返回的值。不过一般不会将对象去转换成对应的数值。一般情况下对象转换成数值都是返回 NAN
    Number({a:123});//NAN
    
    1

# 4.2 parseInt(value,radix)的转换规则

  • radix是一个进制,不写或者写0都是按10处理。(特殊情况:如果 value是以0x 开头,则进制为16)。
  • 进制有一个取值的范围:2~36 之间,不在这个区间的结果是NAN
    parseInt(18,18)// 18+8=>26
    
    1

  会先把value转换成字符串。在转换字符串时更多的是看其是否符合数值格式,它会自动忽略字符串前面的空格,直到找到第一个非空字符串,如果是非数值字符串就直接返回 NAN,如果是数值字符串则会一直匹配到非数值字符串处结束。并且转换空字符转时会返回NAN。

parseInt也能够识别出各种正数格式(八进制、十六进制)。做这种转换时需要传递第二个参数,不然分辨不出八进制格式的数据。

parseInt("");//NAN      
parseInt(null) //NAN
parseInt(undefined);//NAN
parseInt("  s");//NAN
parseInt("s");//NAN
parseInt("   2s");//2
parseInt("0xA",16);//10(十六进制)
parseInt("070");//70
parseInt("070",8);//56
1
2
3
4
5
6
7
8
9

下面是一道关于parseInt()的经典面试题目。

let arr=[10.18,0,"0013",10,25,23,77];
arr.arr.map(parseInt);
console.log(arr); //[10,NAN,2,2,11]

parseInt("10.18",0) // 10
parseInt("0",1) // NaN
parseInt("0013",2)//=>将"001"看做2进制最后转换为10进制=>1
parseInt("10",3) // 3
parseInt("25",4) //=> 将"25"看做4进制最后转换为10进制=>2
parseInt("23",5) // 13
parseInt(77,6) //NaN
1
2
3
4
5
6
7
8
9
10
11

NumberparseInt转换对比。

特殊情况 Number parseInt
空字符串 Number("")=>0 parseInt("")=>NaN
不包含数字的字符串 Number("dddd")=>NaN parseInt("gsdg")=>NaN
只包含数字的字符串 Number("012")=>12Number("012.2")=>12 parseInt("012")=>12,parseInt("012.2")=>12
包含数字的字符串 Number("012x")=>NAN parseInt("012x")=>12
字符串中包含有效的十六进制格式 Number("0xA")=>10 parseInt("0xA")=>10
null Number(null)=>0 parseInt(null)=>NaN
undefined Number(undefined)=>NaN parseInt(undefined)=>NaN

# 4.3 parseFloat转换规则

parseFloatparseInt 的解析规则类似。parseFloat()parseInt()多识别一个0。 区别在于:它只解析十进制值,没有第二个参数指定基数。

# 4.4 为什么12.toString()会报错呢?

这是因为十进制的Number是可以带小数的,小数点前后部分都可以省略,但是不能同时省略。

.01
12.
12.01
1
2
3

12.toString表达式会被看成12.,当做省略了小数点后面部分的数字,而单独看成一个整体。所以如果我们想要单独让"."成为一个整体,就要加入空格:

12 .toString()=>"12"
1

# 5、String类型

这里在价格其他类型的值转换为字符串时,主要遵循如下规则。

  • 1、如果值有 toString()方法,则调用该方法(没有参数)并返回相应的结果;

  • 2、如果值是 null,则返回 "null";

  • 3、如果值是 undefined,则返回 "undefined"

var value1 = 10;
var value2 = true; 
var value3 = null; 
var value4; 
alert(String(value1));     // "10"  
alert(String(value2));     // "true
alert(String(value3));     // "null"
alert(String(value4));     // "undefined" 
1
2
3
4
5
6
7
8

主要有以下方法:

  • 1、字符方法
    • charAt(index):返回给定位置的字符,index未指定时,默认为0。
    • charCodeAt(index):返回指定位置的字符编码,index未指定时,默认为0。
    • fromCharCode():接收一个或多个字符编码,然后将他们转换为字符串。从本质上看是charCodeAt()的相反操作。
    console.log(String.fromCharCode(104,102,103,106));//"hfgi"
    var str="hijhj"
    console.log(str.charAt());//"s",index未指定时,默认为0
    console.log(str.charAt(1));//"i"
    console.log(str.charCodeAt());//104
    console.log(str.charCodeAt(1));//105
    
    1
    2
    3
    4
    5
    6
  • 2、字符串操作方法
    • 字符串拼接:concat(),不会改变字符串本身,会返回一个新的字符串。
    • 字符串分割:slice()substr()substring()。不会改变字符串本身,会返回一个新的字符串。他们之间的区别如下。
方法 第一个参数 第二个参数
slice 表示切割的起点(默认值为0),为负数时会将负值与字符串的长度相加作为索引起点 表示切割的终点(默认值为字符串的长度),为负数时会将负值与字符串的长度相加作为索引终点
substr 表示切割的起点,为负数时会将负值与字符串的长度相加作为索引起点 表示切割的个数,为负数时自接转换为0
substring 表示切割的起点,为负数时自接转换为0 表示切割的终点,为负数时自接转换为0
var str="hello world";
console.log(str.slice());//hello world
console.log(str.slice(1,3))//el
console.log(str.slice(-1,-3))//""
console.log(str.substring());//hello world
console.log(str.substring(1,3));//el
console.log(str.substring(-1,-3))//""
console.log(str.substr())//hello world
console.log(str.substr(1,3));//ell
console.log(str.substr(-1,-3))//""
1
2
3
4
5
6
7
8
9
10
  • 3、字符串位置方法

indexOf(str,index)lastIndexOf(str,index):用于从指定字符串中指定位置(index,默认是0)开始搜索str,返回str第一次出现的位置的索引值。只不过indexOf()是从开头向后搜索,lastIndexOf反之。

  • 4、trim()方法

  用于删除字符串前置和后缀的所有空格。

  • 5、字符串大小写转换方法

    • toLowerCase() 将字符串全部转换为小写;
    • toUpperCase() 将字符串全部转换为大写。还有针对特定地区的方法如
    • toLocaleLowerCase() 将字符串全部转换为小写;
    • toLocaleUpperCase() 将字符串全部转换为大写。建议一般情况下使用针对地区的方法。
  • 6、字符串的模式匹配方法

match(): 只接受一个参数,要么是正则表达式,要么是RegExp对象,返回一个数组。本质上于RegExp的exec()方法相同。

var str="hello world";
var pattern=/llo/;
var matches=str.match(pattern);
console.log(matches)
1
2
3
4

search(): 与match方法的参数相同,要么是正则表达式,要么是RegExp对象。返回字符串中第一个匹配项的索引。如果没有匹配上则返回-1。并且始终从字符串开始向后查找。

var str="hello world";
var pattern1=/llo/;
var pattern2="lloe"
var index1=str.match(pattern1);//2
var index2=str.match(pattern2);//-1
1
2
3
4
5

replace(): 接收两个参数,第一个参数可以是RegExp对象或者字符串,第二个参数是一个字符串或者一个函数。第一个参数是字符串时,name只会替换第一个子字符串。要想替换所有的子字符串,必须提供正则表达式,而且要指定全局(g)标志。

var str = "hello world";
var res1 = str.replace("l", "ww");
console.log(res1); //  hewwlo world     
var res2 = str.replace(/l/g, "ww");
console.log(res2);//hewwwwo worwwd
1
2
3
4
5

  如果第二个参数为字符串,还可以使用一些特殊的字符序列。 实例如下:

var str="hello world hello hello";
var res=str.replace(/(.ll)/g,"123($1)");
console.log(res);//h123(ell)o world h123(ell)o h123(ell)o
1
2
3

  如果第二个参数为函数,在只有一个匹配项的情况下,会向这个函数传递3个参数:模式的匹配项,模式匹配项在字符串中的位置和原始字符串。 function(match,pos,originalText) 。如果是有多个捕获组的情况下,传递给函数的参数依次是模式的匹配项,第一个捕获组的匹配项,第二个捕获组的匹配项。。。,最后两个参数仍然是模式匹配项在字符串中的位置和原始字符串。

split(): 基于指定的分隔符将字符串分割为多个子字符串。并返回一个数组。分隔符可以是字付串也可以是RegExp对象。还可以接受第二个参数,用于指定返回数组的大小。

var str="tre,rwr,rewr,rwrew";
var res1=str.split(",");
var res2=str.split(",",2);
var res3=str.split(/[^\,]+/);//表示以多个非","进行分割
console.log(res1);//(4) ["tre", "rwr", "rewr", "rwrew"]
console.log(res2);//(2) ["tre", "rwr"]
console.log(res3);//(5) ["", ",", ",", ",", ""]
1
2
3
4
5
6
7
  • 7、localeCompare()方法

  用于比较两个字符串。 如果字符串再字母表中排在传入字符串参数之前,则返回一个负数,反之则是一个整数,相等时返回0。

var str="bbc";
alert(str.localeCompare("cca"));//-1
alert(str.localeCompare("aca"));//1
alert(str.localeCompare("bbc"));//0
1
2
3
4
  • 8、HTML方法
    但是尽量不去使用这些方法,因为他们创建的标记通常无法表达语义。

# 6、symbol

用于定义唯一值。这个类型在es6专题中详细总结了。

# 7、bigint

Number.MAX_SAFE_INTEGER 是最大的安全数,超出这个数的值在后面加上n,用9007199254740992n表示。

# 8、object

object主要有以下几种类型

  • 普通对象
  • 日期对象
  • 正则对象
  • 数组对象
typeof {} //object
typeof new Date() //object
typeof [] //object
typeof /\w+/ //object
1
2
3
4

注意: 普通对象的key 值只能是字符串和 Symbol。就算不是这两种类型,也会转化为字符串类型。默认调用toString()将之转化为字符串。

const a={
    name:'james'}
a[[1,2]]=123
a[true]=222
a[null]=122
a[undefined]=123
console.log(Object.keys(a)) //(5) ["name", "1,2", "true", "null", "undefined"]
1
2
3
4
5
6
7
8

注意

  • a=b=10 连等赋值执行顺序从右到左。
  • a.x=b=12,.的优先级(等级为19)高于=(等级为3),所以会先计算a.x=12,所以实际执行过程是a.x=12,b=12
let a={n:10};
let b=a;
a.x=a={n:12};//执行顺序为a.x={n:12},a={n:12}。
console.log(a);//{a:12}
console.log(b);//{n:10,x:{n:12}}
1
2
3
4
5

主要是注意这几个方法:

  • hasOwnProperty(propertyName): 用于检查给定的属性在当前对象实例中(而不是在实例的原型中)是否存在。其中,作为参数的属性名(propertyName)必须以字符串形式指定(例如:o.hasOwnProperty("name"))。

  • isPrototypeOf(object): 用于检查传入的对象是否是传入对象的原型。

  • propertyIsEnumerable(propertyName): 用于检查给定的属性是否能够使用 for-in语句 (本章后面将会讨论)来枚举。与 hasOwnProperty()方法一样,作为参数的属性名必须以字符串形式指定。

  • getKeys(obj): 返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。

  • getValues(obj): 返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。属性名为数值的属性,是按照数值大小,从小到大遍历的。

# 9、function

typeof function(){} //function
1

# 10、类型转换

类型的转换规则如下表所示。转载自ConardLi大神的[JS 进阶】你真的掌握变量和类型了吗] (https://juejin.im/post/5cec1bcff265da1b8f1aa08f) 暂无图片

# 1 非Nmbere类型的数学运算

我们在对各种非 Number 类型运用数学运算符(- * /) 时,会先将非 Number 类型转换为 Number 类型。

1 - true // 0 
1 - null //  1 
1 * undefined //  NaN Number(undefined)=>NaN
2 * ['5'] //  10  Number(["5"])=>Number(["5"].toString())=>5
1
2
3
4

# 2、+ 运算符

但是+是个例外,执行+ 操作符时:

当一侧为String/Object类型,被识别为字符串拼接,并会优先将另一侧转换为字符串类型。

![]+[] //->"false" 等价于false+[] ->"false"+[].toString()
{}+{} //[object Object][object Object]
123 + {}  // 123[object Object]    (规则3) 
[1,2,3]+[4,5,6]  //->1,2,34,5,6 等价于 [1,2,3].toString()+[4,5,6].toString()
1
2
3
4

当一侧为Number类型,另一侧为原始类型,则将原始类型转换为Number类型

123 + '123' // 123123   (规则1)
123 + null  // 123    (规则2)
123 + true // 124    (规则2)
1
2
3

当一侧为Number类型,另一侧为引用类型,将引用类型和Number类型转换成字符串后拼接

{}+0 //0 {}会被看成一个代码块
({}+0) //[object Object]0
0+{} //0[object Object]
1
2
3

# 3、== 运算符

引用类型转换为原始数据类型时,会按照以下优先级来进行转换。

  • Symbol.toPrimitive(input,preferedType?)
  • valueOf()
  • toString()

注意:

  • 1、Boolean 和其他任何类型比较,Boolean 首先被转换为Number类型。
true == 1  // true 
true == '2'  // false  //实际上是Number(true)!==Number("2")
true == ['1']  // true //实际上是Number(true)===Number(['1'].valueOf().toString())
true == ['2']  // false 
//实际上是Number(true)!==Number(['2'].valueOf().toString())
undefined == false // false  false会首先转换为0所以不相等
null == false // false
1
2
3
4
5
6
7
  • 2、StringNumber 比较,先将 String 转换为Number 类型。
123 == '123' // true 
'' == 0 // true      
1
2
  • 3、null == undefined 比较结果是 true,除此之外,null、undefined 和其他任何结果的比较值都为 false
undefined == false // false  false会首先转换为0所以不相等
null == false // false
1
2
  • 4、当原始类型和引用类型做比较时,对象类型会依照ToPrimitive规则转换为原始类型。
'[object Object]' == {} // true 

//分析:{}会直接调用tostring()方法,所以左右两边相等。
1
2
3
'1,2,3' == [1, 2, 3] // true

//分析:[1, 2, 3]会先调用valueOf()方法,然后调用toString()方法
1
2
3
[] == ![] // true

//等价于 Number([].valueOf().toString())==Number(false)
1
2
3

分析: 左边[]会先调用 valueOf(),然后调用 toString() 方法,最后调用Number方法。右边![]会先转换为false,然后转换为 number类型为0,所以左右两边相等。

!的优先级高于==,![]首先会被转换为 false,然后根据上面第二点,false 转换成 Number 类型0,左侧[]转换为0,两侧比较相等。

[null] == false // true
//[null].valueOf().toString()=>""
//等价于 Number([null].valueOf().toString())==Number(false);
[undefined] == false // true
//[undefined].valueOf().toString()=>""
//等价于 Number([undefined].valueOf().toString())==Number(false);
1
2
3
4
5
6

分析: 根据数组的 ToPrimitive 规则,数组元素为nullundefined 时,该元素被当做空字符串处理,所以[null][undefined] 都会被转换为0。

Last Updated: 6/11/2024, 11:35:27 AM