Yapei Li

专注于前端领域

0%

js基础2、变量、常量、数据类型分类、检测、转换

变量和常量

变量variable:值是可以变的;

变量不是具体的值,只是一个用来存储具体值的容器或者代名词,因为它存储的值可以改变,所以称为变量,

变量其实只是一个无意义的名字,他代表的意义都是其存储的那个值;

一个变量只能代表一个值

创建变量

1、var
2、function创建函数(函数名也是变量,只不过存储的值是函数类型而已)
3、let
4、const创建ES6常量
5、import基于ES6的模块规范导出需要的信息
6、class基于ES6创建类

var 和let的区别

1、var有变量提升,let没有变量提升
2、let不能重复命名
3、全局作用域下let声明的变量和window没关系
4、let存在暂时性死区
5、let能形成块级作用域

1
2
3
4
5
//语法:
var 变量名=变量值
let 变量名=变量值
const 变量名=变量值
function 函数名(){}

常量:值是不可变的,任何一个具体的数据值都是常量,例如12就是一个常量

不能给一个常量重新赋值

1
2
3
4
5
6
7
8
//var 变量名=变量值;
var num=12;
//ES6中定义变量是 let
let num2=12;

//定义常量
const num3 =12;
num3 = 13; //报错 : Uncaught TypeError: Assigjnment to constant variable 常量存储的值是不能修改的

数据类型分类和检测

JS中的数据类型

基本数据类型(值类型)

  • number:数字
  • string :字符串(单引号双引号都行)
  • boolean:布尔
  • null 空对象指针
  • undefined 未定义

引用数据类型

  • object 对象数据类型
    • {} 普通数据类型
    • [] 数组
    • /^$/ 正则
    • 日期对象
    • Math数学对象
    • 。。。
  • function 函数数据类型
  • ES6中新增一个特殊数据类型:Symbol,唯一的值

数据类型检测

typeof :检测数据类型的运算符,返回的结果是字符串

返回的结果是字符串,字符串中的内容证明了这个值是属于什么类型的

1、基础数据类型除了typeof null'object'以外,typeof都是自己的数据类型
2、引用数据类型分为:对象数据类型函数数据类型
3、对象数据类型分为:{} 普通对象型,[] 数组, /^$/ 正则日期对象
4、对象数据类型nulltypeof都是‘object’
5、函数数据类型typeof都是‘function’

局限性:

1、typeof null 不是'null' 而是 'object' :因为null虽然是单独的一个数据类型,但是它原本意思是空对象指针,浏览器用typeof 检测 的时候会把它当做对象来检测
2、使用typeof 无法具体细分出 到底是数组还是正则 ,因为返回结果 都是 'object'

面试题:
1
2
3
typeof typeof  []   => string
//1、typeof [] =》 'object'
//2、typeof 'object' =》 string
1
2
3
4
5
6
7
8
9
10
11
12
13
typeof 12 => 'number'

var num=13;
typeof num => 'number'
typeof 'aaa'=> 'string'
typeof true => 'boolean'
typeof null => 'object' //typeof 的bug
typeof undefined => 'undefined'

typeof {aaa:'aaa'} => 'object'
typeof [] => 'object'
typeof /^$/ => 'object'
typeof function (){} => 'function'

XX instanceof YY,检测当前实例是否属于某个类

解决了typeof无法识别是数组还是正则的问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Fn(){

}
var f=new Fn();

console.log(f instanceof Fn) //=>true

console.log([] instanceof Array) //=>true
console.log(/^$/ instanceof Fn) //=>false

[] instanceof Object //true
/^$/ instanceof Object //true
/^$/ instanceof Array //false
[] instanceof Array //true
/^$/ instanceof RegExp //true

function aaa(){}
console.log(aaa instanceof Function) //true

xxx.constructor: 获取当前实例的构造器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var test=1;
//var test=[1];
//var test='1';

if (test.constructor==Array)
{
console.log("This is an Array");
}
if (test.constructor==Boolean)
{
console.log("This is an Boolean");
}
if (test.constructor==Date)
{
console.log("This is an Date");
}
if (test.constructor==String)
{
console.log("This is an String");
}
if (test.constructor==Number)
{
console.log("This is an Number");
}

var test=[1];
console.log(test.constructor == Object); //false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function employee(name,job,born) {
this.name=name;
this.job=job;
this.born=born;
}

var bill=new employee("Bill Gates","Engineer",1985);
console.log(bill.constructor);
//结果
function employee(name,job,born) {
this.name=name;
this.job=job;
this.born=born;
}

Object.prototype.toString.call : 获取当前实例的所属类信息

Object.prototype.toString方法,判断某个对象之属于哪种内置类型。

分为nullstringbooleannumberundefinedarrayfunctionobjectdatemath

