变量、作用域和内存问题
一、基本类型和引用类型的值
-
基本类型:
- Undefined
- Null
- Boolean
- Number
- String
这5种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值
-
引用类型:
引用类型的值是保存在内存中的对象。
JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。
在操作对象时,实际上是操作对象的引用而不是实际的对象
为此,引用类型的值是按引用访问的
-
引用类型可以动态添加属性但是基本类型不行
var person = new Object() person.name = 'Nike' alert(person.name) -
复制变量值
-
基本类型原变量与复制后的变量是完全独立的
-
引用类型原变量与复制后的变量将引用同一个对象:复制后的变量的值实际上是一个指针,而这个指针指向存储在堆中的对象。
如果改变其中一个变量就会影响另一个变量var obj1 = new Object() var obj2 = obj1 obj1.name = 'Nike' alert(obj2.name) // 'Nike'
-
-
传递参数:
- 基本类型值的传递如同基本类型变量的复制一样
- 引用类型值的传递如同引用类型变量的复制一样
function addTen(num) { num += 10 return num } var count = 20 var result = addTen(count) alert(count) // 20 // 基本类型的变量传入后就变成了局部变量 alert(redult) // 30function aetName(obj) { obj.name = 'Nike' } var person = new Object() setName(person) // 全局对象 alert(person.name) // 'Nike'function setName(obj) { obj.name = 'Nike' obj = new Object() obj.name = 'Greg' } var person = new Object() setName(person) // 函数内部重写obj时,这个变量引用的就是一个局部变量 // 这个局部变量在函数执行完毕后会被立即销毁 alert(person.name) // 'Nike' -
检测类型
- typeof(检测基本类型时)
var s = 'Nike' console.log(typeof s) // 结论为字符串的形式:'string' var b = true console.log(typeof b) // 结论为字符串的形式:'boolean' var d = 22 console.log(typeof d) // 结论为字符串的形式:'number' var u console.log(typeof u) // 结论为字符串的形式:'undefined' var n = null console.log(typeof n) // 结论为字符串的形式:'object' var o = new Object() console.log(typeof o) // 结论为字符串的形式:'object' var f = function() { let c = 1 } console.log(typeof f) // 结论为字符串的形式:'function' var p = /\D/gi console.log(typeof p) // 结论为字符串的形式:'object'- instanceof(检测引用类型时)
var a1 = { a: 1} var a2 = [1,2,3] var a3 = /\D/gi console.log(a1 instanceof Object) // 结论为布尔类型的形式:'true' console.log(a2 instanceof Array) // 结论为布尔类型的形式:'true' console.log(a3 instanceof RegExp) // 结论为布尔类型的形式:'true'
二、执行环境及作用域
- 执行环境定义了变量或函数有权访问的其它数据,决定了它们各自的行为
- 机理:每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。虽然我们编写的代码无法访问这个对象,但解析器在处理数据时会在后台使用它。
- 全局执行环境是最外围的一个执行环境
- 根据ECMAScript,所在的宿主环境不同,表示的执行环境对象也不一样
- 在Web浏览器中,全局执行环境是window对象,关闭网页或浏览器是销毁
- 每个函数都有自己的执行环境
- 作用域链的产生:当代码在一个环境中执行时,会创建变量对象的一个作用域链(这里变量对象是一个特定名词)
- 作用域链的用途:保证对执行环境有权访问的所有变量和函数的有序访问
- 作用域链的长相:
- 当前执行代码所在环境的变量对象
→ - 包含(外部)环境的变量对象
→ - 包含(外部)环境的变量对象
→ - …
- →
- 全局执行环境的变量对象
- 当前执行代码所在环境的变量对象
如果这个环境是函数,则其活动对象作为变量对象(对下)
// 全局作用域
var color = 'blue'
function changeColor() {
// 局部作用域
if (color === 'blue') {
color = 'red'
} else {
color = 'blue'
}
}
changeColor()
console.log("Color is now " + color )
// 全局环境
var color = 'blue'
function changeColor() {
// changeColor()局部环境
var anotherColor = 'red'
function swapColors() {
// swapColors()局部环境
var tempColor = anotherColor
anotherColor = color
color = tempColor
// 这里可访问 color anotherColor tempColor
}
// 这里可访问 color anotherColor
swapColors()
}
// 这里可访问color
changeColor()
-
延长作用域链:
- 在作用域链的最前面添加一个变量对象:
- try-catch语句的catch块:会创建一个新的变量对象,其中包含被抛出的错误对象
- with语句:会将指定的对象添加到作用域链中
function buildUrl() { var qs = "?debug=true" /** ** with语句接收location对象 ** 因此其变量对象包含了location对象的所有变量和方法 */ with(location){ // href 相当于 location.href var url = href + qs } return url }
- 在作用域链的最前面添加一个变量对象:
-
没有块级作用域
例如:if块
if (true) { var color = 'blue' } alert(color) // 'blue'for块
for (var i = 0; i < 10; i++){ doSomething(i) } alert(i) // 10
-
声明变量:
1.使用var声明的变量会自动被添加到最接近的环境
2.函数内部,最接近的环境是函数军局部环境
3.with语句中,最接近的环境是函数环境
4.如果初始化变量没有用var,该变量会自动被添加到全局环境中
- 函数内声明:
function add(num1, num2) { var sum = num1 + num2 return sum } var result = add(10, 20) // 30 alert(sum) // 由于sum不是有效的变量,因此会导致错误- 函数未声明:
function add(num1, num2) { sum = num1 + num2 return sum } var result = add(10, 20) // 30 alert(sum) // 30 -
查询标识符
1.搜索从作用域链的前端开始,向上级查询与给定名字匹配的标识符
2.局部环境中找到则停止,否则继续沿作用域链向上搜索
3.搜索过程追溯到全局环境的变量对象
4.如果全局环境中没有,则该变量未声明
var color = 'blue' function getColor() { return color } alert(getColor()) // 'blue' 搜索至全局才停止var color = 'blue' function getColor() { var color = 'red' return color } alert(getColor()) // 'red' 搜索至函数环境停止
三、垃圾收集
-
JavaScript垃圾回收机制的原理:
找出那些不再继续使用的变量,然后释放其占用的内存
为此,垃圾收集器会按照固定时间间隔(或代码执行中预定的收集时间),周期性地执行这一操作 -
垃圾回收策略:标记清除(主流) 与 引用计数
-
有时间可以深究一下这个单元
本文深入探讨JavaScript中变量的基本类型与引用类型,解释了执行环境、作用域链以及垃圾回收机制,帮助理解内存管理。
485

被折叠的 条评论
为什么被折叠?



