原始值和引用值
除了object外的变量都是原始值,引用值就是对象,对象实际上保存在内存空间,而js不允许访问内存空间,因此在对对象进行任何操作时,操作的就是这个引用(reference)
- 用new时有区别
let name1 = "lpj";
let name2 = new String("lpj")'
name1.age = 19;
name2.age = 19;
console.log(name1.age);//undefined name1类型为string
console.log(name2.age);//19 name2类型为object
对象的“复制”
把引用值从一个变量赋给另一个变量时,其储存的值也会复制,区别在于,这个值是指向这个对象的指针传参只传值不传引用
function setName(obj){
obj.name = "lpj"
obj = new Object({
name:"hjy"
})
}
let person = Object()
setName(person)
console.log(person.name)//lpj而非hjy
在函数内部 obj和person都指向同一个对象,obj.name = "lpj"可以成功对这个对象进行操作,但是obj = new Object后,obj会被设置为一个新的引用值(新指针值),而非把这个引用指向一个新对象,这说明了传参时不会传引用,而只是传了个指针值。换句话说,跟c++不同,c++传一个数组变量进来,然后清空,那就是直接清空了。
上下文和作用域链 P89
变量或函数的上下文(即作用域)决定了他们能访问哪些数据以及他们的行为
每个上下文都有一个关联的变量对象,这个上下文中的所有变量和函数都存在这个对象上,这个以一定顺序排列链接变量对象的集合就称为作用域链,当前作用域的变量对象始终在链的最前
这样就可以按顺序去进入各个作用域的变量对象,从而访问数据。
举个例子说明作用域链规则
简单来说:变量对象就像一个个车间,里面按顺序装着不同机器和原料
(如果是全局变量对象Windows的话,那就是总工厂,各种车间(函数、对象)和各种总工厂原料(全局变量)都算是这个工厂的机器/原料(属性))
作用域链就像一条单向传送带连接不同车间,从小车间连向大车间最终连向总工厂
函数在创建和执行时发生了什么?待办什么是context,https://blog.csdn.net/konglingyuan/article/details/51441829
- 创建时:创建Function对象的内部属性[[scope]],包含了一个函数当前作用域中对象的集合,即当前作用域的变量对象(是吗),这个集合就是
函数的作用域链
它决定哪些数据可以被函数所访问,它将把自己完全复制到执行环境的作用域链中
- 执行时:为函数创建一个执行环境(execution context)内部对象
该对象与函数一一对应,会重复创建,执行完毕即销毁 - 为执行环境初始化作用域链,初始化为当前函数的[scope]](即
函数的作用域链)的对象
注意 这里的作用域链不是上面的
函数的作用域链,而是属于环境的,用于解析标识符
至此,活动对象创建完毕,成为函数运行时的一个变量对象
作用域链增强
指原本作用链前端对应的变量对象被换成了别的变量对象
try/catch的catch(创建新的变量对象)以及with语句(挪动变量对象到最前端)-
变量的作用域声明
- var
在函数里var name,外面访问不到,因为这个变量被添加到这个函数上下文的变量对象当中了但是如果不var,直接写name,会自动添加为全局变量,放在全局变量对象当中- 提升(有点抽象)
var name = "lpj"等价于name = "lpj"; var name
也就是说 var在执行的时候,这个声明会被提升到顶端(函数顶端或全局顶端),但是这个赋值却不会 举例:
- 提升(有点抽象)
- var
console.log(name)//undefined
var name = 'lpj'//声明被提升 但是赋值没被提升
let
块作用域:指最近的一堆{}就是一个块,这解释了为什么使用let可以防止for语句的i泄露出去标识符查找 P93
就是指沿着作用域链搜索这个变量的过程,如果在当前作用域找到了color = ''blue''查找即停止,在父级的color = "green"就不会生效
内存与性能P95
- 垃圾回收
每隔一段时间判定哪个变量不会再使用了,就释放它的内存- 标记清理、引用计数垃圾回收详细以及面试
- 性能
手动解除引用,即设为null,能确保下次垃圾回收时被成功回收而非马上被回收- 函数内局部变量会自动被解除引用
- 由于let和const以块(而非函数)为作用域,可能会更早地接触引用从而回收
- 隐藏类的利用
-
内存泄露(待办)https://www.cnblogs.com/princeness/p/11664978.html
内存泄露是指你用不到(访问不到)的变量,依然占居着内存空间,不能被再次利用起来。
在某些环境中,这个闭包会导致内存泄露,即largeObject不能被及时回收
function outer() {
var largeObject = LargeObject.fromSize('100MB');
return function() {
console.log('inner');
};
}
var inner = outer();
遗留问题:闭包为什么能会使内存常驻,为什么能解决这里最后for循环的问题

