js高级程序设计变量、作用域与内存

变量

ECMAScript两种变量
原始值:简单数据
引用值:由多个数据组成的对象

原始值能直接访问到变量内存,而引用值只能通过引用来访问到变量内存

两种变量复制值

原始值:完全独立

let num1 = 5; 
let num2 = num1;

在这里插入图片描述

引用值:浅拷贝就是将引用指向新的值,深拷贝也是独立的

浅拷贝:

let obj1 = new Object(); 
let obj2 = obj1; 
obj1.name = "Nicholas"; 
console.log(obj2.name); // "Nicholas" 

在这里插入图片描述

函数传递参数

引用值传递给参数(即命名参数,局部变量),不是按引用传递的。(参数只能修改对象属性)

function setName(obj) { 
 obj.name = "Nicholas"; 
 obj = new Object(); 
 obj.name = "Greg"; 
} 
let person = new Object(); 
setName(person); 
console.log(person.name); // "Nicholas" 

确定类型

通过typeof来确定对象是什么类型的对象是不准确的,数组跟普通对象还null,都是返回Object

let s = "Nicholas"; 
let b = true; 
let i = 22; 
let u; 
let n = null; 
let o = new Object(); 
console.log(typeof s); // string 
console.log(typeof i); // number 
console.log(typeof b); // boolean 
console.log(typeof u); // undefined 
console.log(typeof n); // object 
console.log(typeof o); // object 

所以ECMAScript推出instanceof更准确来确定对象类型,能排除在typeof中检测原始值为object的情况,所有是Object实例化在object下都是true

let colors = []
console.log(person instanceof Object); //
console.log(colors instanceof Array); // true
console.log(colors instanceof Object) // true
console.log(pattern instanceof RegExp); //

作用域

上下文
上下文:每个变量或函数都有自己的上下文,且这个上下文都会有一个关联的变量对象,这个上下文定义的变量或函数都存在这个对象上,我们实际开发无法用代码显示这个关联对象,只有后台解析代码的时候才会有用到(上下文可以理解为身处的地方
在浏览器中,window对象为顶级全局上下文,这是对var定义的变量,但let跟const定义变量顶级全局上下文不在window上

上下文执行的过程,上级上下文执行到下级上下文,等到下级上下文代码执行完,又会回到上级上下文执行下面代码

作用域链
定义:当我们执行上下文时会创建一个作用域链,这个作用域链决定我们访问的变量对象,就近原则访问最近一个变量对象,逐级往上找变量对象

作用域链增强
作用域链增强:是指在执行到某些语句时,会在该语句所处的作用域链位置前端再创建一个上下文,执行完语句后销毁该上下文(但是其他类型的上下文得在关闭程序时才会被销毁,例如关闭浏览器)

作用域链主要有全局上下文跟函数上下文(第三种时eval()调用内部存在的第三种上下文)

作用域链增强的两种情况
with()语句
try{}catch(){}中的catch
这两个语句都会将括号里面数据作为上下文关联的变量对象,放在作用域链的前端

with语句是指定一个对象作为上下文关联的变量对象

catch则是创建一个新的变量对象,这个变量对象里面包含错误抛出的信息

变量的声明

1.var
var声明的变量会提升,在同一作用域下可以重复声明

2.let与const

let与const声明的变量会有块级作用域,且不能重复声明,且不会提升

const 声明的变量除了引用值,原始值不能更改值,不然会报错,一般推荐用这个来声明变量,除非后期需要更改这个变量

const如果声明的变量想要不能更改值,可以使用Object.freeze来固定其值

const aiqi = Object.freeze({})
aiqi.name="aiqi"
console.log(aiqi.name) //undefined

垃圾回收

1.标记处理
这种标记就是当运行上下文时被用到的变量会被添加标记,不需要用到会被添加待删除标记,此时你访问不到这个变量,当垃圾回收机制运行时,就会释放该变量占有的内存

2.引用计数
引用计数就是当你声明一个变量并给赋予引用值,这个引用值的计数即为1,当这个变量上的引用值被其他引用值覆盖,则上面的引用值计数为0,当引用值计数为0时,等下次垃圾回收程序运行,就会释放引用计数为0的值的内存

这种计数垃圾回收机制有一个问题,循环引用, 就是对象 A 有一个指针指向对象 B,而对象 B 也引用了对象 A,这种情况下两个对象的引用数永远都不会为0,所以这样会有大量的内存得不到释放

解决方法为,当你想要的程序结尾处,将这些会出现循环引用问题的变量赋予null,当垃圾回收程序运行时会将这些值为null的变量清除

3.性能
频繁触发垃圾回收机制会出现性能问题,为此需要合理对何时触发垃圾回收机制进行规定与处理

在 IE 中,window. CollectGarbage()方法会立即触发垃圾回收。
在 Opera 7 及更高版本中,调用 window. opera.collect()也会启动垃圾回收程序。

不推荐自己主动触发垃圾回收

4.内存管理

因为浏览器分配给js的内存比起桌面或其他应用分配给js的内存较小,当然这也是为了安全考虑,所以我需要在用完变量时给其设置值为null,这种操作成为解除引用

在内存管理方面我们应尽量使用const跟let,因为他们都有以块为作用域,且他们声明的变量在无用时会尽快让垃圾回收机制介入回收

隐藏类:用来与对象关联,以追踪对象的属性特征(谷歌采用)

function Article() { 
 this.title = 'Inauguration Ceremony Features Kazoo Band'; 
} 
let a1 = new Article(); 
let a2 = new Article(); 

在上面代码中,a1与a2共用一个隐藏类,但如果在声明完后,改变他们两个其中一个,就会将将两个变量对应不同的隐藏类,如果考虑性能我们应该尽量让他们共用一个隐藏类,所以尽量避免先创建在补充这种操作

上面问题的解决方法

function Article(opt_author) { 
 this.title = 'Inauguration Ceremony Features Kazoo Band'; 
 this.author = opt_author; 
} 
let a1 = new Article(); 
let a2 = new Article('Jake'); 

使用delete也会出现同个构造函数实例的两个变量对应不同隐藏类这种情况解决方法时将要删除的变量的值设为null即可

function Article() { 
 this.title = 'Inauguration Ceremony Features Kazoo Band'; 
 this.author = 'Jake'; 
} 
let a1 = new Article(); 
let a2 = new Article(); 
a1.author = null; 

5.内存泄漏
内存泄漏:是指内存在不用的时候一直存在

1.意外设置全局变量

function aiqi(){
	name = 'aiqi'
	//这种全局变量只要window对象不被清理它就会一直存在
}

2.定时器引起内存泄漏

let name = 'Jake'; 
setInterval(() => { 
 console.log(name); 
}, 100); 

//只要定时器一直在的话,name占用的内存就不会被清理

3.闭包引起内存泄漏

let outer = function() { 
 let name = 'Jake'; 
 return function() { 
 return name; 
 }; 
}; 

只要返回的函数存在就不能清理 name,因为闭包一直在引用着它。
假如 name 的内容很大(不止是一个小字符串),那可能就是个大问题了。

6.静态分配与对象池

合理分配内存,跟避免多次垃圾回收机制触发就能提高内存上的性能问题

减少垃圾回收触发:1.减少对象频繁初始化,2.数组初始化时应设置够用length的数组,这样可以避免垃圾回收多次动态分配触发(动态分配:如果不够用就删除这个数据,在创建个数组)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值