判断基本类型:
1
2
3
4
5
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call("abc");// "[object String]"
Object.prototype.toString.call(123);// "[object Number]"
Object.prototype.toString.call(true);// "[object Boolean]"
判断原生引用类型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//**函数类型**
Function fn(){
console.log(“test”);
}
Object.prototype.toString.call(fn); // "[object Function]"

//**日期类型**
var date = new Date();
Object.prototype.toString.call(date); // "[object Date]"

//**数组类型**
var arr = [1,2,3];
Object.prototype.toString.call(arr); // "[object Array]"

//**正则表达式**
var reg = /[hbc]at/gi;
Object.prototype.toString.call(reg); // "[object RegExp]"

//判断原生JSON对象
var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON);
console.log(isNativeJSON);// 输出结果为”[object JSON]”说明JSON是原生的,否则不是;

//**自定义类型**
function Person(name, age) {
this.name = name;
this.age = age;
}
var person = new Person("Rose", 18);
Object.prototype.toString.call(arr); // "[object Object]" //能准确判断person是Person类的实例

字符串

js当中单引号双引号包起来的都是字符串:"aa" =>string ; '[1,2,3]' => string

常用方法:

charAt

chartCodeAt

substr

substring

slice

toUpperCase

toLowerCase

indexOf

lastIndexOf

split

replace

match

其他类型转换为字符串:除了普通对象都是直接加引号(数组也很特殊)

发生情况

