基本数据类型 & 引用数据类型
基本数据类型
- Number
- String
- Undefined
- Null
- Boolean
- Symol
引用数据类型
- Array()
- Date()
- Object()
- Regexp()
- Function()
-
基本数据类型:
- 基本数据类型的值直接存储在栈内存中
- 值与值之间是独立存在的,修改一个变量不会影响其他的变量
- 基本数据类型之间的比较,比较的是值
let a = 1 let b = a a = b + 2 console.log('a: ', a) // 1 console.log('b: ', b) // 3
-
引用数据类型:
- 对象是保存在堆内存中的
- 每创建一个新的对象,就会在堆内存中开辟出一个新的空间,而变量保存的是对象的内存地址(对象的引用),如果两个变量保存的是同一个对象引 用,当修改其中一个变量修改属性时,另一个也会受到影响。
- 引用类型数据的比较,比较的是地址
let obj = new Object() obj.name = '小明' let a = obj let b = obj // a.name = '小明' a = null console.log('a: ', a) console.log('b: ', b)
undefined
- 只有一个值,即undefined。声明一个变量未对其赋值 / 初始化,该变量的默认值为undefined
- undefined派生自null, undefined == null // true
null
- 只有一个值,即null。表示一个空对象指针
- 如果用一个变量来接收对象,可将该变量的初始值设为null,也方便判断
let obj = null
console.log(typeof obj) // object
NaN (not a number)
- 会返回NaN的操作
- 无穷大除以无穷大
- 给任意负数做开方运算
- 算数运算符与不是数字或无法转换为数字的操作数一起使用: ‘aaa’ - 123
- 字符串解析成数字:Number(‘aaaa’)
-
一个表达式中如果有减号 (-)、乘号 (*) 或 除号 (/) 等运算符时,JS 引擎在计算之前,会试图将表达式的每个分项转化为 Number 类型(使用 Number(x) 做转换)。如果转换失败,表达式将返回 NaN
-
加号 (+) 不会将其两边的变量转化为 Number 类型,这是因为JS表达式的执行顺序是按照运算符的优先级从左到右依次进行的,如果加号 (+) 两边的变量都是 Number 类型时,才会做数字相加运算,如果其中有一个变量是字符串,则会将两边都作为字符串相加
栈和堆
栈(stack)
- 存放基本数据类型,基本数据类型大小确定,栈可自动分配空间和释放
- 可存放:Number,String,Undefined,Null,boolean,Symol,对象指针
堆
- 存放引用数据类型,引用数据类型大小不确定,堆会动态分配空间但不会自动释放
- 可存放:Object,Array,Funtion
栈和堆的区别?
-
栈
- 存取速度比堆快
- 数据可共享
- 会自动释放
-
堆
- 堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(参数传递)。
创建对象是为了反复利用,这个对象将被保存到运行时数据区。
- 堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(参数传递)。
其他
- new 一个构造函数,会生成一个实例对象,该实例对象保存在堆中
- 声明变量时,会首先遍历当前的内存栈,看看有没有重名变量,有的话就返回错误。
构造函数与普通函数的区别
命名规范:
构造函数首字母大写,普通函数不需要。new运算符:
构造函数需要和new操作符配合使用,普通函数不需要。- 构造函数作为一个模板,配合new可以生成多个相同结构的实例对象。
- 构造函数面向对象,普通函数面向过程。
new运算符的内部实现?
function A() {
console.log('A')
}
var a = new A();
// 1. 创建一个新的对象
var o = new Object();
// 2. 将空对象的原型赋值为构造函数的原型
o._proto_ = A.prototype;
// 3. 将构造函数的内部this,指向新创建的空对象
A.call(o);
// 4. 返回
改变函数this指向
关键字:
call、apply、bind
-
共同点
-
都能改变函数的this指向
-
第一个参数,都是this要指向的对象
-
都可以利用后续参数传参
-
不同点
-
fun.call(obj,a,b),接收的是连续参数
-
fun.apply(obj,[a, b]) 接收的是数组参数
-
bind是返回对应函数,稍候调用,call和apply是立即调用
-
tips
-
call和apply是函数非继承的两个方法,也就是说每个函数都可调用
-
需要改变this指向的函数,在前面调用方法,方法内的第一个参数是this要指向的对象
闭包
- 函数内部嵌套一个函数,内部函数可以访问外部函数的作用域
- 作用:私有化变量,保护变量不受全局污染
- 缺点:不容易被回收,占用内存,滥用闭包容易造成内存泄漏
function foo(x){
let num = 10;
return function (y){
alert(y)
}
}
let aaa = foo(2);
aaa('这是一个闭包')
对象取值的两种方式
- 点调用
- []调用,键名要加引号
let obj = {
name: "ZYTX",
age: "Y13xG_4w",
gender: "AAAAAA.doc"
}
console.log('第一种:', obj.name)
console.log('第二种:', obj["name"])
逻辑运算符&& ||
&&:假前真后,||:假后真前
console.log(0 && 2) // 0
console.log(1 && 2) // 2
console.log(0 || 2) // 2
console.log(1 || 2) // 1
js跳出循环的三种方法,区别,使用场景
return
- 作用:终止函数的执行,并返回函数的值,
不会继续向下执行
- 使用场景:只能用于函数中,在for循环中使用会报错
break
- 作用: 用来退出循环或者退出一个switch语句,
不会继续向下执行
。 - 使用场景:普通循环,switch
continue
- 作用:
跳过本次循环,继续下一次的循环
- 使用场景:只能用在while语句、do/while语句、for语句、或者for/in语句的循环体内,在其它地方使用都会引起错误!
立即执行函数(IIFE)
(function sayHi(age) {
console.log('iife立即执行函数')
})()
(function sayHi(age) {
console.log('iife立即执行函数')
}())
如果使用标记的模板字符串,则第一个参数的值始终是字符串值的数组。 其余参数获取传递到模板字符串中的表达式的值!
!和!!的区别?
- !可将变量转换成boolean类型,null,undefined,空字符串, 0,“”取反都为true,其余都为false。
- !!常常用来做类型判断,在 !(变量)之后再做逻辑取反运算
!是逻辑与运算,并且可以与任何变量进行逻辑与将其转化为布尔值,!!则是逻辑与!取反运算,尤其后者在判断类型时代码简洁高效,省去了多次判断null、undefined和空字符串的冗余代码。
== 和===的区别?
- == 抽象相等, 转换类型比较
- === 严格相等, 先比较类型,再比较值
try…catch
作用:可以测试代码中的错误
- try:内部是需要运行的代码
- catch:当try的代码运行错误时,执行catch内部的代码,抛出错误信息
- finally:无论有无异常操作都会执行
try {
let num = 1;
if (num > 0) {
console.log('try')
}
} catch(err) {
console.log('catch: ', err)
}
finally {
console.log('finally')
}
sessionStorage()会话存储
sessionStorage.setItem('isValue', '设置会话存储') // 设置
sessionStorage.getItem('isValue') // 获取
sessionStorage.removeItem('isValue') // 删除
sessionStroage.clear() // 删除所有保存的数据