红宝书阅读笔记 第四章

变量 作用域 内存

es变量有两种不同类型数据:原始值和引用值
原始值:undefined、null、boolean、number、string、symbol
保存原始值的变量是按值访问
引用值:保存在内存中的对象,是由多个值构成的对象。JavaScript不能直接访问内存位置,因此不能直接操作对象所在的内存空间。操作对象时,实际上操作的是对象的引用(reference)而非实际对象本身。保存引用值的变量是按引用访问的(字符串是原始值,不是引用值)

费曼学习法:
我个人感觉引用值和指针应该是一个道理吧,一个引用值a指向
内存中的一个object,
b=a;
b也指向object,所以和指针很相似
书85图,很生动

传递参数

注意,JavaScript中所有函数的参数都是按值传递的,不同于其他语言
按值传参,值被复制到一个局部变量
按引用传参,值在内存中的位置会被保存到一个局部变量,在函数内部修改会影响到函数外部

证明为什是按值传递
//1
function setName(obj) {
    obj.name = 'zhaosi'
}
let person = new Object()
setName(person)
console.log(person.name)//'zhaosi'

//2
function setNameElse(obj) {
    obj.name = 'zhaosi'
    obj = new Object()
    obj.name = 'la'
}
let person = new Object()
setName(person)
console.log(person.name)//'zhaosi'

首先如果是按照引用传递,第二组应该返回la,所以不是按引用传递
而为什么按值传递可以改变person.name?
person被复制到obj,在函数内部obj和person都指向同一个对象,即使按值传进函数,obj也会通过引用访问对象。而外部变化因为obj指向的对象保存在全局作用域的堆内存上

百度中定义指针就是内存地址,我打算把它理解为指向某个对象的一个变量(说不清,就是那个意思,反正就是我是指针,我就是指向那里,a等于我,a就指向那里),按引用传递就是把那段内存地址给了obj,obj=new Object()就不指向那里了,而是指向新的对象;但是因为值传递,obj也是获得了指向那里的权利,或者可以使用这种指向的权利,但不能改变这个指向(你可以住你家房子,但房本是你爸妈名,你可以住那,也可以住在别处,但是房子始终不是你的)

确定类型

原始类型用typeof,否则全是object

s='aaa'
o = new Object()
m = null
h = function(){}
console.log(typeof s)
console.log(typeof o)
console.log(typeof m)
console.log(typeof h)

string
object
object
function

所以instanceof更适合引用值

o = new Object()
m = null
h = function(){}
console.log(o instanceof Object)
console.log(m instanceof Object)
console.log(h instanceof Function)
console.log([1,2] instanceof Array)


true
false
true
true

执行上下文与作用域

首先,我认为书中对上下文的解释、描述不够详细,反正我有点蒙
,上下文是context的翻译
https://zhuanlan.zhihu.com/p/348452188
https://www.jianshu.com/p/0d2fb2f2f52c
https://www.php.cn/js-tutorial-407137.html 讲的很好
费曼学习法:执行上下文我理解就是当前代码的运行环境,分为全局环境和函数环境
在执行前,引擎会构建全局上下文,将其放入上下文栈,所以栈底永远为全局上下文,直到关闭浏览器它才会出栈。然后将相应的函数上下文入栈。每个上下文对应一个变量对象,其包含了该上下文的变量、函数等。而到执行该上下文的时候,变量对象变为活动对象,各种属性可以访问。
执行上下文的属性:变量对象、作用域链、this指向
执行上下文的生命周期:创建、执行
创建阶段,生成变量对象、建立作用域链、确定this指向;建立函数名为属性名、函数所在内存地址引用为当前值的属性,建立变量名为属性名,undefined为属性值
执行阶段进行变量赋值等操作:变为活动对象,将变量赋值
作用域链,就是把上下文串起来的感觉,把前面的上下文存储在[[scope]]属性,再把当前的也放入其中,访问某个变量就从最上面以及上下文从上向下寻找
this:指向,执行前确定;
全局变量、单独调用function的this为window(非严格模式),否则为undefined;对象调用函数,指向对象;构造函数指向实例

变量声明

var添加到最近的上下文,如果不写var就添加到全局上下文
会有提升,对于变量和函数声明

let、const是块级作用域的声明
没有提升,不能重复声明在同一个作用域内

优先const let var

垃圾回收

执行环境负责在代码执行时管理内存
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Memory_Management 这个就够了

内存管理

将内存占用量保持在较小的值会有更好的性能,优化内存就是只保存必要的数据;如果数据不必要,就设为null,从而释放内存,叫做解除引用

function createPerson(name) {
    let localP = new Object()
    localP = name;
    return localP
}
//局部变量自动解除引用
let globalP = new createPerson('aaa')
//全局变量需要显式解除
globalP = null

隐藏类

尽量让两个对象共享同一个 构造函数,尽量避免先构造再补充

内存泄漏

内存泄漏 (Memory leak)是在 计算机科学 中,由于疏忽或错误造成程序未能释放已经不再使用的 内存 。. 内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费

尽量避免全局变量的声明
function setName() {
    name ='jake'
}

定时器悄悄导致内存泄漏
let name = 'jj'
setInterval(() => {
    console.log(name)
},100);//一直使用name,使其无法回收


小心闭包
let outer = function() {
    let name = 'jake'
    return function() {
        return name;
    };
}//name内存泄漏,只要outer存在,就不能清理name

静态分配与对象池

避免多余垃圾回收,减少浏览器垃圾回收次数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值