J04 js中常用的数据类型

216 阅读7分钟

基本数据类型

  • number:常规数字和NaN
  • bigint:最大安全数
  • symbol:唯一值
  • infinity:无穷大
  • string: 所有用单引号、双引号、反引号(撇)包起来的都是字符串
  • boolean: true/false
  • null:空对象指针
  • undefined:未定义

引用数据类型

  • 对象数据类型object
    • {} 普通对象
    • [] 数组对象
    • /[1]?(\d|([1-9]\d+))(.\d+)?$/ 正则对象
    • Math数学函数对象
    • 日期对象
    • 实例对象
    • prototype原型对象
  • 函数数据类型function

一.number数字类型

包含:NaN、正数、零、负数、小数

NaN:NaN和任何值都不相等(包括自己),NaN!=NaN,所以我们不能用相等方式判断是否为有效数字。

not a number:不是一个数,但它率属于数字类型

console.log('AA' == NaN);//=>false
console.log(10 == NaN);//=>false
console.log(NaN == NaN);//=>false 
isNaN

检测一个值是否为非有效数字,如果不是有效数字返回TRUE反之是有效数字返回FALSE

语法:isNaN([val])
console.log(isNaN(10)); //=>FALSE 

console.log(isNaN('AA')); //=>TRUE 

console.log(isNaN('10')); //=>false

在使用isNaN进行检测的时候,首先会验证检测的值是否为数字类型,如果不是,先基于Number()这个方法,把值转换为数字类型,然后再检测

console.log(isNaN('10')); //=>FALSE

/*步骤:
 *  Number('10')  =>10
 *  isNaN(10) =>FALSE
 */
console.log(isNaN('AA')); //=>TRUE

/*步骤
 * Number('AA') =>NaN 
 * isNaN(NaN) =>TRUE
 */

1.把其它类型值转换为数字类型

  • Number([val])

1.1、字符串转换为数字类型

把字符串转换为数字,只要字符串中包含任意一个非有效数字字符(第一个点除外)结果都是NaN,空字符串会变为数字零

 console.log(Number('12.5')); //=>12.5

console.log(Number('12.5px')); //=>NaN

console.log(Number('12.5.5')); //=>NaN

console.log(Number('')); //=>0 

1.2、布尔转换为数字

bolean转换为数字,ture的结果是1;false的结果是0

console.log(Number(true)); //=>1

console.log(Number(false)); //=>0

console.log(isNaN(false)); //=>false 

1.3、空对象指针null转换为数字

null等于0;虽然代表没有,但有占位,那还是有一个东西

console.log(Number(null));//=>0

1.4、未定义undefined转换为数字

undefined未定义,未定义就是没有值,没有赋值就是NaN

console.log(Number(undefined)); //=>NaN

1.5、引用数据类型转换为数字

对象变为数字,应该先valueOf,没有原始值再toString变为字符串,最后把字符串转换为数字

console.log(Number({name:'10'}));
分析步骤:
//1.引用类型先转换为字符串
=>{name:'10'} .toString() 
//2.在转换为数组类型
=> "[object Object]" 
=> NaN
console.log(Number([]));
分析步骤:
//1.引用类型先转换为字符串
=> [].toString() -> ''
//2.在转换为数组类型
=> Number('')
=>0
console.log(Number([12]));
分析步骤:
//1.引用类型先转换为字符串
=>[12].toString() -> '12'
//2.在转换为数组类型
=>Number('12')
=>12
console.log(Number([12,23]));
分析步骤:
//1.引用类型先转换为字符串
=> [12,23].toString() 
=> '12,23'
//2.在转换为数组类型
=>Number('12,23')
=>NaN 

1.6、ParseInt/ParseFloat

语法:ParseInt/ParseFloat([val],[进制]);也是转换数字的方法,对于字符串来说,他是从左到右依次查找有效数字,直到遇到非有效数字,停止查找,(不管后面是否还有数字,都不在找了),把找到的当做数字返回。

console.log(Number('12px')); //=>NaN  
console.log(parseInt('12px')); //=>12
console.log(parseInt('12px24')); //=>12
console.log(parseInt('width:12px')); //=>NaN
console.log(parseInt('12.5px')); //=>12
console.log(parseFloat('12.5px')); //=>12.5  

