变量的作用域:
作用:起作用。
域:范围,区域。
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].οnclick=function(){ alert(i); } } </script></body>以上是:这里是由于先绑定,后触发,给每个按钮绑定事件,但是在触发的时候i已经是循环完之后,所以i的值一直都是3。