说道作用域,难免要提一下变量
一、变量数据类型
1、基本类型
Number 、String、 null、 undefined、 boolean : 这五种数据是按值访问的,因为可以操作变量中的实际值。(添加属性不会出错,但是没意义)
2、引用类型
对象(Object) : 保存内存中的对象,不可以直接访问内存中的位置,不能直接操作内存中的空间,在操作对象时实际上是在操作对象的引用。(可以添加属性)。
两种类型值复制后的表现:
看段代码:
var value = 4
var valueTarget = value
var value =5
console.log( value ) // 5
console.log( valueTarget ) // 4
var obj = {
name: "liu",
age: 33
}
var _obj = obj
obj.name = "yong"
console.log( obj.name ) // yong
console.log( _obj.name ) // yong
来张图
基本类型:value和valueTarget经过复制后,两个变量中的值是相互独立的,改变一个不会影响另一个。
引用类型:obj和_obj同样也会复制一个值,但是这个值是个指针,而这个指针在内存中指向唯一一个对象,复制结束后,两个变量引用了同一个对象。改变一个时会对另一产生影响。
看个例子:
function setName( obj ) {
obj.name = "liu"
obj = new Object()
obj.name = "yong"
}
var person = new Object()
setName( person )
console.log( person.name )
// 即使在函数内部修改了参数的值,但是原始引用不变,实际上。
// 当函数内部重写obj时,这个变量引用就是一个局部对象了。局部对象会在函数执行完毕后销毁。
二、检测类型
1、typeof : 检测String、Number、Boolean、undefined的最佳工具。值为null时,返回Object
2、instanceof : 检测引用类型的工具,检测某某是不是某对象的实例。
三、作用域(执行环境)
var size = 44
function addSize() {
var add = 66
function reduceSize() {
var reduce = 22
// 这里能访问size和add和reduce
}
reduceSize()
// 这里能访问size和add
}
// 这里只能访问size
addSize()
1、作用域链
2、javascript中没有块级作用域,也就是说“没有花括号封闭的代码块没有自己的作用域。”
if( true ) {
var color = "blue"
}
console.log( color ) //blue
for( var i = 0; i < 10; i ++ ) {
console.log( "heihei" ) //heihei
}
console.log( i ) // 10
3、var声明的变量会自动添加到最近的环境中。如果没有var则会添加到全局中。
4、查询标识符
var color = "blue"
function getColor() {
//var color = "black" //如果这里在定义一个,将不会查找全局的color
return color
}
console.log( getColor() ) //blue
搜索过程:从作用链的前端开始,向上逐级查询:首先找getColor()的变量对像,看是否有color的标识符,没有找到就去上一级找(全局环境),找到,搜索结束。
var color = "blue"
function getColor() {
var color = "red"
return color
}
console.log( getColor() ) //red
console.log( window.color ) //blue
当在局部定义color时,任何位于局部变量color之后的代码,如果不适用window.color都无法访问全局color。
javscript:常用的垃圾收集方式:
一种:标记清除(mark-and-sweep)。变量进入环境时标记“进入环境”,离开时标记离开。
另一种:引用计数,跟踪记录每个值被引用的次数。
内存问题
通常:分配给web浏览器的内存比分配给桌面应用程序的内存少。
function create( name ) {
var person = new Object();
person.name = name;
return person
}
var globa = create( "liu" );
// 解除global的引用。
globa = null
当调用create()这个函数时,person以函数返回值的形式赋值给globa。由于在person在函数create()执行完后,就离开了其执行环境,生命周期就结束了。无需单独解除引用。而全局变量globa则需要手工解除引用。
解除引用不一定回收该内存,解除的目的是让值脱离执行环境,以便垃圾收集器下次运行时将其收回。