1. 外层变量在内部可以找到,反之找不到

以下看个案例:

  1. var a=10;
  2. function aaa(){
  3. alert(a);
  4. }
  5. function bbb(){
  6. var a=20;
  7. aaa();
  8. }
  9. bbb();

结果是?

aaa()和外层的a=10处于同一个变量作用域。所以只能查找10.

如果把a=10去掉呢?结果是报错了。

还是变量作用域的问题,aaa的环境在全局环境下,不可能找到bbb里面的a=20.

2. var的问题:不var就是全局变量

var不写也是可以的。但是不写可能产生一些问题——变量会变成一个全局变量!

由此衍生出这样的问题:

  1. function aaa(){
  2. var a=b=10;
  3. }
  4. aaa();
  5. alert(a);
  6. alert(b);

回想问题,b变成了一个全局变量,a是一个局部变量。

所以alert(a)会报错。

去掉alert(a),aaa()运行的结果是产生了一个全局变量b和一个局部变量a。所以alert(b)的结果是10。

3.变量查找是就近原则,寻找var定义的变量

  1. var a=10;
  2. function aaa(){
  3. alert(a);
  4. var a=20;
  5. }
  6. aaa();

结果是什么?

既不是10也不是20。是undefined

当就近未找到,就会查找外层。一层一层知道直到找到为止。把结果简化一下吧:

  1. var a=10;
  2. function aaa(){
  3. var a=20;
  4. alert(a);
  5. }
  6. aaa();

结果是20。这很符合常识的推断。

  1. var a=10;
  2. function aaa(){
  3. a=20;
  4. alert(a);
  5. }
  6. aaa();

弹出a也是20,但是运行过程需要注意:最开始查找10,接着查找内部,发现a被修改为20.——本质是调用了外层的a。

好了。现在回到本节最初的例子,aaa调用alert的时候,查找的是外层的a,这个进程遇到var a=20这一步时,由于函数内部预解析,查找的作用域就变了。开始查找函数内部的a,但是var a=20这一步放在了后面,所以结果是undefined。

实际上代码变成了这样:

  1. var a=10;
  2. function aaa(){
  3. var a;
  4. alert(a);
  5. a=20;
  6. }
  7. aaa();

所以所有变量在定义时必须放最前面、

4.结合分析

  1. var a=10;
  2. function aaa(){
  3. bbb();
  4. alert(a);
  5. function bbb(){
  6. var a=20;
  7. }
  8. }
  9. aaa();

的结果是什么?

弹出结果是10。因为a是局部中的局部,说白了找不着。

那如果这么写呢?

  1. var a=10;
  2. function aaa(){
  3. bbb();
  4. alert(a);
  5. function bbb(){
  6. return a=20;
  7. }
  8. }
  9. aaa();

好了。由于函数的预解析作用,导致bbb执行修改了全局变量a。所以弹出结果是20.同理,如果我把全局变量var a=10删去。结果还是20。因为bbb又创造了一个全局变量a。

5. 参数跟局部变量同名,优先级是等同的

  1. var a=10;
  2. function aaa(a){
  3. alert(a);
  4. }
  5. aaa(a);

这个简单的例子中弹出的是10。

如果把参数改成b,

  1. var a=10;
  2. function aaa(b){
  3. alert(a);
  4. }
  5. aaa();

结果还是10.

那么这个a究竟是参数呢,还是全局变量a?

答案是,参数名和全局变量名一样时,走的是参数,不一样时,走的是全局变量。

比如:

  1. var a=10;
  2. function aaa(a){
  3. a+=3;
  4. }
  5. aaa(a);
  6. alert(a);//结果是10

基本数据类型不存在引用关系,里面的a就是一个局部变量

看个纠结一点点的吧:

  1. var a=5;
  2. var b=a;
  3. b+=3;
  4. alert(a)

a是5。这是常识。

基本类型的赋值是不存在引用关系的。但如果我想让a和b存在引用关系,应该怎么做?

  1. var a={
  2. a:5
  3. }
  4. var b=a;
  5. b.a+=3;
  6. console.log(a);//{a:8}

如果不存在依存关系——

  1. var a={
  2. a:5
  3. }
  4. var b={
  5. a:a.a
  6. };
  7. b.a+=3;
  8. console.log(a);

另外一个简单例子是数组。

假设这样

  1. var a=[1,2,3];
  2. var b=a;
  3. b.push(4);
  4. console.log(a);//[1,2,3,4]

所以真的要小心了。如果你不想存在引用关系,应该

  1. var b=a.slice()

复合对象应用关系还可以衍生出这样的操作:

  1. var a=[1,2,3];
  2. function aaa(a){
  3. a.push(4);
  4. }
  5. aaa(a);
  6. console.log(a);//[1,2,3,4]

真是没有做不到,只有想不到,这个a又是什么鬼?不是局部变量吗?

a是确实是局部变量没错,但是它引用了外部的数组a。对这个局部变量的操作必将导致外部a的改变!

