数字字面量
字符串字面量
布尔字面量
undefined
null
引用类型分为如下几种
new Object()
new Array()
new RegExp()
new String()
new Number()
new Bollean()
new 自定义对象()
通过new的方式生成的对象
{},[],正则字面量。
var a = 'abc'
var b = 123
var c = true
var d = undefined
var e = null
var f = {
n: 'test'
}
f.n = null
var a = {
b: 123,
c: 'abc',
d: true,
e = null,
f = {
h: 'test',
j: {
k: 567 }
}
}
函数的内存使用
functionsay(){
var a = '测试' var b = {
c: 123 }
}
functionsay(){ var a = '测试' var b = {
c: 123 }
}
say()
String;
按值传递,互相不影响
Number
按值传递,互相不影响
Boolean
按值传递,互相不影响
Array
按引用传递,对当前内存指向同一地址:
解决方案:
1.采用es6中Set进行解耦(浅拷贝)
2.使用JSON进行解耦(深拷贝)
3.使用slice函数进行解耦(浅拷贝)
4.利用拓展运算符解决(浅拷贝)
const a2=[...a1]
const[...a2]=a1
Object
按引用传递,对当前内存指向同一地址
采用JSON (深拷贝)
Object.assign()克隆(浅拷贝)
Object.create() 创建(浅拷贝)
浅拷贝只针对单层结构的数组或对象,对于复杂结构的需要采用深拷贝
更多深拷贝 ,可以采用jquery,lodash等类库实现
或者自己实现,对结构一层一层遍历
function copy (obj) {
var newobj = obj.constructor === Array ? [] : {}
if(typeof obj !== 'object'){
return
}
for(var i in obj){
newobj[i] = typeof obj[i] === 'object' ?
copy(obj[i]) : obj[i]
}
return newobj
}
堆是动态分配内存,内存大小不一,也不会自动释放。栈是自动分配相对固定大小的内存空间,并由系统自动释放。
按引用传递的数据 再堆里面存储执行栈的指针
按值传递(call by value)是最常用的求值策略:函数的形参是被调用时所传实参的副本。修改形参的值并不会影响实参。按引用传递(call by reference)时,函数的形参接收实参的隐式引用,而不再是副本。这意味着函数形参的值如果被修改,实参也会被修改。同时两者指向相同的值。
按引用传递会使函数调用的追踪更加困难,有时也会引起一些微妙的BUG。
按值传递由于每次都需要克隆副本,对一些复杂类型,性能较低。两种传值方式都有各自的问题。
JS的基本类型,是按值传递的。
这两者的本质区别是:传递的数据类型不一样,值传递的是一个数值,而引用传递传递的是一个对象。
这个很明显会报错,因为没有创建变量a
这个结果 a 为 6 ,因为并没有调用函数 fn 所以函数找不到a ,a++ 并没有执行;
这个结果 a 为 6, 因为这个fn 执行后把 参数6传给了 函数里边的 a ,在函数内部开辟了一个空间 a = 6 ,然后经过a++; a 为 7 , 但结果并不会改变函数外面的 a 的值 ,所以结果还是 为6 .
在函数调用中,传递数值,我们成为“值传递”,
值传递特点:因为值传递的数据,地址和值是一个内容,所以在拷贝之后,改变新的,不会影响老的。
这个结果为7,因为这个fn执行后把参数6 传给了函数 fn 但是函数fn 里并没有接受这个参数的 形参, 这是函数内部并没有 a 的空间 ,所以会自动向外面搜索 找到a 的值 这时 是对外部 a 的修改,所以会改变 a 的值。
引用传递的特点:因为引用传递的数据,地址和值是两部分内容,所以在默认拷贝之后,仅仅拷贝了地址,没有拷贝值,此时两个地址指向了同一个值,那么就会造成修改新的,会影响老的,因为只有一个值。