变量的作用域:
作用:起作用。
域:范围,区域。
1,变量的生命周期。
2,哪里可以访问变量。
----------------作用域-----------
1,全局作用域 全局都可以访问的变量的区域
2,局部作用域:主要就是函数作用,理解为:函数体内部的执行环境。
不存在的变量或函数会报错;不存在的属性或方法,返回undefined;
javascript 没有块级作用域:
比如
{ ...... } //在这个花括号里面的变量就叫块级作用域,但JS中没有块级作用。
比如:
if(){......} for(){.....)等等:
<script>
if (true) {
var a=0;//属于全局变量,因为JS不存在块级作用域,即:{}花括号之间的作用域,其他语言会有
}
for (var i = 0; i < elements.length; i++) {
var b=1;//属于全局变量,因为JS不存在块级作用域,即:{}花括号之间的作用域,其他语言会有
}
</script>
----------------------------------------
<script>
function fn(){
var x=y=1;
console.log(x);//返回 1
console.log(y);//返回 1
}
// console.log(x);//报错,因为x是局部变量,不能再函数体以外进行访问。
fn();//如果不执行该方法,则输出下面y就会报错: y is undefined
console.log(y);//返回 1
</script>
---------js没有块级作用,所以变量都是全局作用域------------
script type="text/javascript">
if (true) {
var name="xm"; //在js中没有块级作用域,所以,这里的name是全局变量。
};
document.write(name);//输出:xm
</script>
--------------------
script type="text/javascript">
if (true) {
var a.name="xm"; //这里的对象a没有声明,所以会出现uncaught SystaxError的错误。
};
document.write(a.name);// 虽然js不存在块级作用,但是每个对象必须声明。变量可以直接使用,如:name等于 var name。
</script>
-----------------
因为不用var声明的变量是全局变量,y是全局变量,可以输出;x是局部变量,因此输出x会报错。
<script type="text/javascript">
function fn(){
var x=y=1;//这里的y用var声明,所以是全局变量。
}
fn();
document.write(y);
document.write(x);
</script>
因为不用var声明的变量是全局变量,y是全局变量,可以输出;x是局部变量,因此输出x会报错。
---------------
在JS中,主要是全局变量和,函数变量(局部变量)
说白了,下面的两个a完全不同,第一个是全局变量,函数内的是局部变量。
<script type="text/javascript">
var a="xm"; //这里的a 是全局变量
function fn(){
var a="xh"; //这里的a 是局部变量,在函数中重新声明了。
document.write(a); //这里读取的是局部变量,所以a="xh"。
}
fn();
document.write(a); //这里读取的是全局变量,而不是局部变量,所以a="xm"。
</script>
-------
下一个例子完全相反:
-------
说白了,下面只有一个全局变量a。
<script type="text/javascript">
var a="xm";
function fn(){
a="xh"; //在函数内没有用var声明变量,说明是全局变量,a的值被改为 "xh"。
document.write(a); //全局变量 a="xh"。
}
fn();
document.write(a);//全局变量a在函数内被修改为"xh",所以这里的a="xh"。
</script>
===============
全局作用域的 变量对象 window:
<script>
var a=70;
function add(){
return a+10;
}
add();//返回80;
console.log(window.a===a);//返回 true
console.log(window.add===add);//返回 true
</script>
-------------------------
局部作用域的 变量对象 :
<script>
var a=70;
function add(){
return a+10;
var b=10;
function fn(){
var c=20;
return a+b+c+20;
}
}
</script>
解析:
1,全局作用域变量对象
window.a===a
window.add===add
2,add函数的局部作用变量对象,是看不见摸不着的,假如局部变量的变量对象是:add
add.b===b
add.fn===fn
3,fn函数的局部作用变量对象,是看不见摸不着的,假如局部变量的变量对象是:fn
fn.c===c
三个作用域就连成了一个作用域链:
作用域都是从内层向外层查找属性值。
如查找 fn.c 的值的查找顺序----fn局部作用域----add局部作用域-----window全局作用域,取最近存在的值,即:fn.c=20,如果不存在,返回undefined
如查找 fn.a 的值的查找顺序----fn局部作用域----add局部作用域-----window全局作用域,fn.a=window.a=70。
如查找 add.a 的值的查找顺序 ---add.a局部作用域 -----window全局作用域,add.a=window.a=70
如查找 add.c 的值的查找顺序----add.a局部作用-----window全局作用域,不存在,所以add.c 返回:undefined,这里add.c!==fn.c,只可以向外查找,不能向内查找。
所以,局部变量一定比全局变量效率高,内层变量一定比外层变量效率高。
============
通过 with(obj) 来延长作用域链,但是这个很鸡肋,降低效率,还有其他一切问题,不推荐使用,了解即可,如下代码:
<script>
/*
注意比较以下全局变量对象和局部变量对象的属性和方法:
全局变量对象window的属性及方法:
1,window.person对象
2,window.score属性*/
var person={};
var person.name="xm";
var person.sex="male";
var score=80;
/*局部变量对象person
1,person.name 等价于修改了上面的window.person.name
2,person.sex 等价于修改了上面的window.person.sex
3,person.score 等价于widow.score*/
with(person){
name="xh";//全局属性中已经定了变量对象window的属性person对象中name的属性,所以这里只是重新赋值。
sex="female";//全局属性中已经定了变量对象window的属性person对象中sex的属性,所以这里只是重新赋值。
score=90; //因为person不存在该属性,全局属性中已经定了person的属性,所以继承了window.score的值,并且修改了。
}
</script>
============
<script type="text/javascript">
//以下 person未定义的变量 报错
document.write(person || person="xm");
document.write(window.person || window.person="xm");
</script>
不存在的变量或函数会报错;不存在的属性或方法,返回undefined;||是短路操作,形如a||b,如果a的值转换成布尔值是true的话,a||b等于a;如果a的值转换成布尔值是false的话,a||b等于b。
--------------------
<body>
<button>1</button>
<button>2</button>
<button>3</button>
<script type="text/javascript">
var btns=document.getElementsByTagName('button');
for (var i = 0; i < btns.length; i++) {
btns[i].onclick=function(){
alert(i);
}
}
</script>
</body>
以上是:这里是由于先绑定,后触发,给每个按钮绑定事件,但是在触发的时候i已经是循环完之后,所以i的值一直都是3。