console.log(Number(true)); //=>1
console.log(parseInt(true)); 
分析步骤:
//1.先把TRUE转换为字符串"TRUE" 
=>parseInt('true') 
=>NaN
console.log(parseInt(NaN)); 
分析步骤:
//1.先把NaN转换为字符串"NaN" 
=>parsetint("NaN")
=>NaN
console.log(Number(null)); //=>0

console.log(parseInt(null)); 
分析步骤:
//1.先把null转换为字符串"null" 
=> parseInt('null') 
=>NaN
 console.log(isNaN(Number(parseInt("0.8"))));
 分析步骤:
 //1.先算parseInt("0.8")
 =>parseInt("0.8")
 =>0
 //2. 再算0是不是数组类型
 =>Number(0)
 =>0  
 //3.最后检测0是不是一个数
 =>isNaN(0)
 =>false
console.log(Number('')); //=>0
console.log(parseInt('')); //=>NaN
var str = 'abc123';
var num = parseInt(str);  //=>NaN
if (num == NaN) { //=> NaN==NaN 不相等,NaN和谁都不相等(包括自己)
	alert(NaN);
} else if (num == 123) {   //=>NaN==123 不成立
	alert(123);
} else if (typeof num == 'number') { 
//=> typeof NaN = "number"  //=>"number"==="number" 条件成立
	alert('number'); 
} else {
	alert('str');
}
分析:
//parseInt 是把一个字符串转换为数字(如果值不是字符串,也要先转换为字符串),
从字符串最左侧开始查找,把找到的有效数字字符转换为数字,一旦遇到一个非有效数字字符,
则停止向后查找(不管后面是否还有数字都不在找了)
// 在浏览器中弹出一个窗口  输出 "number"
计算结果:
1.isNaN(null) //=>isNaN(0) =>false
2.isNaN(parseInt(null)) //=>parseInt("null") =>NaN =>isNaN(NaN) =>true
3.Number(null) //=>0
4.parseFloat(null) //=>parseFloat("null") =>NaN
计算结果:Number和parseInt在转换为数字的时候,规则是不一样的

1.parseInt("") //=>NaN
2.Number("") //=>0
3.isNaN("") //=>需要先调用Number转换为数字再检测 isNaN(0)  =>false
4.parseInt(null) //=>先把值转换为字符串 parseInt("null") =>NaN
5.Number(null) //=>0
6.isNaN(null) //=>isNaN(Number(null)) => isNaN(0) =>false
7.parseInt("12px") //=>12
8.Number("12px") //=>NaN
9.isNaN("12px") //=>isNaN(Number('12px')) =>isNaN(NaN) =>true

1.7 toFixed:保留小数点后面N位(最后的结果是一个字符串)

let n = 3.1415926;
console.log(n.toFixed(2)); //=>"3.14"

2.bigint最大安全数

ES6中提供了一个新的数据类型 BigInt:管理超过安全数值的数字

2.1 求最大安全数

console.log(Number.MAX_SAFE_INTEGER);
//=>9007199254740991 最大安全数(JS能够有效识别的最大整数)

2.2 求最小安全数

console.log(Number.MIN_SAFE_INTEGER);
//=>-9007199254740991 最小安全数(JS能够有效识别的最小整数)

2.3 超过最大安全数 最比较是无效的

console.log(9007199254740992 == 9007199254740993);
//=>true  应该是不一样的,但是超过了最大数值,JS无法精准计算

console.log(BigInt(9007199254740992), BigInt(9007199254740993));
//=>9007199254740992n 9007199254740992n(出现n超过最大安全数)

//=>9007199254740991n  =>bigint类型的

3.symbol 唯一值

Symbol([value]):创建唯一值

console.log(Symbol('A') == Symbol('A'));
//=>false

console.log(Number(Symbol(10))); 
//=>报错

4.Infinity:无穷大

console.log(Infinity);
//=>Infinity

二.String类型

在JS中用 单引号/双引号/反引号 包起来的都是字符串

  • 语法
    • String([value])
    • [value].toString()

在JS中常用的数学运算

  • 数学运算:+ - * / 加减乘除 %(膜)取余数
 console.log(4 / 2); //=>除  2
 console.log(7 / 3); //=>除  2.3333333333333335
 console.log(7 % 3); //=>取余  1
console.log('10' - 10); //=>0
console.log('10px' - 10); //=>NaN */
console.log(10 - null); //=>10
console.log(3 * undefined); //=>NaN
console.log(true - "12"); //=>1-12 =>-11
console.log(3 - "3px"); //=>NaN
console.log(3 + "3px"); //=>"33px"  字符串拼接
console.log(1 + "1"); //=>"11" 字符串拼接
console.log(1 + {}); 
//=>"1[object Object]" 
//=>在把{}转换为数字过程中,先把他转换为字符串"[object Object]",
//=>此时右侧出现了字符串,则不再是数学运算,而是字符串拼接了
console.log(1 + []); //=>'1'
console.log([10] + true); 
//1.先把其转换为字符串"10"
=>"10"+true
//2.此时操作变为字符串拼接(和数学运算没关系了)
=>"10true" 
console.log(true + [10]); //=>"true10"
console.log(1 + true); //=>2 */
let a = 10 + null + true + [] + undefined + '珠峰' + null + [] + 10 + false;
console.log(a);
  
=>10 + null => 10 + 0 => 10
=>10 + true => 10 + 1 => 11
=> 11 + [] => 11 + => '11'
//空数组变为数字,先要经历变为 空字符串,遇到字符串,啥都别想了, 直接变为字符串拼接 
=>'11' + undefined -> '11undefined'
 =>'11undefined珠峰null10false'
var a = 'abc' + 123 + 456;
console.log(a);//=>'abc123456'
分析步骤:
在JS中除了数学运算还有字符串拼接
//1.=>'abc' + 123 => 'abc123'
//2.=>'abc123' + 456 
    => 'abc123456'
