变量和常量
变量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 | //语法: |
常量:值是不可变的,任何一个具体的数据值
都是常量,例如12就是一个常量
不能给一个常量重新赋值
1 | //var 变量名=变量值; |
数据类型分类和检测
JS中的数据类型
基本数据类型(值类型)
number
:数字string
:字符串(单引号双引号都行)boolean
:布尔null
空对象指针undefined
未定义
引用数据类型
object
对象数据类型{}
普通数据类型[]
数组/^$/
正则- 日期对象
Math
数学对象- 。。。
function
函数数据类型- ES6中新增一个特殊数据类型:
Symbol
,唯一的值
数据类型检测
typeof :检测数据类型的运算符,返回的结果是字符串
返回的结果是字符串,字符串中的内容证明了这个值是属于什么类型的
1、基础数据类型
除了typeof null
是'object'
以外,typeof
都是自己的数据类型
2、引用数据类型
分为:对象数据类型
和函数数据类型
3、对象数据类型
分为:{} 普通对象型
,[] 数组
, /^$/ 正则
,日期对象
等
4、对象数据类型
和null
的typeof
都是‘object’
5、函数数据类型
的typeof
都是‘function’
局限性:
1、typeof null 不是'null' 而是 'object'
:因为null
虽然是单独的一个数据类型,但是它原本意思是空对象指针
,浏览器用typeof
检测 的时候会把它当做对象来检测
2、使用typeof
无法具体细分出 到底是数组
还是正则
,因为返回结果 都是 'object'
面试题:
1 | typeof typeof [] => string |
1 | typeof 12 => 'number' |
XX instanceof YY
,检测当前实例是否属于某个类
解决了typeof无法识别是数组还是正则的问题
1 | function Fn(){ |
xxx.constructor: 获取当前实例的构造器
1 | var test=1; |
1 | function employee(name,job,born) { |
Object.prototype.toString.call : 获取当前实例的所属类信息
Object.prototype.toString
方法,判断某个对象之属于哪种内置类型。分为
null
、string
、boolean
、number
、undefined
、array
、function
、object
、date
、math
判断基本类型:
1 | Object.prototype.toString.call(null); // "[object Null]" |
判断原生引用类型:
1 | //**函数类型** |
字符串
在
js
当中单引号
和双引号
包起来的都是字符串:"aa" =>string
;'[1,2,3]' => string
常用方法:
charAt
chartCodeAt
substr
substring
slice
toUpperCase
toLowerCase
indexOf
lastIndexOf
split
replace
match
…
其他类型转换为字符串:除了普通对象都是直接加引号(数组也很特殊)
发生情况
1、基于alert
、confirm
、prompt
、document.write
等方法输出内容
的时候,会把输出的值转化为字符串然后输出,这些输出答案必须加单引号
2、基于+
进行字符串拼接
的时候
3、把引用数据类型值
转化为数字
的时候,首先会转化为字符串
,然后再转换为数字
4、给对象设置属性名
,如果不是字符串,首先转化为字符串
,然后再当做属性存储到对象中(对象的属性名只能是数字或者字符串
)
5、手动调用toString、toFixed、join、String
等方法的时候,也是为了转化为字符串
1 | var n=Math.PI; => 3.141592654 |
转换规律
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 | 1.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 | Number('12') => 12 |
parseInt():转化为整数
1、只使用一个参数时,从左到右依次查找有效数字字符,直到遇到非有效数字字符为止
把其他数据类型的值转换为number,把一个字符串中的整数部分解析出来
提取规则:
从左到右依次查找有效数字字符,直到遇到非有效数字字符为止
(不管后面是否还有,都不找了),把找到的转换为数字;parseInt(‘12px13’) => 12;parseInt(‘px12’) => NaN识别不了小数点后面的数字 转化为整数
转化的不是字符串时先转化为字符串
1 | Number('12px') => 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 | 1 7 |
parseInt(157, 8) 8进制157 转10进制
1 | 1 5 7 |
parseInt(154, 6) 6进制154 转10进制
1 | 1 5 4 |
依次类推
8进制 一个bit最大到 7
2进制 一个bit最大到 1
10进制 一个bit最大到 9
超出的都不是有效字符(可以当做不存在)
8进制18 =》 余数8超出是无效的 删除后 只剩 1, 相当于 8进制的1转10进制 =》1
1 | let arr=[1,2,3] |
parseFloat():转化为小数,可以识别小数点
在parseInt的基础上可以识别小数点,把一个字符串中小数(浮点数)部分解析出来
1 | parseInt('12.5px') => 12 |
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
(是数字的):true
,false
,null
,纯数字字符串
,只有一项并且为数字的数组
,因为这几个调用Number
结果都是数字
1 | isNaN([]) => isNaN(Number([])) => isNaN(Number(toString([]))) => isNaN(Number('')) => isNaN(0) => false |
布尔值(JS真假)
只有两个值:true false
Boolean():把其它数据类型转换为布尔数据类型
假(false)只有以下五种: 0 、 NaN、空字符串、null、undefined
真(true):除了以上五种都是true
其他值转化为布尔值
只有“0、NaN、‘’、null、undefined”五个值转化为false,其余都转化为true
基于!/!!/Boolean
等方法转换
条件判断中的条件都会转换为布尔值
1 | if(n){ |
!,取反,先把值转换为布尔类型值,然后取反
叹号在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 =>
有这个属性
但是找不到 是 nulldocument.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]’]=300obj[{}] =>获取的时候也是先把对象转换为字符串’[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 | var obj={name:'aaa',age:18} |
数组
var arr=[12,13]
中括号包裹起来,包含0到多项内容
数组对象的属性名是数字,我们把数字属性名称为当前对象的索引
获取
arr[0]
arr[‘0’]
arr.0 不行 报错
正则
var reg=/^$/
由元字符组成一个完整的正则
Symbol
创建出来的是唯一的值,没有和他相等的
1 | var a=Symbol('aaa') |