下面的代码或许让人更清醒些——

  1. var a=[1,2,3];
  2. function aaa(a){
  3. a=[1,2,3,4]
  4. }
  5. aaa(a);
  6. console.log(a);//[1,2,3,4]

因为参数a没有引用外部的a,所以怎么操作都跟外部的a没半毛钱关系!

javascript练习题(2):变量作用域的更多相关文章

  1. javascript中的变量作用域以及变量提升

    在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解. 变量作用域 “一个变量的作用域表示这个变量存在的上 ...

  2. JavaScript基础——理解变量作用域

    一旦你开始在JavaScript应用程序中添加条件.函数和循环,就需要理解变量作用域.变量作用域规定了如何确定正在执行的代码行上的一个特定变量名的值. JavaScript允许你既定义全局版本又定义局 ...

  3. javascript中的变量作用域以及变量提升详细介绍

    在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解变量作用域 “一个变量的作用域表示这个变量存在的上下文 ...

  4. 【JavaScript 从零开始】变量作用域

    变量作用域 一个变量的作用域(scope)是程序源代码中定义这个变量的区域. 全局变量拥有全局作用域,在JavaScript代码中的任何地方都是有定义的.然而在函数内声明的变量只是函数体内有定义. 他 ...

  5. JavaScript学习系列2一JavaScript中的变量作用域

    在写这篇文章之前,再次提醒一下 JavaScript 是大小写敏感的语言 // 'test', 'Test', 'TeSt' , 'TEST' 是4个不同的变量名 JavaScript中的变量,最重要 ...

  6. JavaScript要点 (一) 变量-作用域

    JavaScript 作用域 作用域—可访问变量的集合. 全局变量或者函数可以覆盖window对象的变量或者函数: 局部变量和window对象可以覆盖全局变量和函数. JavaScript 作用域 在 ...

  7. javascript中的变量作用域

    在网上看了一道js面试题 <script type="text/javascript"> var tt = 'aa'; function test() { alert( ...

  8. javascript痛点之一变量作用域

    1.用var声明的变量是有作用域的,比如我们在函数中用var声明一个变量 1 'use strict'; 2 function num(){ 3 //用var声明一个变量num1 4 var num1 ...

  9. 【Javascript系列】变量作用域

    问题描述 本篇文章主要讲解javascript变量及其作用域. 1   内容区 在js中,变量大致可分为全局变量(全局作用域)和局部变量(局部作用域): 用关键字var定义变量(全局变量,可以省略va ...

  10. JavaScript练习题 全局变量 局部变量 作用域

    前沿:大家好~我是阿飞~本次 任何简单的事情都可以复杂化,本次让我们来做下搞事情的练习题吧 例题1: var a = 1; function fn1(){ var a = 2; alert(a); / ...

随机推荐

  1. office 2013 activiate---(run as admin)

    win7 office 2013 activiate---(run as admin) empty the garbage in osx rm -rf ~/.Trash

  2. 【转】Spring中@Component的作用

    今天在写程序的时候看见一个以前没有见过的注解(@Component),在网上查找过后,经过实践,决定把它记录下来. 1.@controller 控制器(注入服务) 用于标注控制层,相当于struts中 ...

  3. pandas 修改列名

    原始文件 下面是Excel打开以及pd.read_csv() 打开: 里面只是干巴巴的数据,没有列名,so,需要给其设置列名. Method1 不让第一行数据默认当作列名(默认第一行数据是列名了). ...

  4. for and range()

    pyhon 中 for 循环可以遍历任何序列的项目,如一个字典或者一个字符. for 循环格式一般如下: for <variable-变量> in <sequence-序列>: ...

  5. python进程间数据不共享(示例演示)

    import multiprocessing data_list = [] def task(arg): data_list.append(arg) print(data_list) def run( ...

  6. 我的Java开发学习之旅------>Java利用Comparator接口对多个排序条件进行处理

    一需求 二实现Comparator接口 三验证排序结果 验证第一条件首先按级别排序级别最高的排在前面 验证第二条如果级别相等那么按工资排序工资高的排在前面 验证第三条如果工资相当则按入职年数排序入职时 ...

  7. java 多线程 day01 创建线程

    线程,即代码的执行路径java 面向对象编程.所以线程在java中也是用对象来表示的,创建线程对象的类就是 Thread如下代码即开启一个新的线程,通过线程对象的start方法,即可启动线程 Thre ...

  8. C#设置当前程序通过IE代理服务器上网

    注意:以下设置只在当前程序中有效,对IE浏览器无效,且关闭程序后,自动释放代码. using System; using System.Collections.Generic; using Syste ...

  9. SqlAlchemy基本

    安装SQLAlchemy: $ easy_install sqlalchemy 数据库表是一个二维表,包含多行多列 [ ('1', 'Michael'), ('2', 'Bob'), ('3', 'A ...

  10. python代码结构

    1. 使用#单行注释,使用'''...'''多行注释 2. 使用连接符\来把一行过长的代码分为多行 3. 用缩进来控制代码块,推荐使用PEP8缩进风格,即四个空格 4. if ...: elif... ...