Js作用域与作用域链详解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Js作用域与作用域链详解相关的知识,希望对你有一定的参考价值。

 

Js作用域与作用域链详解

http://blog.csdn.net/yueguanghaidao/article/details/9568071

一:函数作用域

 技术分享

 技术分享

第一句输出的是: "undefined",而不是 "global"

第二讲输出的是:"local"

  你可能会认为第一句会输出:"global",因为代码还没执行var scope="local",所以肯定会输出“global"。

  我说这想法完全没错,只不过用错了对象。我们首先要区分javascript的函数作用域与我们熟知的C/C++等的块级作用域。

  在C/C++中,花括号内中的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的。而Javascript压根没有块级作用域,而是函数作用域.

所谓函数作用域就是说:-变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。

所以根据函数作用域的意思,可以将上述代码重写如下:

 技术分享

 技术分享

 

 

我们可以看到,由于函数作用域的特性,局部变量在整个函数体始终是由定义的,我们可以将变量声明”提前“到函数体顶部,同时变量初始化还在原来位置。

为什么说Js没有块级作用域呢,有以下代码为证:

 

 技术分享

技术分享

都输出是“local",如果有块级作用域,明显if语句将创建局部变量name,并不会修改全局name,可是没有这样,所以Js没有块级作用域。

现在很好理解为什么会得出那样的结果了。scope声明覆盖了全局的scope,但是还没有赋值,所以输出:”undefined“。

所以下面的代码也就很好理解了。

 

 技术分享

 技术分享

 

 

 

二:变量作用域

 技术分享

 技术分享

 

Js中没有用var声明的变量都是全局变量

三:作用域链

 技术分享

 

当执行s时,将创建函数s的执行环境(调用对象),并将该对象置于链表开头,然后将函数t的调用对象链接在之后,最后是全局对象。然后从链表开头寻找变量name,很明显

name是"slwy"。

但执行ss()时,作用域链是: ss()->t()->window,所以name是”tlwy"

 

 技术分享

技术分享

 

当文档加载完毕,给几个按钮注册点击事件,当我们点击按钮时,会弹出什么提示框呢?

很容易犯错,对是的,三个按钮都是弹出:"Button4",你答对了吗?

当注册事件结束后,i的值为4,当点击按钮时,事件函数即function(){ alert("Button"+i);}这个匿名函数中没有i,根据作用域链,所以到buttonInit函数中找,此时i的值为4,

所以弹出”button4“。

 

附: 使用闭包 保存变量

 技术分享

技术分享

 

四:with语句

说到作用域链,不得不说with语句。with语句主要用来临时扩展作用域链,将语句中的对象添加到作用域的头部。

 

 

  1. js没有块级作用域(你可以自己闭包或其他方法实现),只有函数级作用域,函数外面的变量函数里面可以找到,函数里面的变量外面找不到。
  2. 变量的查找是就近原则,去寻找var定义的变量,当就近没有找到的时候就去查找外层。
  3.   当参数跟局部变量重名时,优先级是等同的。传参时,基本类型传值,引用类型传引用。

 

 

 

1、 JavaScript没有代码块作用域的概念,局部作用域是针对函数来说的。

2、  如果不使用var声明的变量,默认为全局变量

以上是关于Js作用域与作用域链详解的主要内容,如果未能解决你的问题,请参考以下文章

JS高阶---作用域与作用域链

js的作用域与作用域链

JavaScript-作用域与作用域链

js-高级(原型与原型链作用域与作用域链闭包)

死磕前端javascript知识点详细讲解 • 第2篇《作用域与作用域链》

作用域与作用域链