1、基于alertconfirmpromptdocument.write等方法输出内容的时候,会把输出的值转化为字符串然后输出,这些输出答案必须加单引号
2、基于+进行字符串拼接的时候
3、把引用数据类型值转化为数字的时候,首先会转化为字符串,然后再转换为数字
4、给对象设置属性名,如果不是字符串,首先转化为字符串,然后再当做属性存储到对象中(对象的属性名只能是数字或者字符串
5、手动调用toString、toFixed、join、String等方法的时候,也是为了转化为字符串

1
2
3
4
5
var n=Math.PI;    =>  3.141592654
n.toFixed(2) => '3.14'

var arr=[12,23,34]
arr.join('+') => '12+23+34'

转换规律

1、浏览器默认转换`的时候调用的都是 toString
2、除了普通对象都是直接加引号(数组也很特殊)
  • 1 ->'1' (手动调用toString不行);
  • NaN -> 'NaN' ;
  • null -> 'null' (手动调用toString不行) ;
  • [] -> '' ;
  • [12] -> '12' ;
  • [12,13] -> '12,13' ;
  • function fn(){} -> 'function fn(){}' ;
  • new Date().toString() -> '2018.08.27'
3、不管是啥样的普通对象,最终结果都是'[object Object]'

普通对象:{ name:'name'} -> '[object Object]'

数据类型 例子 return
字符串 “foo”.toString() “foo”
数字 1.toString() Uncaught SyntaxError: Invalid or unexpected token
布尔值 false.toString() “false”
undefined undefined.toString() Uncaught TypeError: Cannot read property 'toString' of undefined
null null.toString() Uncaught TypeError: Cannot read property 'toString' of null
String String.toString() “function String() { [native code] }”
Number Number.toString() “function Number() { [native code] }”
Boolean Boolean.toString() “function Boolean() { [native code] }”
Array Array.toString() “function Array() { [native code] }”
Function Function.toString() “function Function() { [native code] }”
Date Date.toString() “function Date() { [native code] }”
RegExp RegExp.toString() “function RegExp() { [native code] }”
Error Error.toString() “function Error() { [native code] }”
Promise Promise.toString() “function Promise() { [native code] }”
Obejct Object.toString() “function Object() { [native code] }”
Math Math.toString() “[object Math]”
手动调用toString不行的情况
1
2
3
4
5
6
7
8
9
10
11
12
1.toString()  //报错

let a=1;
console.log(a.toString()); //‘1’

let a=null;
console.log(a.toString()); //报错
console.log(null.toString()); //报错

let a=undefined;
console.log(a.toString()); //报错
console.log(undefined.toString()); //报错

number数字

JS 除了常规数字 增加了一个number类型的数据 NaN

Number(),把其它数据类型的值转换为number类型的

1、字符串转数字,从左到右只要出现任何一个非有效数字字符,最后结果都是NaN

Number(‘12’) => 12

Number(‘12px’) => NaN

Number(‘’) => 0

Number(‘ ‘) => 0 Space

Number(‘\n’) => 0 换行符

Number(‘\t’) => 0 制表符(Tab)

2、布尔转数字

  • Number(true) => 1
  • Number(false) => 0

3、其他转数字

  • Number(null) =>0
  • Number(undefined) => NaN
  • Number(‘’) => 0
  • Number(NaN) => NaN

4、引用数据类型转数字,首先需要把引用数据类型转换为字符串

引用数据类型转换为number,首先需要把引用数据类型转换为字符串(用toString),再把字符串转换为number 即可;

数组:[] => ‘’ => 0; [12] => ‘12’ => 12; [12,23] => ‘12,13’ => NaN;

对象Number({aaa:’aaa’}) => NaN : Number({}) => ‘[object Object]’ => NaN

正则:/^$/.toString() -> ‘/^$/‘ ->NaN

1
2
3
4
5
6
7
8
9
10
Number('12')  =>  12
Number('12px') => NaN

Number(true) => 1
Number(false) => 0
Number(null) => 0
Number(undefined) => NaN

Number([]) => Number(String([])) => Number('') => 0

parseInt():转化为整数

1、只使用一个参数时,从左到右依次查找有效数字字符,直到遇到非有效数字字符为止

把其他数据类型的值转换为number,把一个字符串中的整数部分解析出来

提取规则:从左到右依次查找有效数字字符,直到遇到非有效数字字符为止(不管后面是否还有,都不找了),把找到的转换为数字;parseInt(‘12px13’) => 12;parseInt(‘px12’) => NaN

识别不了小数点后面的数字 转化为整数

转化的不是字符串时先转化为字符串

1
2
3
4
5
Number('12px')  =>  NaN
parseInt('12px') => 12
parseInt('12px13') => 12
parseInt('12.5px') => 12
parseInt('px12') => NaN

2、使用两个参数时parseInt(string, radix),radix :2 ~ 36

参数 描述
string 必需。要被解析的字符串。
radix 可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN

示例:

parseInt(17, 8) 相当与8进制的17转为 10进制的数据
1
2
3
1          7
81次方 80次方
1*8 +7*1180次方)=15
parseInt(157, 8) 8进制157 转10进制
1
2
3
1           5             7
82次方 81次方 80次方
1*8*8 + 5*8 +7*1180次方)= 111
parseInt(154, 6) 6进制154 转10进制
1
2
3
1           5          4
62次方 61次方 60次方
1*6*6 + 5*6 + 4*1 = 70

依次类推

8进制 一个bit最大到 7
2进制 一个bit最大到 1
10进制 一个bit最大到 9
超出的都不是有效字符(可以当做不存在)

8进制18 =》 余数8超出是无效的 删除后 只剩 1, 相当于 8进制的1转10进制 =》1

1
2
3
4
5
6
7
8
let arr=[1,2,3]
console.log(arr.map(parseInt)); //[ 1, NaN, NaN ]

//parseInt分别接收到:
parseInt(1,0) //当radix是0时 默认以10位基数 1
parseInt(2,1) //当radix是小于 2 或者大于 36,则 parseInt() 将返回 NaN
parseInt(3,2) //当radix是2 是以2进制计算 此时只有01是有效字符

parseFloat():转化为小数,可以识别小数点

在parseInt的基础上可以识别小数点,把一个字符串中小数(浮点数)部分解析出来

1
2
3
parseInt('12.5px')    =>  12
parseFloat('12.5px') => 12.5
parseFloat('px12') => NaN

NaN:

not a number :不是一个有效的数字,但是属于number类型

1、typeof NaN => ‘number’

2、NaN和任何其他值都不相等包括他自己

NaN === NaN => false ;

3、NaN加任何数据(除了字符串)结果都是NaN

isNaN:检测是否为有效数字的唯一方法

用来检测是否是非有效数字,如果是非有效数字,返回结果是true;是数字false

检测是否为有效数字的唯一方法

当我们使用isNaN检测值的时候,如果检测的值不是number数据类型的时候,浏览器会默认的把值先转换为number类型(使用Number()),然后再去检查

isNaN(‘12’) =》 false

数字类型中只有NaN不是有效数字,其余都是有效数字

isNaN检测是false(是数字的):truefalsenull纯数字字符串只有一项并且为数字的数组,因为这几个调用Number结果都是数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   isNaN([])   =>  isNaN(Number([]))   =>  isNaN(Number(toString([])))   =>  isNaN(Number('')) =>  isNaN(0)    => false
isNaN(0) => false 是数字
isNaN(NaN) => true 不是数字

isNaN('12') => false 是数字,我们使用isNaN检测值的时候,如果检测的值不是number数据类型的时候,浏览器会默认的把值先转换为number类型(使用Number()),然后再去检查

isNaN(true) =>isNaN(Number(true))=>isNaN(0) => false 是数字
isNaN(false) => false 是数字

isNaN(null) => false 是数字
isNaN(undefined) => isNaN(Number(undefined)) => isNaN(NaN) true 不是数字

isNaN([12]) => false 是数字
isNaN([12,13]) => true 不是数字
isNaN({aaa:9}) => true 不是数字
isNaN(/^$/) => true 不是数字
isNaN(function(){}) => true 不是数字

布尔值(JS真假)

只有两个值:true false

Boolean():把其它数据类型转换为布尔数据类型

假(false)只有以下五种: 0 、 NaN、空字符串、null、undefined

真(true):除了以上五种都是true

其他值转化为布尔值

只有“0、NaN、‘’、null、undefined”五个值转化为false,其余都转化为true

基于!/!!/Boolean等方法转换

条件判断中的条件都会转换为布尔值

1
2
3
4
5
6
7
if(n){
//=>把n的值转化为布尔值验证条件真假
}

if('3px' + 3){
//=>先计算表达式结果为'3px3',把结果转化为布尔值true,条件成立
}

!,取反,先把值转换为布尔类型值,然后取反

叹号在JS中还有一个作用叫取反,先把值转换为布尔类型值,然后取反

!1 => false; ![] => false;!0 => true

!!,取两次反相当于没有取反

在一个叹号取反的基础上再取反 ,取两次反相当于没有取反,但是已经把其他的类型转换为了布尔类型,效果和Boolean一样 : !![] => true; !!null =>false ; !!1 => true;

null 和undefined

null: 空,没有
undefined:未定义 没有

‘’:空字符串 没有
0:也可以理解为没有

undefined:未定义

1、变量提升阶段只声明不定义:默认值 undefined
2、严格模式下:没有明确的执行主体,this就是undefined
3、对象没有这个属性名,属性值是undefined
4、函数定义形参不传值:默认是undefined
5、函数没有返回值(没有return或者 直接return;),默认返回就是 undefined

null:空

1、手动设置变量的值或者对象某一个属性值为null(此时不赋值,后边会赋值)
2、在JS的DOM元素获取中,如果没有获取到指定的元素对象,结果一般都是null
3、Object.prototype.__proto__的值也是null
4、正则捕获的时候,没有捕获到结果,默认也是null

document.parentNode => 有这个属性但是找不到 是 null

document.parentnode => 没有这个属性 是 undefined(parentnode是不存在的 )

空字符串和null的区别

都是去种树

空字符串属于挖了坑没有种,

null 是坑都没挖

空字符串相对于null来说开辟了内存,消耗了一点点性能

null和undefined的区别

null 一般都是暂时没有赋值,预期中以后会有

在js中null一般是手动先赋值值为null,后期再给其赋具体值

undefined:完全没在预料之内,一般都不是人为手动控制的,大部分都是浏览器自主为空;后面可以赋值也可以不赋值

普通对象object

var obj={name:’aa’,age:19}

每一个对象都是由0到多组 属性名(key、键):属性值(value、值)组成的,或者说是由多组键值对组成的,每一组键值对中间用逗号分隔

属性是用来描述当前对象特点特征的,属性值是对这个特征的描述

对象的属性名只能是字符串或者数字格式的,存储的属性值可以是任何的数据类型

当我们存储的属性名不是字符串也不是数字的时候,浏览器会把这个值转化为字符串(toString),然后 进行存储;obj[{}]=300 把{}.toString()后的结果作为属性名存储进来obj[‘[object Object]’]=300

obj[{}] =>获取的时候也是先把对象转换为字符串’[object Object]’,然后获取之前存储的300

操作:

属性名.属性值;忽略了属性名的单双引号,obj.name

属性名[属性值],不能忽略单双引号,obj[‘name’]

如果属性名是数字:

obj.0 不行 ; 只能用中括号方式获取:obj[0] 或者 obj[‘0’],obj[0] === obj[‘0’]

如果操作的属性名在对象中不存在,获取的结果是undefined

设置、修改

一个对象的属性名是不能重复的,如果之前存在就是修改属性值的操作,如果不存在就是新设置属性的操作:obj.aaa=18;obj[‘aaa’]=19;

删除:delete obj.aaa

假删除:让其属性值为null,但是属性还在对象中:obj.aaa=null
真删除:把整个属性都在对象中移除,delete obj.aaa;

1
2
3
4
5
6
7
var obj={name:'aaa',age:18}
var name='bbb'


obj.name => 'aaa' 取name属性
obj['name'] => 'aaa' 取name属性
obj[name] => undefined'bbb'属性 此处的name是一个变量

数组

var arr=[12,13]

中括号包裹起来,包含0到多项内容

数组对象的属性名是数字,我们把数字属性名称为当前对象的索引

获取

arr[0]

arr[‘0’]

arr.0 不行 报错

正则

var reg=/^$/

由元字符组成一个完整的正则

Symbol

创建出来的是唯一的值,没有和他相等的

1
2
3
4
5
6
7
8
9
var a=Symbol('aaa')

console.log(a) //Symbol('aaa')

var b=Symbol('aaa')

console.log(b) //Symbol('aaa')

console.log(a==b) //false