变量 作用域和内存问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了变量 作用域和内存问题相关的知识,希望对你有一定的参考价值。
4.1变量
变量包含2种类型的值:
基本类型的值: 即undefined,null, string,number,boolean. 按值访问,可以操作保存在变量中实际的值, 不能添加属性。
var name = "Nicholas"; name.age = 27; console.log(name.age); //undefined
引用类型的值:多个值构成的对象。JS不允许直接操作对象的内存空间。给一个对象添加属性是,是在实际的对象中添加。
俩种类型值的区别:
1.保存方式不同: 基本类型保存再对象空间中。引用类型保存再内存中。
2.复制变量值时:基本类型 从一个变量复制到另外一个变量,变量对象是创建一个新值,然后把值复制给新变量。
引用类型 复制值的一个指针,存储在新变量中,实际引用的是同一个对象。
var obj1 = new Object(); var obj2 = obj1; obj1.name = "Nicholas"; console.log(obj1); console.log(obj2); //Object {name: "Nicholas"} //Object {name: "Nicholas"}
传递参数
JS中所有函数的参数都是按值传递的。
基本类型的值从一个变量复制到另一个变量,实际是值被复制了俩份。
function addTen (num) { num +=10; return num; } var count = 20; var rezult = addTen(count); console.log(rezult); console.log(count); // 30 rezult保存的值 被当做参数传递进addTen进行了10;再返回 // 20 count再外部,没有受到+10的影响,所以返回20.很好的证明了保存在变量中基本类型的值向另外一个副本复制值 是创建了一个副本
而参数是对象(对象是引用类型的一种)时,也是按值传递。
function setName (obj) { obj.name = "Nicholas"; obj = new Object(); obj.name = "Gray"; } var person = new Object(); setName(person); console.log(person.name); // Nicholas 即使再函数内部修改了参数的值,原始的引用仍然保持不变。
// 再函数内部重写obj时,这个变量引用的是一个局部对象,这个局部对象会在函数执行完毕后立即被销毁。
检测类型
instanceof: 变量是给定类型的实例返回true.
function setName (obj) { obj.name = "Nicholas"; } var person = new Object(); setName(person); console.log(person instanceof Object); //true person是Object的实例
执行环境及作用域
执行环境: 定义变量或函数有权访问的其他数据,决定他们各自的行为。执行环境中的代码执行完毕后,该环境被销毁,变量和函数也被销毁。
变量对象: 每个执行环境有一个变量对象。环境中定义的所有变量和函数都保存再这个对象中。
全局执行环境: 最外围的一个执行环境,也被认为是window对象。所有全局变量和函数都是作为window对象的属性和方法创建的。
作用域链: 函数有自己的执行环境。代码在一个环境中执行时,会创建变量对象的一个作用域链。用途是搜索变量和函数。作用域链的前端始终都是当前执行代码所在环境的变量对象。
var color = "blue"; function changeColor() { if(color === "blue") { color = "red"; } else { color = "blue"; } } changeColor(); console.log("Color is now " + color); // Color is now red
函数changeColor的作用域链包含2个对象,它自己的变量对象(arguments对象)和全局变量对象(color)。
var color = "blue"; function changeColor() { var anotherColor = "red"; function swapColors() { var tempColor = anotherColor; anotherColor = color; color = tempColor; } }
内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境的变量和函数。
没有块级作用域
再JS中,if语句中变量声明会将变量添加到当前的执行环境。
if(true) { color = "red"; } console.log(color); //red
for语句创建的变量i既然再for循环执行结束后,依旧存在循环外部的执行环境中。
for(var i=0; i <10; i++) { i++; } console.log(i); //10
查询标识符
查询标识符从作用域最前端开始,向上逐级查找与给定名字匹配的标识符。找到为止,没有找到意味着该变量未声明。
var color = "blue"; function getColor() { return color; //首先再getcolor函数里寻找color标识符,未找到 //接着向上查找,包裹getColor的是全局执行环 境,最后在全局执行环境中到了,,并立即返回 } console.log(getColor()); // blue
如果存在同名标识符,局部变量优先级最高。
var color = "blue"; function getColor() { var color = "red"; //局部变量覆盖了全局变量 return color; } console.log(getColor()); //red
以上是关于变量 作用域和内存问题的主要内容,如果未能解决你的问题,请参考以下文章