您的位置:首页 > Web前端 > JavaScript

JS变量、作用域、内存问题(摘至javaScript高程3)

2018-01-30 11:39 531 查看

基本数据类型和引用数据类型

基本数据类型:简单的数据段,其数据类型是按值访问,可以操作保存变量中的实际值。存放形式 是以栈的方式存放。

引用数据类型:多个值构成的对象,其值是保存在内存中的对象。存放形式是以堆的形式存放。

ES中所有函数的参数都是按值传递的,即把函数外部的值复制给函数内部。

基本类型的值传递如同基本类型的变量复制一样,

引用类型值的传递,如同引用类型变量的复制一样。

在向参数传递基本类型的值时,被传递的参数会被复制给一个局部变量。

在向参数传递引用数据类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此其局部变量的变化会反映在函数的外部。

//基本数据类型的 值传递
function addTen(num){
num += 10;
return num;
}
var count = 20;
var person = addTen(count);
console.log(count)  //20
console.log(person)     //30


//引用数据类型 的值传递
function addTen(obj){
obj.name = 'lose'
}
var person = new Object();
addTen(person)
console.log(person.name)    //lose


//引用数据类型 的值传递
function addTen(obj){
obj.name = 'lose';
obj = new Object();
obj.name = 'amy';
}
var person = new Object();
addTen(person)
console.log(person.name)    //lose


注:引用数据类型依然是按值传递,当在函数内部重写了obj时,这个变量引用的就是一个局部对象了,而这个局部对象会在函数执行完毕后立即销毁。

检测类型

基本数据类型用 typeof 可以直接检测;

引用数据类型用instanceof检测;用法如下:

console.log(person instanceof Object)   //变量person是对象吗


所有引用类型的值都是Object的实例,检测一个引用数据类型和Object构造函数时,instanceof 操作符始终会返回true。

反之,用instanceof 检测一个基本数据,始终会返回false,因为基本数据类型不是对象。

执行环境与作用域

执行环境定义了变量或函数有权访问的其他数据,每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。

全局执行环境是最外围的一个执行环境。在web浏览器中,全局执行环境被认为是window对象,因此所有全局变量和函数都是作为window对象的属性和方法创建的。某个执行环境的所有代码执行完毕后,该环境被销毁,保存在其中的函数定义和变量也随之销毁。(全局执行环境,直到某个应用退出时才会被销毁)

当代码在一个环境中执行时,会创建变量对象的一个作用域链。其用途是为了保证对执行环境有权访问所有变量和函数的有序访问。

var color = 'blue';
function changeColor(){
if(color === 'blue'){
color = 'red';
}else{
color = 'blue';
}
};
changeColor();
console.log('color is ' + color);   //color is red


举个栗子:

var color = 'blue';
function changeColor(){
var anotherColor = 'red';
function other(){
var tempColor = anotherColor;
anotherColor = color;
color = tempColor;
//可以访问tempColor,color,tempColor
}
//可以访问 color,anotherColor,不能访问tempColor
other();
}
//可以访问color,不能访问anotherColor,tempColor
changeColor();


以上代码涉及3个执行环境:全局,changeColor() 局部环境,other() 局部环境;

内部环境可以通过作用域链访问外部的所有环境,但外部环境不能访问内部环境的任何变量和函数。

这些环境之间的联系是线性的、有次序的,每个环境都可以向上搜索作用域链,以查询变量和函数名;但任何环境都不能通过向下搜索作用域链而进入另一个执行环境。

js没有会块级作用域

举个栗子:

if(true){
var color = 'blue';
}
console.log(color)  //blue


if语句的变量声明会将变量添加到当前的执行环境中(全局环境);

例如在 for 语句中:

var doSomething = function(){ }
for(var i = 0; i<10; i++){
doSomething(i);
}
console.log(i)  //10


for语句创建的变量i即使在for循环结束后,也依旧会存在于循环外部的执行环境中。

1,声明变量

如果初始化变量时没有使用var声明,该变量会自动添加到全局环境中.

function sun(num1,num2){
a = num1 + num2;
return a;
}
var rest = sun(10,20);
console.log(a);     //30
console.log(rest);  //30


2,查询标识符

举个栗子:

var col = 'blue';
function find(){
return col;
}
console.log(find());    //blue


首先,搜寻 find() 的变量对象,找寻其中是否包含一个 名为 col 的标识符;

如果没有,则继续找下一个变量对象(全局对象),找到以后,搜索停止。

如果局部环境中存在同名标识符,则不会使用位于父环境的标识符

举个例子:

var col = 'blue';
function find(){
var col = 'red';
return col;
}
console.log(find());    //red
console.log(window.col);    //blue


任何位于局部变量声明后的代码,如果不使用 window.都无法访问全局变量。

如果有一个操作数是对象,而另一个不是,就会在对象上调用 valueOf() 的方法取得基本类型的值。

垃圾收集

JS具有自动垃圾收集机制。

1 : 标记清除

2 : 引用计数

3:管理内存

优化内存占用的最佳方法,为执行中的代码只保存必要的数据,一旦数据不再拥有,通过将其值设置为null来释放引用,该方法被称作为接触引用

举个栗子:

function content(name){
var loctionPerson = new Object();
loctionPerson.name = name;
return loctionPerson;
}
var restFun = content('lose')
//手动解除restFun 的引用
restFun = null;


注:解除一个值的引用,并不意味着自动回收该值所占用的内存。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: