Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

作用域、局部变量的声明方式对变量类型的影响 #9

Open
CoolRabbit520 opened this issue Mar 13, 2018 · 0 comments
Open

Comments

@CoolRabbit520
Copy link
Owner

CoolRabbit520 commented Mar 13, 2018

问题来源

函数中声明变量的时候,困惑是否要使用var关键字。
或者是说,在函数内部,使用或者不使用var关键字声明变量会有什么区别?

问题解答

函数内部,使用或者不使用var关键字声明变量会有区别,区别主要体现在:是否添加var关键字会影响该变量的作用域

  • 使用var声明的变量会被自动添加到最近的环境中。
    在函数内部,初始化声明使用var,该变量会被定义成函数内部的局部变量,外部无法访问。例如:
function add(num1,num2){
	var sum=num1+num2;
	return sum;
}

var result=add(10,20);//30
alter(sum);//由于sum不是有效的全局变量,因此会导致错误。
  • 但是,如果初始化声明没有使用var,该变量会被自动添加到全局变量中(实际上是为window全局对象创建新属性,具体分析见下文)。例如:
function add(num1,num2){
	 sum=num1+num2;
	return sum;
}

var result=add(10,20);//30
alter(sum);//30

总结:使用'var'就可以关联当前作用域,不使用'var'始终都是在为window全局对象创建属性。


注意

在对象内部,添加属性是不用添加var关键字的

问题延伸

if语句或者for语句中,使用或者不使用var关键字声明变量会有区别吗?

问题解答

  • 首先要明确一点:JS中没有块级作用域。所以不同于上面“函数内部声明变量”的情况,即:是否添加var关键字都不会影响该变量的作用域。

类C语言中有这个概念,因此很容易混淆。
块级作用域:简单说来就是,花括号{}括起来的代码共享一块作用域,里面的变量都对内或者内部级联的块级作用域可见。

在JS中,if语句或for语句中的变量声明将会添加到当前的执行环境中。例如:

if (true) {
	var color="rad";
}
alert(color);//"red"
for(var i=0;i<10;i++){
	dosomething();
}
alert(i);//10
  • 所以,在if语句或者for语句中的变量本质上就是“一般的(全局)变量”。
    这个问题就变成了“在javascript中,使用或者不使用var关键字声明变量会有区别吗?"

需要肯定的是,声明变量用var关键字和不用是存在区别的,具体的区别在下面具体讨论。


问题再延伸

javascript中声明全局变量用var和不用的区别?

问题解答

先来看一个例子:

<script>
var a = 1;
b = 2;
window.c = 3;
</script>

分析

在全局作用域里,上面3种形式都可以创建对“全局变量”。

  • var a = 1;使用var直接声明变量。

  • 由于这段代码是出现在全局作用域中的,所以可以认为b=2;只是省略了前面window.的部分。 所以,b=2;window.c=3;本质上是一样的。

在web中使用JS,Window 对象是全局对象。这意味着在网页中定义的任何一个对象、变量和函数都是以Window为其全局对象。也就是说,要引用当前窗口根本不需要特殊的语法。

  • 在执行b=2;这个语句的时候,当前执行环境会沿着作用域链寻找名字叫做b的变量,一直找到作用域链的顶端还没有找到,于是给window这个全局对象添加一个属性b然后赋值。

全局变量和函数都是作为window对象的属性和方法创建的。也就是说,在全局作用域中声明的变量和函数会自动变成windowd对象的属性和方法。
相应的,Window对象的属性和方法也可以作为全局变量和函数来使用。
不使用var声明变量,而是对全局对象的属性进行赋值操作。

当编译器解析到了一个没有var关键字的变量时,
首先,它会尝试在当前作用域链中解析该变量。
如果在任何当前作用域链中找到该属性,则会执行对该属性赋值。
如果没有找到该属性,它才会在全局对象(即当前作用域链的最顶层对象,如window对象)中创造该属性并赋值。

  • window.c = 3;就是在window对象上直接定义属性并且赋值。

总结

分析完上面那个例子,发现本质上声明全局变量用var和不用是没有区别的,最终都能在全局环境中创建了一个全局可用的变量(实际上是window对象的属性),只是达成的这个目的的方法不同:使用var就是直接定义全局变量;不使用var则是通过在window对象上直接定义属性。

区别

当然在使用过程中还是有两点区别:

  1. 使用var声明的全局变量不能通过delete操作符删除,没有使用var声明的变量可以被删除。
var age=29;
window.color="red";
name="ROSE";

delete window.age;//返回false
delete window.color;//返回true
delete window.name;//返回true

alert(window.age);//29
alert(window.color);//undefined
alert(window.name);//undefined

var num = 1 ;是使用var语句添加的window属性,具有名为[[configurable]]的特性,默认值为false,因此这样定义的属性不能通过delete操作符删除。

  1. 使用var声明的全局变量会被提升,而不用var声明的全局变量不会被提升。例如:
<script>
alert(a);
var a=1;//undefined

alert(a);//error, a is not defined
a=1;
</script>

参考资料

1.《JavaScript高级程序设计》
2.Javascript全局变量var与不var的区别 - CSDN博客

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant