(1)Javascript之作用域链
来源:互联网 发布:酷家乐在线装修软件 编辑:程序博客网 时间:2024/05/17 06:56
- 引言
- javascrpt的作用域前言
- Javascript的Demo
- 1demo1代码
- 2demo2代码
- 3demo3代码
- 4 demo4代码
- 5demo5代码
- 6demo6代码
- 7demo7代码
- 8demo8代码
- 9demo9代码
- 总结
1.引言
大家在初学javascript中,总感觉js和一些后台语言(例如C#,Java)太像了,除了js的类型是弱类型,其他感觉没有什么区别啊,好像语法都是一样的呢,其实这是不对的,js还是有很多它自己的特性,接下来我们就着重说一下js语言一些特别之处,其中一处便是javascript的作用域问题。
2.javascrpt的作用域前言
在js中是不存在封闭作用域的。比如下面这个例子:
for(var i=0;i<10;i++){}alert(i);//此处弹出10
在上面这个例子中,弹出i
为10,而不是undefined
,如果这行代码是用Java语言写的,那么i
肯定是未定义的(不信的同学可以去试一试),那么js的作用域到底是怎么回事呢?接下来我们用几个demo
来介绍一下,在介绍demo之前,我们首先记住三句话:
- 在JavaScript中函数是一个对象。
- 函数对象会创建一个新的作用域。(很重要)
- 一级作用域链是共享的,标签下面为一级作用域链(不理解没问题,先记住)
3.Javascript的Demo
3.1demo1代码
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title></head><script> var a=0; var click1=function(){ alert(a); } </script><body><button onclick="click1();">弹框</button></body></html>
- demo1图片
首先大家都能看出来,此时点击按钮弹出0,此时我们从作用域链的角度去解释一下为什么弹出0.
解释:
- 我们在一级作用域链中定义了变量
var a=0
(在script标签下面),还定义了一个变量var click1
- 当我们点击按钮时,因为按钮是标签(标签下面的为一级作用域),所以在一级作用域中查找函数对象
click1
,然后触发click1
- 当函数被触发时,在click1的内部(注意是内部)执行代码
alert(a)
(函数对象会创建一个新的作用域,我们叫做click1二级作用域,注意我们叫做click1二级作用域),因为click1二级作用域没有对象a
,然后他就会向上查找,查找到一级作用域有一个a=0,所以弹出0.
3.2demo2代码
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title></head><body><button id="btn">弹框</button></body><script> var a=0; function click1(){ var a=6; alert(a); } document.getElementById("btn").onclick=click1;</script></html>
- demo2图片
点击按钮弹出 6
解释
*demo2和demo1的区别在于在二级作用域中定义一了一个变量var a=6
,当执行click1函数时,它先从 click1二级作用域查找,查找到了a,所以弹出对话框6.
3.3demo3代码
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title></head><body><button id="btn">弹框</button></body><script> var a=0; function click1(){ alert(a); var a=4; } document.getElementById("btn").onclick=click1;</script></html>
- demo3图片
弹出undefined
解释:
- 我们在click1二级作用域下面执行了
alert(a)
,它会首先在二级作用域下面找,发现二级作用域有变量a,但是在alert(a)的时候,a还没有赋值,所以弹出undefined,这也叫做变量名提升。代码和下面等价
function click1(){ alert(a); var a=4; }//等价于function click1(){ var a; alert(a); a=4; }
3.4 demo4代码
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title></head><body><button id="btn">弹框</button></body><script> function click1(){ var b=6; function click2(){ var b=4; alert(b); }; click2(); alert(b); } document.getElementById("btn").onclick=click1;</script></html>
- demo4图片
结果先弹出4,在弹出6
解释:
- 在一级作用域下面定义了一个click1,在click1二级作用域下面定义了b=6,click2,在click2三级作用域下面定义了b=4.(函数对象创建一个新的作用域,因为click1是二级作用域了,所以新创建的作用域是click2三级作用域)
- 当我们执行click1的时候,在click1里面调用了click2,然后alert(b)
- 在click2 我们首先alert(b),因为我们在三级作用域定义了一个b=4,所以弹出4。在click1中的alert(b),因为我们在二级作用域定义了b=4,所以弹出4(注意:二级作用域不能访问三级作用域)
3.5demo5代码
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title></head><body><button id="btn">弹框</button></body><script> function click1(){ var b=6; function click2(){ b=4; alert(b); }; click2(); alert(b); } document.getElementById("btn").onclick=click1;</script></html>
- demo5图片
先弹出4,然后又弹出4
解释:
- demo5和demo4 的区别在于在click2三级作用域链中没有定义b,所以当b=4时它会向上查找,查找到二级作用域有b的定义,所以将二级作用域中的b修改为4,所以弹出4,当执行click1中的alert(b)时,b已经被修改成了4,所以第二次弹出的也是4.
3.6demo6代码
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title></head><body><button id="btn">弹框</button></body><script> function click1(){ var b=6; function click2(){ alert(b); }; } document.getElementById("btn").onclick=click2;</script></html>
- demo6图片
显示click2未定义
解释:
- 因为script标签下面为一级作用域,click2在二级作用域下面,作用域链可以向上查找,但是不能向下查找,所以在执行代码
document.getElementById("btn").onclick=click2;
,当触发点击事件时,显示click2未定义。
3.7demo7代码
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title></head><body><button id="btn">弹框</button></body><script> function click1(){ var b=6; function click2(){ var b=5 }; function click3(){ alert(b); } click3(); } document.getElementById("btn").onclick=click1;</script></html>
- demo7图片解释
弹出6
解释:
- 在这个demo中有两个三级作用域链(注意只有一级作用域链是共享的),一个是click2三级作用域,一个是click3三级作用域,当alert(b)的时候,作用域链是向上查找的,找到了click1二级作用域中b=6,所以弹出了6
3.8demo8代码
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title></head><body><button id="btn">弹框</button></body><script> function click1(){ var b=6; function click2(){ var b=5 }; function click3(){ var b=4; alert(b); } click3(); } document.getElementById("btn").onclick=click1;</script></html>
- demo8图片
弹出4
解释:
- demo8与demo7的区别就是在click3里面定义了b=4,所以直接在它本身作用域中拿到了b,所以弹出4.
3.9demo9代码
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title> <script> window.onload=function(){ click4=function(){ alert(6) }}</script></head><body><button id="btn" onclick="click4();">弹框</button></body></html>
弹出 6
解释:
- 大家可能疑问,为什么不是未定义呢?标签下面为一级作用域,所以代码
<button id="btn" onclick="click4();">弹框</button>
应该会在一级作用域中查找click4,但是click4明明在二级作用域中啊?注意我写的是click4=function(){},此处并没有用var ,所以这里不是定义是赋值,当执行click4=function(){}时,它首先会在2j级作用域中查找是否有click4,没有查找到,所以去一级作用域中查找,也没有查找到,所以就会在一级作用域中声明一个var click4,上面的代码与下面等价:
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title> <script> var click4; window.onload=function(){ click4=function(){ alert(6) }}</script></head><body><button id="btn" onclick="click4();">弹框</button></body></html>
- 当我们把我们的代码修改为这样时,就会显示未定义了
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title> <script> window.onload=function(){ var click4=function(){ alert(6) }}</script></head><body><button id="btn" onclick="click4();">弹框</button></body></html>
click4未定义
4.总结
然后我们在看一看我们开头说的几句话
- 在JavaScript中函数是一个对象。
- 函数对象会创建一个新的作用域。
- 一级作用域链是共享的,标签下面为一级作用域链
- 作用域链向上查找,不可能向下查找
在看这几个特点,关于js的作用域链你懂了吗?
1 0
- (1)Javascript之作用域链
- javascript之作用域链
- javascript之作用域
- 1、JavaScript高级之函数作用域链
- JavaScript高级之词法作用域和作用域链
- 进击JavaScript之词法作用域与作用域链
- javascript之(四)作用域链,闭包
- JavaScript学习笔记之作用域链
- 5.JavaScript深入之作用域链
- javascript 之作用域链-07
- JavaScript学习之作用域(一)
- javascript作用域链-(1)
- javascript之变量作用域
- javascript 笔记之作用域
- javaScript变量之作用域
- JavaScript作用域之我见
- JavaScript之作用域原理
- Javascript之理解作用域
- SpringMVC之获取随机验证码
- Solr 6.0 学习(九) SolrDispatchFilter源码解析之HttpSolrCall及扩展
- 【Android】Dx unsupported class file version 52.0
- Linux下profile和bashrc四种的区别
- 线性刻度尺
- (1)Javascript之作用域链
- 深入理解C实现文本文件的加密解密,读取长度操作
- 反射设置android6.0 以太网的打开和设置静态Ip,不用导源码包
- 设置IE浏览器文本模式为IE8或IE7
- 为什么我设置焦距没有效果
- 条目有限的RecyclerView 与ScrollView滑动冲突解决(仅限条目有限)
- 排序:归并排序的迭代写法与递归写法
- Animation 动画介绍和实现
- 初步学习Struts2