JS—Review
-
数据类型判断
typeof
:返回数据类型的字符串表达;可以区别数值、字符串、布尔值、undefined
、函数对象;不能区别null
和Object
以及Object
和Array
;instanceof
:专门用来判断对象的具体类型,Object
、Array
和函数对象;=== / ==:全等可以判断两个数据类型是否一致;可以判断
undefined
和null
(因为它们的类型唯一的值);-
undefined
和null
的区别:undefined
代表定义未赋值;null
代表了赋值了只是值为null
; -
什么时候给变量赋值为
null
?—初始赋值,指向的对象此时还没有确定;
—结束时,让指向的对象称为垃圾对象,被垃圾回收;
-
严格区别变量类型和数据类型:
—变量类型:变量内所存值的类型
- 基本(值)类型:保存基本类型数据的变量值;
- 引用类型:保存对象地址值;
—数据类型
- 基本类型;
- 对象类型;
-
-
数据—变量—内存
数据
—存储在内存中代表特定信息的,本质上是0101二进制数据;
—数据的特点:可读性、可运算和可传递的基本特性;
—万物皆数据,函数也是数据;
—程序中所有操作的目标:数据;
- 算数运算
- 逻辑运算
- 赋值运算
- 调用函数传参
- …
内存
—内存条通电后产生的临时的可存储数据空间;
—内存产生和死亡过程:内存条(集成电路板)—>通电—>产生一定容量的存储空间—>存储数据—>断电—>内存空间和数据全部消失;
—程序运行由硬盘加载到内存,进行运算;
—内存空间是临时的,而硬盘空间的永久的;
—声明变量和函数或者创建对象时,JS引擎会自动为此分配一定大小的内存来存放对应的数据;
—一块内存包含2个数据:内部存储的数据(一般数据/地址数据)、内存地址值数据;
—内存分类:
- 栈内存:全局变量和局部变量(空间比较小);
- 堆内存:对象(空间较大);
变量
可变化的量,由变量名和变量值组成;
一个变量对应一个小内存,变量名用来查找到对应的内存,变量值就是内存中保存的内容;
—变量在赋值的时候,只有在对象的情况下,才会赋值内存存储的地址值数据,其它直接赋值内存存储数据内容;
三者关系
内存用来存储程序运行需要操作的数据;
变量是内存的标识,通过变量找到对应的内存,进而进行操作(读/写)内存中的数据;
关于赋值与内存的问题
赋值运算
var a = xxx
中,a内存中到底保存的是什么?—xxx是基本数据,保存的就是该数据值;
—xxx是对象,保存的为对象的地址值;
—xxx是一个变量,保存变量的内存内容(可能是基本数据,也可能是地址值);
引用变量赋值问题
—多个引用变量指向同一个对象,即其保存的内存内容都是同一个地址值,通过一个引用变量修改对象内部数据,其他所有引用变量也为修改后的数据;
— 多个引用变量指向同一对象,当一个引用变量指向另一个对象,其他引用变量还是指向原来的对象,不会改变;
<script> var a = {age:18}; function fun(obj){ obj = {age:25}; } //这里调用过程中,a实参传递给形参,即a和obj指向同一对象 fun(a); //而函数中obj又指向其他对象,即a和obj最终指向的不是同一对象 //此时obj成为垃圾对象,函数一执行完毕,局部变量就会释放,obj不在指向对象,即其成为了垃圾对象 console.log(a.age);//返回18 </script>
在JS调用函数时传递变量参数时,是值传递还是引用传递?
只有值传递,没有引用传递,传递的都是变量的值,只是这个值可能是基本数据,也可能是地址(引用)数据;
如果后一种,地址传递看成引用传递,那么值传递和引用传递都快可以有;
JS引擎如何管理内存?
-
内存生命周期
分配内存空间,得到它得使用权—>存储数据,可以反复进行操作—>释放当前变量对应的内存空间;
函数内部的局部变量只有在函数执行的时候才会产生,函数执行完毕后,其内部的所有变量都会自动释放;变量所指向的对象会在后面某个时刻完成垃圾回收;
-
释放内存
局部变量:为执行函数分配的栈空间内存,函数执行完后自动释放;
对象:存储对象的堆空间内存,当内存没有引用指向时,成为垃圾对象,由垃圾回收机制进行回收;
全局变量不会自动释放内存;
-
对象
—多个数据的集合体(封装体),用来保存多个数据的容器就是对象;一个对象代表现实事物在编程中的抽象;
—对象可以对多个数据进行统一管理;
—对象的组成:
-
属性
—代表现实事物的状态数据;
—由属性名和属性值组成;
—属性名都是字符串类型,属性值是任意类型;
-
方法
—代表现实事物的行为数据;
—是特别的属性,属性值是函数;
—如何访问对象内部数据?
- .属性名:编码简单,但是有时不能用;
- [‘属性名’]:编码麻烦,但是通用;
- 当属性名不是合法的标识名或者属性名不确定时(变量),必须使用[‘属性名’]的方式;
-
-
函数
—能够实现特定功能的n条语句的封装体为函数,只有函数是可以执行的,其他类型的数据是不执行的;函数也是对象;
—函数可以提高代码复用,便于阅读和交流;
— 定义函数:函数声明、表达式;
—调用(执行)函数:
test()
直接调用函数new test()
new调用obj.test()
通过对象调用函数test.call/apply(obj)
临时让test()
成为obj
的方法进行调用;该调用方式可以让一个函数成为任意指定对象的方法进行调用;
回调函数
—特点:自定义的,没有直接调用,但最终它在特定条件或者时刻执行了;
—常见的回调函数:DOM事件回调函数(
this
指向发生事件的dom元素)和定时器回调函数(this
指向window
);ajax请求回调函数和生命周期回调函数(后面学); -
IIFE
—全称:Immediately-Invoked Function Expression立即调用函数表达式;也可以称为匿名函数自调用;
—作用:内部隐藏实现,不会污染外部(全局)命名空间;用它来编写js模块;
<script> //内部隐藏函数 (function(){ var a = 1; function test(){ cosole.log(++a); } window.$=function(){ return {test:test} } })() //全局调用函数 //其中$是一个函数,$执行后返回的是一个对象; $().test(); </script>
-
函数中的
this
—
this
是一个关键字,一个内置的引用变量;—所有函数内部都有一个变量
this
;—它的值是调用函数的当前对象;如果没有直接指定,
this
指向window
;—在定义函数时,
this
还没有确定,只有在执行时才动态确定(绑定)的;—如何确定
this
的值?test()
指向window
;p.test()
指向p
;new test()
指向新创建的对象;test.call(obj)
指向obj
;
-
JS语句中分号问题
参考知乎网址(尤雨溪):https://www.zhihu.com/question/20298345
—JS语句后面可以不加分号,但是在以下2种情况下不加分号会有问题:
- 小括号开头的前一条语句;例如立即调用函数表达式;
- 中括号开头的前一条语句;例如数组;
—解决方法:在行首加分号;
—比较有代表性的例子:vue.js库