JS内存、变量与数据
内存
- 内存:内存条通电后产生可存储数据的空间(临时的)
- 分为:栈内存(存储变量)和堆内存(存储对象)
每块内存都有两个数据:内部存储的值和自身的地址
变量
变量:由变量名和变量值构成,在内存中占有一定的空间。在编程语言中,其实变量就是一个名字,用来储存和代表不同值的东西。
声明变量
1.var a=1
2.let b=2
3.const c=3 创建的值(可以理解为常量)不能修改并且必须在定义时初始化(赋值)
4.funtion fun()声明函数也相当于声明变量
5.class Person{}
创建类也相当于声明变量
6.import fun from'./index.js'
模块导入也相当于声明变量
7.Symbol创建唯一的值 let a=Symbol(100) let b=Symbol(100) console.log(a==b)//false
变量的作用域
变量的作用域就是定义这个变量的区域。在函数内部声明的为局部变量,只能在函数内部访问;全局变量拥有全局作用域,在当前文档任何代码位置都可以访问。
ES6中新增了代码块,在代码块中声明的变量将成为代码块所在函数的局部变量
if (true) {
var a=1
}
console.log(a)//1
if (true) {
let a=1
}
console.log(a)//Uncaught ReferenceError: a is not defined
- 变量提升:简单来说就是可以先使用变量稍后在声明而不会发生异常,这是因为将声明变量的语句提升到函数或者语句的最前面,提升后的变量默认值为undefined
var声明的变量会进行变量提升
console.log(a) //undefined
var a=1
在 ECMAScript 6 中,let(const)将不会提升变量到代码块的顶部。因为在变量被声明之前引用会抛出引用错误,这个变量从代码块一开始就处于“暂时性死区”直到变量被声明、
console.log(a) //t.html:11 Uncaught ReferenceError: Cannot access 'a' before initialization
let a=1
数据
存储在内存中代表特定的一些信息,本质上就是一串二进制数字。
特点:可传递,可计算。
数据类型:
- 基本数据类型:
- string :所有单引号 双引号 反引号包起来的东西
- number :常规数字和NaN(not a number)注意NaN和任何值包括自己都不相等!所以不能通相等来判断是否为有效数字
console.log(('aa') == NaN);//false
console.log(10 == NaN); //false
console.log(NaN == NaN);//false
isNaN:用来判断一个数是否为有效数字。true:不是有效数字 false:是有效数字。
在检测时会首先判断是否为number类型,如果不是将调用number()转换后,number类型再判断是否为NaN类型,如果是number类型则直接判断是否为NaN类型。
console.log(isNaN('aa'));//true 不是有效数字
console.log(isNaN(10));//false 是有效数字
+ boolean :true false
+ null(空对象指针)
- 初始化时赋值为null,代表是个空值
- 结束时赋值为null,让其变为垃圾对象,等待回收
let person={name:'jack'}
person=null//让person的指针指向null,空引用
+ underfined(未定义)
- 引用数据类型:
- object :任何一个对象都是由一个或者多个键值对组成的
- array
- function
null与underfined的区别:都代表没有
* null:声明并赋值,值为null(一般是手动设置为null,后期知道准确值再赋予);
例:
let num=null//let num=0;一般最好赋值为null,因为0不是空值,在栈内存中占有内存空间
num=13
* underfined:声明但是未赋值
例:
let num
console.log(num)//underfined
数据类型的转换
1、转换为string类型:
1)String()
`String(123)`
2)[val].toString()
console.log([].toString());//'' 当你尝试输出一个对象或一个变量时 JavaScript 会自动调用变量的 toString() 方法
console.log(({name: 'jack'}).toString());//[object Object] 因为Object.prototype.toString()不是用来转换为字符串的,而是用于检测数据类型
console.log(null.toString());//Uncaught TypeError null与underfined禁止直接toString(),但是是可以转换为'null' 'underfined'的
3)加法运算
其余的情况调用toString()方法一般都是在外面包裹上''
加法运算:任何类型与string类型进行相加,都会转换为string类型然后拼接,没有string类型则转换为number类型进行运算
let a=123
let b='hello'
console.log(a+b)//123hello
2、转换为number类型:
-
1、Number():遵循V8引擎的底层机制
- 1)如果是Boolean值,true和false将分别转换为1和0。
- 2)如果是数字值,只是简单的传入和返回。
- 3)如果是null值,返回0。
console.log(Number(null));//0
- 4)如果是undefined,返回NaN。
console.log(Number(undefined));//NaN
- 5)如果是字符串:
- ① 字符串中只包含数字时,转换为number类型
console.log(Number('123'));//number
- ② 字符串中包含有效的浮点格式,如“1.1”,则将其转换为对应的浮点数值(同样也会忽略前导零);
console.log(Number('123.1'));//123.1
- ③ 如果字符串是空的(不包含任何字符),则将其转换为0;
console.log('')//0
- ④ 如果字符串包含任意一个非有效字符,就将其他转换成NaN.
console.log(Number('123.1.1'));//NaN
`console.log(isNaN(Number('50px')));//true 字符串中有一个为非有效数字就会被转换为NaN - ⑤ 将引用数据类型转换为number,是基于tostring()方法将其转换为string类型后再转换为number,只要字符串中有非有效数字就为NaN
console.log(Number({}));//NaN
console.log(Number([]));//0 []---''---0
console.log(Number([12]));//12 [12]→'12'→12
console.log(Number([11, 23]));//[11,23]→'11,23→'NaN
- ① 字符串中只包含数字时,转换为number类型
-
2、parseInt():先转换为字符串然后从左向右查找
-
1)如果第一个非空格字符不是有效数字,parseInt()就会返回NaN; 用parseInt()转换空字符串会返回NaN、
console.log(parseInt(''))//NaN 没找到有效数字就是NaN
console.log(parseInt('s1'))//NaN
-
2)如果第一个非空格字符为有效数字,继续向下转换,直到遇到非数字字符,将其之前的转换
console.log(parseInt('50px'));//50
console.log(parseInt('50.5'));//50
-
- 如果字符串以"0x"开头且后跟数字字符,就会将其当作一个十六进制整数;
-
- 如果字符串以"0"开头且后跟数字字符,就会将其当作一个八进制整数;
-
-
3、parseFloat():
和parseInt类似,从第一个非空字符开始,直到遇到一个无效的浮点字符结束,所以字符串中的第一个小数点是有效的,而第二个小数点就是无效的了,因此它后面的字符串将被忽略。
console.log(parseFloat('50.5.5'));//50.5
- Number与parseInt的区别:
- Number:根据V8引擎的底层机制,不同的类型应该怎么转换
- parseInt:根据额外提供的机制,如果是字符串则根据如上的规则,不是字符串先将其转换为字符串然后按照规则进行转换
- Number与parseInt的区别:
console.log(Number('50.5px'));//NaN
console.log(parseInt('50.5px'));//50
console.log(parseFloat('50.5px'));//50.5
- 4、四则运算符
- 规则:
- 加法运算:有string类型时全部转换为string进行拼接;没有string类型转换为number类型进行加法运算
- 其他运算:全部转换为number类型然后进行运算,NaN和任何类型运算结果都是NaN类型
- 规则:
let a='hello'
let b=123
console.log(a-b)//NaN
综合运算:
console.log(10+null+true+[]+underfined+''中国'+null+[]+10+false)//11underfined中国null10false
① 10+null=10
②10+true=11
③11+[]=11+''='11'
④'11'+underfined='11underfined'...
3、转换为boolean类型:
-
转换规则:以下六种情况转为false,其余转换为true
1)0
2) ""
3)underfined
4) null
5)NaN
6)'false' -
转换方式:
- 1)Boolean()
- 2)!/!!:取反,先转换为boolean类型,然后取反
console.log(!1)//false console.log(!!1)//true
- 3)判断语句
if(''){ console.log('true') }else{ console.log('false' ) }
数据类型的检测
- 1、typeof [val]:用于检测数据类型的运算符
- 1)结果是一个字符串
- 2)字符串中包含对应的数据类型
- 3)能检测的数据类型:string number boolean object function undefined
- 4)局限性:
① null用typeof检测结果为object
console.log(typeof null)//object
② 不能区分具体的对象类型,全部为object
console.log(typeof [1,2])//object
练习:注意运算顺序从右向左
console.log(typeof typeof typeof [])//string
- 2、instanceof :用于检测当前实例是否属于某个类
- 3、constructor:基于构造函数检测数据类型
- 4、Object.prototype.toString.call():检测数据类型最佳方式
本节要点
1、
number():遵循c++底层原理:
字符串中有一个无效字符就位NaN
'' null转换为0
undedined转换为NaN
true为1 false为0
引用类型先调用toString()再转换为number类型:{}为NaN []为0 [12]为12 [12,34]为NaN
parseInt() parseFloat():先调用toString方法再从左向右侧查找是否有有效数字
isNaN():返回值为boolean类型,先转换为number类型,再判断是否为NaN
typeof():外面包裹上"",输出为字符串形式,能识别string number boolean undefined object(null 识别为object,不能区分具体的object类型)
2、
console:页面中是什么输出什么
alert prompt confirm输出字符串形式
数据传递---堆栈底层机制
基本数据类型
let a=12
let b=a
b=13
console.log(a);//12
引用数据类型
let n={
name:'jack'
}
let m=n
m.name='rose'
console.log(n.name);//rose
![](https://img2018.cnblogs.com/blog/1779093/201911/1779093-20191122180604117-933145484.png)
练习
- 1、
let n=[10,20]
let m=n
let x=m
m[0]=100
x=[30,40]
x[0]=200
m=x
m[1]=300
m[2]=400
console.log(n, m, x);
//[100, 20] [200, 300, 400] [200, 300, 400]
![](https://img2018.cnblogs.com/blog/1779093/201911/1779093-20191122214926716-938403874.png)
- 2、
var a='abc'+123+456;//'abc123456'
var b='456'-'123'//333
var c=100+true+21.2+null+undefined+'Tencent'+[]+null+9+false//'NaNTencentnull9false'
- 3、
重点:连等号a=b=1实际上执行顺序是 a=1 b=1
let a={
n:1
}
let b=a
a.x=a={
n:2
}
console.log(a.x);//underfined
console.log(b);//{n:1;{x:2}}
![](https://img2018.cnblogs.com/blog/1779093/201911/1779093-20191122221443545-1628318769.png)
- 4、如下会有什么问题?
let a={name:'tony'}
let b=a
a.x=b //对象中的属性值是对象本身,对象本身又有这个属性,无限循环会导致内存溢出
![](https://img2018.cnblogs.com/blog/1779093/201911/1779093-20191124150648302-1677079077.png)
- 5、深入理解
<div id="box"></div>
注意:只要堆内存中的值被修改,浏览器就会基于DOM映射机制把页面中的元素重新渲染
let box=document.getElementById('box')
box.style.backgroundColor='red' //背景颜色设置为红色
let aa=document.getElementById('box').style
aa.backgroundColor='yellow'//背景颜色为黄色
如下图表示:
![](https://img2018.cnblogs.com/blog/1779093/201911/1779093-20191124205558882-472485322.png)
![](https://img2018.cnblogs.com/blog/1779093/201911/1779093-20191124210342231-1234017347.png)