字面意思,作用域是指变量和函数的作用范围,换言之,作用域决定了变量和函数的可见性和有效时间。javascript作用域是用函数来区分,与其他语言的大括号不同。

for (var i=0; i<5; i++){
var mystring = "平底斜";
console.log(i);
}
alert(mystring);//弹出"平底斜"

这段代码在javascript中运行正常,在其他语言中就会报错。这是因为javascript的作用域是基于函数,而不是大括号。

作用域分为全局作用域和局部作用域。

有三种情况会出现全局作用域:

1、最外层定义的变量和函数

var mystring = "平底斜";
function fun(){
alert("Hello World");
}

变量mystring和函数fun()拥有全局作用域,在任何位置都可以直接调用。

2、未定义的变量

function fun(){
var a=b=0;
mystring = "平底斜";
console.log(mystring);
}
fun();
alert(b);

变量mystring没有使用var进行变量声明,所以即使在函数内部也是全局变量。容易忽略的是变量b,看上去使用var进行了声明,实际上只对变量a进行了声明,等同于

function fun(){
var a=(b=0); //自右向左赋值
mystring = "平底斜";
console.log(mystring);
}

一个JS文件中应该尽可能少的出现全局变量,最佳实践是使用var进行变量声明,并且在声明的同时进行赋值。

function fun(){
var a=0, b=1, c=2; //等同于var a=0; var b=1; var c=2;
}
fun();
alert(c); //脚本报错,因为c是局部变量

3、全局对象window

var mystring = "平底斜";
console.log(mystring);
console.log(window.mystring);
console.log(window["mystring"]);
console.log(this.mystring);
console.log(this["mystring"]);//此处this就是window,针对this以后会专题讲解

全局变量都可以看做window的属性,使用方法就如以上代码:可以用"."也可以用"[]"甚至可以省略window

局部变量只有一种情况:在函数内部声明的变量拥有局部作用域

function fun(){
var mystring="平底斜"; //局部变量
console.log(mystring);
}
fun();
console.log(mystring); //脚本报错

冷知识:

全局变量中,使用var声明与不使用var是有区别的,var声明的变量无法删除,未声明的变量可以删除。

var mystring="平底斜";
newstring = "博客园";
delete mystring;
delete newstring;
console.log(mystring); //"平底斜"
console.log(newstring); //脚本报错

作用域链由内向外查找变量,在内部找到变量便停止查找,否则往上一层作用域查找,直到最外层都没有找到变量则返回undefined

var myscope = "平底斜";
function fun(){
var myscope = "博客园";
console.log(myscope); //"博客园"
}
fun();

上面这段代码,就是因为作用域链有内向外,先在函数内部查找myscope,找到了就直接返回该变量值,并停止查找。

易错点:

var myscope = "平底斜";
function fun(){
console.log(myscope); //脚本报错
var myscope = "博客园";
console.log(myscope); //"博客园"
}
fun();

声明变量会在当前作用域中置顶,又叫变量提升或者声明置顶。以上代码等同于:

var myscope = "平底斜";
function fun(){
var myscope;
console.log(myscope); //脚本报错
myscope = "博客园";
console.log(myscope); //"博客园"
}
fun();

需要注意的是变量提升是在函数定义时发生,并不是在函数调用时:

var myscope = "平底斜";
function fun1(){
console.log(myscope);
}
function fun2(){
var myscope = "博客园";
fun1();
}
fun2(); //"平底斜"

如上,fun2()调用fun1()时,是先在fun1()中搜索myscope,找不到时再到父级作用域中查找。作用域的嵌套关系是在定义时产生,而不是在调用的时候。

