JS的作用域和声明提前,js中局部变量泄露为全局变量

news/2024/7/19 15:37:08 标签: js

JS的作用域和声明提前

首先介绍下Javascript的函数作用域的概念,然后了解下什么是作用域和声明提前,最后通过一个例子剖析Javascript的作用域链。

1.变量的作用域

稍微有些编程背景的都知道,变量的作用域分为两种: 全局变量 和 局部变量 。

Javascript是一门 弱类型语言 。所有的变量声明都是通过var来接收,如

  1. var num = 1; 
  2. var str = “string”; 
  3. var flag = true; 

看似是一个非常省事的机制,但是也有让人头疼的时候,一些隐式的类型转换经常会把搞晕。先看看全局变量和局部变量:

  1. var g = "global"; function f(){ var l = "local"; 

注意 : 1. 如果在函数f()中将去掉var声明,则变量l就会从局部变量升级为全局变量。

2. 局部变量的优先级高于同名的全局变量 。如果在函数f()中声明一个局部变量也为g,则全局变量就会被局部变量覆盖

2.作用域和声明提前

看到Javascript作用域这块,可以说颠覆了以前我对作用域的认识。类似Java和C等编程语言,在花括号“{}”内的代码都是有各自的作用域的,并且在这个范围以外,这些变量是不可见的,我们称这种作用域为 块级作用域 。

但是这完全不适用于Javascript,因为Javascript没有块级作用域,但是Javascript有 函数作用域 。函数作用域简言之就是:变量在声明他们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。

对于“ 变量在声明他们的函数体以及这个函数体嵌套的任意函数体内都是有定义的 ”这句话的延伸理解:变量在声明之前就已经可用。我们称这种特性为声明提前,也就是函数里的所有变量都被“提前”至函数体的顶部。

下面我们看一个经典的陷阱案例:

  1. var v = "yoyo"; (function(){ console.log(v); var v = "check now"; 
  2.     console.log(v); 
  3. })(); 

对于第二次执行结果“check now”没有什么特别的,为什么第一次输出的不是“yoyo”而是“undefined”。

对于这个问题的解释就用到上面的那句话, 局部变量在整个函数体始终是有定义的 ,即在函数体内局部变量覆盖了同名全局变量,而且,程序只有在执行到var语句时,局部变量才会被真正赋值。所以,这时你大概会明白为什么是undefined了,因为此时还没有遇到var,即没有定义,等价于下面的形式:

  1. var v = "yoyo"; (function(){ var scope; console.log(v); var v = "check now"; 
  2.     console.log(v); 
  3. })(); 
  4.  
  5. 疑问 ? ? ? 
  6.  
  7. 将上面的代码稍稍修改为: 
  8.  
  9. var v = "yoyo"; (function(){ 
  10.     console.log(v); 
  11. })(); 

运行结果为:

相比于上面的代码只是少了一行添加一个局部变量v并赋值的语句,但是结果却是“yoyo”。

这里之所以输出“yoyo”,不能按照上面的定式思维。上面有句话叫“局部变量在整个函数体始终是有定义的”,但是这里没有局部变量的定义,所以按照下面要提到的作用域链会逐层向上寻找变量,最后找到了全局变量v,从而最后的输出是“yoyo”。

举一个通俗点的例子,你准备要花钱买点东西时,会先摸摸自己的钱包,没了你可以找你爸要,你爸也没有就再找你爷爷,... 。而你爸没钱买东西时,他并不会来找你要。

以上是我的个人理解,如果你对这两种情况有自己的理解,请在下方给出,望不吝指教。

3.作用域链

全局变量在程序中始终是有定义的,局部变量在声明它的函数体内以及其所嵌套的函数内始终是有定义的。

每一段Javascript代码(全局代码或函数)都有一个与之相关联的作用域链,这个作用域链就是一个对象列表或链表。比如当 Javascript需要查找变量x的值时,它会从链中的第一个对象开始,如果该对象有一个名为x的属性,则直接使用,如果不存在名为x的属性,则会继续 向链上的下一个对象查找,如此递归下去直到找到。如果整个链上都找不到,则认为不存在x这个属性。举例:

  1. name="lwy"; function t(){ var name="tlwy"; function s(){ var name="slwy"; console.log(name); } function ss(){ console.log(name); } s();   ss();  
  2. }  
  3. t(); 
4、js中函数作用域中将局部变量 -----泄露为全局变量




转载自:http://www.cnblogs.com/janneystory/p/5689747.html

http://www.niftyadmin.cn/n/1732645.html

相关文章

css3 -webkit-image-set 设置不同分辨率 背景图片

今天get到的一个新技能&#xff0c;看来好久没看css3都要out了&#xff0c;谨以此警醒一下自己 语法&#xff1a; image-set() image-set( <image-set-option># ) <image-set-option> [ <image> | <string> ] <resolution> 说明&#xff1a; i…

html表单---学习笔记03

第8章 表单 8.1 表单标记<form> <form name"表单名称" method"提交方法" action"处理程序">......</form> 关于表单的更多介绍&#xff1a;http://www.cnblogs.com/polk6/archive/2013/06/08/3124228.html ☟ 表单属性&#x…

常见CSS与HTML使用误区

误区一.多div症 <div class"nav"><ul><li><a href"/home/">Home</a></li><li><a href"/about/">About</a></li><li><a href"/concact/">Concact</a>…

前端面试

来总结一下自己的前端面试 一、面试题 我大概说一下我没有写出来的一些&#xff0c;表示好多东西能用&#xff0c;但概念性东西有点晕 1、行内元素&#xff0c;块级元素&#xff0c;空元素各5个&#xff08;空元素表示类似于<br/>&#xff09; 块级元素 address - 地址…

前端开发常用技巧

1、背景图片中部放大、缩小 <html><head><title>测试背景图片属性</title><script src"http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script><style>.back{width:200px;height:200px;line-height:200px;bac…

js函数理解

函数 函数声明、函数表达式、匿名函数 函数声明&#xff1a;function fnName () {…};使用function关键字声明一个函数&#xff0c;再指定一个函数名&#xff0c;叫函数声明。 函数表达式 var fnName function () {…};使用function关键字声明一个函数&#xff0c;但未给函数命…

PHP配置步骤

背景&#xff1a; 作为web前端人员&#xff0c;必不可少的会接触到一些服务器端的脚本语言&#xff0c;比如PHP。因为最近在进行相关知识的总结&#xff0c;同时也回顾一下PHP基础知识。这次总结先从PHP的开始说起&#xff0c;即PHP的配置步骤。 什么是PHP&#xff1f; PHP&…

Flexible 弹性盒子模型之CSS flex-flow

实例 让弹性盒的元素以相反的顺序显示&#xff0c;且在必要的时候进行拆行&#xff1a; display:flex;flex-flow:row-reverse wrap; 效果预览 浏览器支持 表格中的数字表示支持该属性的第一个浏览器的版本号。 紧跟在 -webkit-, -ms- 或 -moz- 后的数字为支持该前缀属性的第一个…