var b = '456' - '123';
console.log(b);//=>333
分析:
1.-/*%这些运算符都是数学运算(要把其它类型值基于Number()转换为数字再进行运算)
2.字符串中只要出现非有效数字字符结果就是NaN,空字符串变为0
3. true:1   false:0   null:0   undefined NaN symbol不能转
4. 对象是先转换为字符串 toString,然后在转换为数字
=>456 - 123 => 333
能输出"1"的有哪些 ?(1)

1.alert(1)//输出的是"1"因为基于alert/confirm等输出结果,都会把内容转换为字符串再输出

2.console.log(parseInt(1.3)) //=>parseInt('1.3')  =>1

3.console.log(1) //=>1  console.log输出的内容还是原本的数据格式

4.console.log(isNaN(1)) //=>false

5.console.log(parseInt("1")) //=>1

1.字符串拼接

除了加法以外,其余的情况都是数学运算(如果遇到非数字类型,需要基于Number把其强制转换为数字类型,然后在进行运算的);加号在JS中既有数学运算,也有字符串拼接的意思(只要加号两边的任意一边出现字符串,则变为字符串拼接)

1.1数字转为字符串

//1.声明一个变量,用变量名把存储值转换字符串
let a = 12;
console.log(a.toString()); //=>'12'

//2.NaN的字符串是 "NaN"
console.log((NaN).toString()); //=>'NaN'

1.2布尔转换为字符串

console.log(true);//=>'true'
console.log(false);//=>'false'

1.3空对象和未定义转换为字符串

null和undefined是禁止直接toString的; 但是和undefined一样转换为字符串的结果就是 'null'/'undefined'

 (null).toString(); 
 //=>报错Uncaught TypeError: Cannot read property 'toString' of null
 
 (function).toString(); 
 //=>报错 Uncaught SyntaxError: Unexpected token )

1.4数组转化为字符串

"第一项,第二项..."(逗号分隔数组中的每一项)

[].tostring();//=>''
[12].tostring();//=>'12'
[12,23].tostring();=>'12,23'

1.5正则转化为字符串

/\^$/.tostring();
//=>'/\^$/'

1.6普通对象转化为字符串

普通对象转换为字符串都是''[object object]'' 普通对象除外不是加单双引号

({name:'xxx'}):tostring();//=>"object object"

// 普通对象.toString()的结果是 "[object Object]"  
// Object.prototype.toString方法不是转换为字符串的,而是用来检测数据类型的

1.7 字符串拼接

//题目:
// 真实项目中经常把一些变量的值拼接到指定的字符串中
// 完成字符串拼接处理:2020年03月03日 12:00:00
let year = '2020';
let month = '03';
let day = '03';
let hours = '12';
let minutes = '00';
let seconds = '00';
// 1.ES6中的模板字符串就是为了解决传统字符串拼接中的问题(反引号 TAB上面的撇):
${}中存放变量或者其它的JS表达式即可,很简单的完成字符串拼接
let result = `${year}${month}${day}${hours}:${minutes}:${seconds}`;
console.log(result);   
// 2.传统的拼接方式,我们需要在字符串中基于 "++" 或者 '++' 的方式把变量拼接到字符串中
(这种方式涉及很多恶心的规则,一不留神就容易拼错)
 let result = year + "年" + month + "月" + day + "日 " + hours +
 ":" + minutes + ":" + seconds;
 console.log(result);

三. boolean布尔转换为数据类型

只有两个值true false 只有 0、NaN、''、null、undefined 五个值转换为FALSE,其余都转换为TRUE(而且没有任何的特殊情况)

  • Boolean([val])
  • !/!!
  • 条件判断
 console.log(Boolean(0));//=>false
console.log(Boolean(''));//=>false
console.log(Boolean(' '));//=>true
console.log(Boolean(null));//=>false
console.log(Boolean(undefined));//=>false
console.log(Boolean([]));//=>true
console.log(Boolean([12]));//=>true
console.log(Boolean(-1));//=>true
 

!:取反(先转为布尔,然后取反) !!:取反再取反,只相当于转换为布尔 <=> Boolean

console.log(!1); //=>FALSE
console.log(!!1); //=>true 

条件判断中,每一个条件最后一定是true/false

if (1 == 1) {}
if (1) {
	//=>写一个值,也是要把这个值转换为布尔,然后校验程序的真假
}
if (3 + '3px') {} //=>3 + '3px' =>'33px' true
if (3 - '3px') {} //=>3 - '3px' =>NaN   false

1.null / undefined区别

null和undefined都代表的是没有

  • null:意料之中(一般都是开始不知道值,我们手动先设置为null,后期再给予赋值操作) let num = null; //=>let num = 0; 一般最好用null作为初始的空值,因为零不是 空值,他在栈内存中有自己的存储空间(占了位置) ... num = 12;

  • undefined:意料之外(不是我能决定的)

let num; //=>创建一个变量没有赋值,默认值是undefined
num = 12;

四.bject对象数据-普通对象

所有的对象都应该具备以下特点:

  • 1.用键值对(key:value 俗称属性名和属性值) 来描述一个对象的特征(每一个对象都是综合体,存在零到多组键值对)
  • 2.{ key:value , ...} 每一组键值对是 key:value 的格式,多组键值对用逗号分隔
  • 3.key不能是引用数据类型的,value可以是任何的数据类型
let obj = {
    name: '张三',
    age: 25,
    sex: '男',
    score: [100, 98, 89],
    fn: function () {}
    };
console.log(obj); //=>{name: "张三", age: 25, sex: "男", score: Array(3), fn: ƒ}

1.新增或者修改属性和属性值

  • 操作属性的两种方式:
    • 1)对象.属性名 = 属性值 .在这里可以理解为“的”
    • 2)对象["属性名"] = 属性值
let obj = {
        sex: 0
    };
obj.name = 'js';//=>第一次是新增
obj['name'] = "jq";//=>第二次是修改
console.log(obj);//=>name:'jq'

2.获取对象中的属性名和属性值

  • 1)获取指定属性名的属性值
let obj = {
        sex: 0
    };
console.log(obj.sex); //=>0
console.log(obj['sex']); //=>0
  • 2)如果指定的属性不存在,获取到的属性值是undefined(不会报错)
let obj = {
        sex: 0
    };
console.log(obj['age']); //=>undefined
  • 3)获取当前对象中所有的属性名:返回结果是包含所有属性名的数组
let obj = {
        sex: 0
    };
console.log(Object.keys(obj)); //=>["sex"]

3.删除对象中指定的属性

  • 1)假删除:当前属性还存在,只不过属性值赋值为空
let obj = {
        sex: 0
    };
  obj.sex = null;
  console.log(obj);//=>{sex: null}
  • 2)真删除:彻底把属性从对象中移除掉
let obj = {
        sex: 0
    };
  delete obj.sex;                           
 console.log(obj);//=>{}

4.对象的属性名不能是引用数据类型值

  • 基于**对象['属性名']**的方式操作,需要保证属性名是一个值(字符串/数字/布尔等都可以),如果不是值而是一个变量,它会把变量存储的值作为对象的属性名进行操作
  • 基于 对象.属性名的方式操作,属性名就是点后面的
4.1.基于点的方式操作有自己的局限性,属性名不能是数字的,不能对象.数字属性,此时只能用对象[数字属性]

let n = 100;
let obj = {
    1: 100
};
console.log(obj.1);
//=>Uncaught SyntaxError: missing ) after argument list
4.2.其它非字符串格式作为属性名和字符串格式没啥区别
let n = 100;
let obj = {
    1: 100
};
console.log(obj[1]);//=>100
console.log(obj['1']);//=>100
4.3. obj对象内没有n属于新增 n是属性名可以是(数据格式、字符串)
let n = 100;
let obj = {

};
obj.n = 200; 
console.log(obj);//=> {n:200} 

obj['n'] = 200; 
console.log(obj);//=> {n:200} 
4.4.n本身是一个变量(n和'n'的区别:前者是一个变量,后者是一个字符串的值),它代表的是所存储的值100(是一个数字格式)
let n = 100;
let obj = {
   
};
obj[n] = 200; 
console.log(obj);//=> {100:200} 
console.log(obj[100]);=> obj[100]=200 
4.5.如果对象中没有m
let n = 100;
let obj = {
    1: 100
};
 obj[m] = 200;
 console.log(obj.m);
 //=>Uncaught ReferenceError: m is not defined m这个变量没有被定义
4.6 如果属性名是true,就是“true”
let n = 100;
let obj = {
    1: 100
};
obj[true] = 300; //=>{true:300}
 console.log(obj.true); //=>300
4.7.如果属性名是undefined,就是 'undefined'
let n = 100;
let obj = {
    1: 100
};
obj[undefined] = 400; //=>{undefined:400}
 console.log(obj.undefined); //=>400

5.对象的属性名不能是引用类型的

let n = {
    x: 100
};

let m = [100, 200];

let obj = {};

obj[n] = "js"; 
//=>obj[{x:100}] 但是对象不能作为属性名,需要把其转换为字符串
//=>{"[object Object]":"js" }

obj[m] = "jq";
//=>obj[[100,200]] =>{ "100,200":"jq" }

console.log(obj); 
//=>{[object Object]: "js", 100,200: "jq"}

五.数组

数组是特殊的对象

  • 1.它的属性名是数字,数字从零开始,逐级递增,每一个数字代表着当前项的位置 =>我们把这种数字属性名叫做“索引”
  • 2.默认有一个length属性存储数组的长度
let arr = [10, 20, 30];
console.log(arr[0], arr[1], arr[2]);//=>10 20 30
console.log(arr.length);//=>3
console.log(arr['length']);//=>3
let arr = [10.18, 0, 10, 25, 23];
arr = arr.map(parseInt);
console.log(arr);


/* 分析步骤:
arr = arr.map((item, index) => {
	// 循环遍历数组中的某一项就会触发回调函数
	// 每一次还会传递当前项和当前项的索引
}); 
//1.
parseInt('10.18',0(10))
 从字符串左侧第一个字符开始查找,找到符合[radix]进制的值(遇到一个不合法的,则停止查找),
 把找到的值变为数字,再按照把[radix]转换成为十进制的规则处理
	'10' -> 10
//2.
parseInt('0',1)   =>NaN
//3.
parseInt('10',2)
	10  把它看做2进制,最后转换为10进制
	1*2^1 + 0*2^0 => 2
//4.
parseInt('25',3)
	2  当做3进制转换为10进制
	2*3^0 => 2
//5.
parseInt('23',4)
    23 当做4进制转换为10进制
	2*4^1 + 3*4^0  => 11

==============知识点1====================
parseInt([value],[radix])
-> [radix]这个值是一个进制,不写或者写0默认都按照10处理
(特殊情况:如果value是以0X开头,则默认值不是10而是16)
-> 进制有一个取值的范围:2~36之间,如果不在这之间,整个程序运行的结果一定是NaN
-> 把[value]看做[radix]进制,最后把[radix]进制转化为十进制

================知识点2===================
把一个值转换为十进制
[位权值:每一位的权重,个位是0,十位是1...]

147(八进制) => 十进制
1*8^2 + 4*8^1 + 7*8^0

12.23(四进制)=> 十进制
1*4^1 + 2*4^0 + 2*4^-1 + 3*4^-2
4^0=1
4^-1=1/4
4^-2=1/(4*4)
*/