javascript进阶系列专题:作用域与作用域链的更多相关文章

  1. javascript进阶系列专题:闭包(Closure)

    在javascript中,函数可看作是一种数据,可以赋值给变量,可以嵌套在另一个函数中. var fun = function(){ console.log("平底斜"); } f ...

  2. JavaScript进阶系列07,鼠标事件

    鼠标事件有Keydown, Keyup, Keypress,但Keypress与Keydown和Keyup不同,如果按ctrl, shift, caps lock......等修饰键,不会触发Keyp ...

  3. JavaScript进阶系列06,事件委托

    在"JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数"中已经有了一个跨浏览器的事件处理机制.现在需要使用这个 ...

  4. JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数

    本篇体验JavaScript事件的基本面,包括: ■ 事件必须在页面元素加载之后起效■ 点击事件的一个简单例子■ 为元素注册多个点击事件■ 获取事件参数 ■ 跨浏览器事件处理 □ 事件必须在页面元素加 ...

  5. JavaScript进阶系列04,函数参数个数不确定情况下的解决方案

    本篇主要体验函数参数个数不确定情况下的一个解决方案.先来看一段使用函数作为参数进行计算的实例. var calculate = function(x, y, fn) { return fn(x, y) ...

  6. JavaScript进阶系列03,通过硬编码、工厂模式、构造函数创建JavaScript对象

    本篇体验通过硬编码.工厂模式.构造函数来创建JavaScript对象. □ 通过硬编码创建JavaScript对象 当需要创建一个JavaScript对象时,我们可能这样写: var person = ...

  7. JavaScript进阶系列02,函数作为参数以及在数组中的应用

    有时候,把函数作为参数可以让代码更简洁. var calculator = { calculate: function(x, y, fn) { return fn(x, y); } }; var su ...

  8. JavaScript进阶系列01,函数的声明,函数参数,函数闭包

    本篇主要体验JavaScript函数的声明.函数参数以及函数闭包. □ 函数的声明 ※ 声明全局函数 通常这样声明函数: function doSth() { alert("可以在任何时候调 ...

  9. JavaScript学习系列博客_20_JavaScript 作用域

    作用域 - 作用域指一个变量的作用的范围 - 在JS中一共有两种作用域 1.全局作用域 - 直接编写在script标签中的JS代码,都在全局作用域- 全局作用域在页面打开时创建,在页面关闭时销毁 - ...

随机推荐

  1. HTML5 Web app开发工具Kendo UI Web中如何绑定网格到远程数据

    在前面的文章中对于Kendo UI中的Grid控件的一些基础的配置和使用做了一些介绍,本文来看看如何将Kendo UI 中的Grid网格控件绑定到远程数据. 众所周知Grid网格控件是用户界面的一个重 ...

  2. dr.wondr博士随笔之某古旧非智能机T6XXX 恢复一例

    大家好!欢迎再次来到dr.Wonde的微博! 今次我给大家带来索尼爱立信古董机T650i的取证工作展示! 首先请出今天我们的主角索尼爱立信 T650i>> 然后在工厂模式下,连接设备,看图 ...

  3. zabbix_sender自定义监控

    这里推荐这个博客 http://www.ttlsa.com/monitor/zabbix/ 在这里学一遍都不用买书,直接就能玩转zabbix了 回归正题 zabbix相关包下载地址:http://ww ...

  4. CentOS 6.5 安装HDFS集群(Hadoop-2.7.3)

    安装真实集群,而不是但节点或者伪分布式,以3个节点为例,node1为NameNode和SecondNameNode,node2和node3为DataNode. 1.3台机器的配置必须要一模一样,只需要 ...

  5. LR中线程和进程的区别

    LoadRunner中的进程与线程    1.进程与线程的区别: 进程和线程的区别是什么?进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性.进程和线程的区别 ...

  6. Python作业 1

    用户有三次机会登录,登录成功,显示欢迎界面. 三次登录失败,账户被锁定,下次登录失败. 思路: 1:流程控制:for或者while循环,达到三次检测目的. 2:文件操作. 检测文档,一旦发现输入账户名 ...

  7. 使用AFNetWorking 实现以Basic Authentication方式获取access-token

    由于服务器端对于调用API获取数据接口进行了限制,需要在调用API之前获取一个access-token,所以需要在iOS里实现获取这个access-token的功能. 服务器端是在ASP.NET中基于 ...

  8. 使用AFNetWorking读取JSON出现NSCocoaErrorDomain Code=3840的解决方法

    最近在使用AFNetworkWorking读取JSON时,出现了NSCocoaErrorDomain Code=3840的错误.这种错误应该是服务器端返回JSON格式不对造成的.通过Google搜到这 ...

  9. Netty : writeAndFlush的线程安全及并发问题

    使用Netty编程时,我们经常会从用户线程,而不是Netty线程池发起write操作,因为我们不能在netty的事件回调中做大量耗时操作.那么问题来了 – 1, writeAndFlush是线程安全的 ...

  10. WebForm Application Viewstate 以及分页(功能性的知识点)

    Application: 全局公共变量组 存放位置:服务器 特点:所有访问用户都是访问同一个变量,但只要服务器不停机,变量一直存在于服务器的内存中,不要使用循环大量的创建Application对象,可 ...