JavaScript笔记(4)作用域与作用域链
2016-05-27 21:21
525 查看
分析比较下面几组代码,尤其注意(4)和(5)
注意(7)在控制台调试和页面内调试的区别
(1)全局变量贯穿所有代码
(2)局部变量在函数内替换同名全局变量
(3)局部变量不能在函数外使用
(4)“提前”使用局部变量,会得到undefined值
(5)作用域以函数为界限,而不是“复合语句”
(6)函数内定义变量时不用var引导,则自动升级为全局变量
(7)全局变量实际上是全局对象this的一个属性
(8)作用域链
观察函数嵌套定义形成的作用域链。
全局变量就是全局对象this的属性,函数内定义的变量就是本函数(对象)的属性,引用变量时如果本函数不存在该变量,则会查找父节点中的同名变量,如果父节点没有该属性(变量),则继续查找父节点的父节点,以此类推,直到全局对象。如果全局对象也没有该属性,则导致“引用出错(ReferenceError)”的异常。
三个按钮都是弹出:"Button4"。当注册事件结束后,i的值为4,当点击按钮时,事件函数即function(){ alert("Button"+i);}这个匿名函数中没有i,根据作用域链,所以到buttonInit函数中找,此时i的值为4,所以弹出”button4“。
注意: Internet Explorer 8 及更早IE版本不支持 addEventListener() 方法,IE9支持的也不好。
注意(7)在控制台调试和页面内调试的区别
(1)全局变量贯穿所有代码
var i=10;//定义全局变量 function f(){ console.log(i);//输出全局变量i的值10 } f(); console.log(i);//输出全局变量i的值10
(2)局部变量在函数内替换同名全局变量
var i=10;//定义全局变量i function f(){ var i=20;//定义局部变量i console.log(i);//输出局部变量i的值20 } f(); console.log(i);//输出全局变量i的值10
(3)局部变量不能在函数外使用
function f(){ var i=20;//定义局部变量i console.log(i);//输出局部变量i的值20 } f(); console.log(i);//超出函数定义的范围,局部变量i已经不存在,输出"“i”未定义"
(4)“提前”使用局部变量,会得到undefined值
function f(){ console.log(i);//输出undefined,注意此处的i是局部的,但为undefined var i=20;//虽然不是函数的第一句,但其作用域已然相当于第一句,但此初始化之前的输出为undefined console.log(i);//输出已经初始化的值20 } f();
(5)作用域以函数为界限,而不是“复合语句”
function f(){ if(true){ var m=30;//变量m在此函数内均可访问,而不是限定在此“复合语句”中 } for(var n=1;n<10;n++); console.log(m);//输出30 console.log(n);//输出10 } f();
(6)函数内定义变量时不用var引导,则自动升级为全局变量
function f(){ i=100;//虽然在函数内,但没有使用var,则自动升级为全局变量 console.log(i);//输出全局变量i的值100 } f(); console.log(i);//输出全局变量i的值100
(7)全局变量实际上是全局对象this的一个属性
var i=100; k=300; function f(){ var j=200; console.log(i);//输出100 console.log(delete j);//销毁局部变量失败,输出false。(函数结束局部变量会自动销毁) console.log(j);//输出200 } f(); this.k=500;//k=500隐含this console.log(this.i);//输出100 console.log(k);//输出500 console.log(delete i);//在IE控制台销毁全局变量成功,输出true;在IE页面中销毁失败,输出false console.log(i);//在IE控制台全局变量i已经被销毁,无法引用,输出"“i”未定义" ;在IE页面中销毁失败,输出100
(8)作用域链
观察函数嵌套定义形成的作用域链。
全局变量就是全局对象this的属性,函数内定义的变量就是本函数(对象)的属性,引用变量时如果本函数不存在该变量,则会查找父节点中的同名变量,如果父节点没有该属性(变量),则继续查找父节点的父节点,以此类推,直到全局对象。如果全局对象也没有该属性,则导致“引用出错(ReferenceError)”的异常。
var i=100; var j=500; function f1(){ var i=200; console.log("f1.i=="+i);//f1()内含有局部变量i的定义,因此查找链为:f1(),输出f1.i==200 function f2(){ i=300; console.log("f2.i=="+i);//f2()内含有i的重新赋值,因此查找链为:f2(),输出f2.i==300 function f3(){ console.log("f3.i=="+i);//f3()内虽然含有i的重新赋值,但在下一句,因此查找链为:f2()->f3(),输出f3.i==300 i=400;//如果将此句改为 var i=400,则上一句的输出为f3.i==undefined(原因参见(4)) function f4(){ console.log("f4.i=="+i);//f4()内没有i的定义,因此查找链为:f4()->f3(),输出f4.i==400 console.log("f4.this.i=="+this.i);//直接使用全局对象this的属性i的值,因此输出f4.this.i==100 function f5(){ console.log("f5.j=="+j);//f5()至f1()内均无变量j的定义,因此查找链为:f5()->f4()->f3()->f2()->f1()->window,输出f5.j==500 console.log("f5.i=="+i);//查找链为:f5()->f4()->f3(),输出f5.i==400 console.log("f5.this.i=="+this.i);//直接使用全局对象this的属性i的值,因此输出f5.this.i==100 console.log("f5.k=="+k);//查找链为:f5()->f4()->f3()->f2()->f1()->window,但直到window对象也没有k属性,因此输出SCRIPT5009: “k”未定义 } f5(); } f4(); } f3(); } f2(); } f1();应用中的典型错误(转自:http://blog.csdn.net/yueguanghaidao/article/details/9568071 的举例,感谢博主yueguanghaidao)
<html> <head> <script type="text/javascript"> function buttonInit(){ for(var i=1;i<4;i++){ var b=document.getElementById("button"+i); b.addEventListener("click",function(){ alert("Button"+i);},false); } } window.onload=buttonInit; </script> </head> <body> <button id="button1">Button1</button> <button id="button2">Button2</button> <button id="button3">Button3</button> </body> </html>
三个按钮都是弹出:"Button4"。当注册事件结束后,i的值为4,当点击按钮时,事件函数即function(){ alert("Button"+i);}这个匿名函数中没有i,根据作用域链,所以到buttonInit函数中找,此时i的值为4,所以弹出”button4“。
注意: Internet Explorer 8 及更早IE版本不支持 addEventListener() 方法,IE9支持的也不好。
相关文章推荐
- JQuery1——基础($对象,选择器,对象转换)
- Android学习笔记(二九):嵌入浏览器
- Android java 与 javascript互访(相互调用)的方法例子
- JavaScript演示排序算法
- javascript实现10进制转为N进制数
- 最后一次说说闭包
- Ajax
- 2019年开发人员应该学习的8个JavaScript框架
- HTML中的script标签研究
- 对一个分号引发的错误研究
- 异步流程控制:7 行代码学会 co 模块
- ES6 走马观花(ECMAScript2015 新特性)
- JavaScript拆分字符串时产生空字符的原因
- Canvas 在高清屏下绘制图片变模糊的解决方法
- Redux系列02:一个炒鸡简单的react+redux例子
- JavaScript 各种遍历方式详解
- call/apply/bind 的理解与实例分享