js基础阵营:变量篇之变量作用域

上面已经介绍完了变量的定义,说完定义肯定要说下变量的常见的问题。其实变量的常见问题说来说去也就那么几个,变量作用域,变量提升。这就跟前面说到张无忌的乾坤大挪移一样,用来用去也就那么几招。那么我们首先来看变量作用域

1.变量作用域

为了理解什么是变量作用域,我们首先要搞明白一个概率-'执行环境'。故名思议,执行环境就是我们要处理一件事所处的环境,举个栗子:我们去TAM取款机取钱,那么ATM机器就是一个执行环境,一个执行取钱命令的环境。那么这个环境中包括哪些东西呢?ATM取款机这个执行环境中呢就包括钱,以及如何取钱这个操作。那么我们类比到我们的js中,我们就不难明白什么是执行环境,执行环境就是定义了变量(钱)或者函数(取钱操作)的一个范围。
理解了执行环境,那么我们变量作用域也很好明白了,那就是变量所能操作(读取)的一个执行环境。那么我们常见的变量作用域有哪些呢?在ES5时代变量的作用域有两种:全局作用域以及函数作用域,在ES6时代引入了块级作用域的概率,下面我们来一个一个来剖析

1.1全局作用域

全局作用域就是在最外层的一个执行环境,js代码运行宿主不同(js可以在浏览器运行也可以在node环境中运行)表示的执行环境也不同,在浏览器中我们说到的全局作用域就是指window对象,因为所有的变量以及函数都是作为window对象的属性和方法来创建的,我们来看一下代码

var name = '二锅头';
console.log('window.name的值为:' + window.name);

我们把代码复制到浏览器的控制台就能得到一下结果:



这个时候我们就能看到其实我们定义的变量name变成了window的一个属性。所以只要能访问到window的地方都能使用我们的name属性。这也就是为什么叫全局作用域的原因。

1.2函数作用域

函数作用域,说简单点就是函数的执行环境。还是用前面银行取钱的例子,我们取钱这个动作可以理解为一个函数,我们在这个取钱(函数)中,我们进行了输入密码,插卡等等操作,那么我们输入密码这个只能是在取钱这个动作中有效。你把卡放到另一个环境中这个密码就无效了对吧。所以函数作用域就是属于这个函数的全部变量都可以在这个函数内部使用。当脱离了这个函数,函数中原有的函数变量都无效。我们来看下代码

  var number= 1;
  function sayHello() {
     console.log(number)
     var testName= '二锅头';
     console.log(testName)
  }
 sayHello();
 console.log(number);
 console.log(testName);

我们来看下结果是什么


image.png

我们可以清洗的看到在函数sayHello中定义的变量name,在外部输出打印的时候会报错,提示没有定于,那么说明了什么?说明了这个name仅仅存在于sayHello这个函数中。形成了一种很奇特的块作用域。

1.3块作用域

顾名思义,块作用域是在一个固定的区域内有效,在js中通常是一个\color{blue}{\{\\}\}内部中为一个块作用域。我们来看下下面的代码

   var password = '123456';
   if(password  === '123456') {
     let testName = '二锅头';
    console.log(testName + '你的密码是对的!');
  }
console.log(testName);
image.png

所以我们可以看到,testName当前仅仅在if这个块({})中有用,在外部的时候依旧会提示未定义。所以在我个人的理解里,ES6通过let以及const相当于'劫持'了变量,从而胁迫变量成为一个块作用域。可以理解你去取钱,有人抢银行,把你的密码抢走了,胁迫你取钱了

深入探讨下1

至此,js的三大作用域都结束了,但是真的结束了吗?深究下,为什么会出现以上作用域,原理是什么呢?


image.png

开头我们已经说过了,执行环境。我们可以理解为没一个作用域都是有对应的执行环境,全局作用域是最大的执行环境,每个函数有函数的执行环境,每个块级作用域有自己的执行环境,当程序执行定义全局变量的时候,会将全局环境中的变量推入到一个全局环境中,当执行完成后,弹出,返回之前的执行环境,因此我们可以用下图来表示


image.png

我们在深入下,程序是如何知道怎么处理的呢?在js中,我们永远逃脱不了一个东西---链。同样的在作用域中同样有一个链,那就是作用域链。当程序在一个环境中执行的时候,就会创建一个作用域链,通过这个作用域链来保证在此环境中有权访问所有的变量和函数。作用域链的前端永远是当前执行环境的变量对象,例如:当环境是一个函数的时候,其作用域链的前端是arguments对象。作用域链的下一个是下一个环境中,直到全局环境中。我们看下面例子。通过例子来了解
var a = '全局环境';
function test(){
   var b = "test环境";
   test1();
  function test1() {
      var c = 'test1环境'
  }
  var d = "test环境"
}
test();
var e = "全局环境"

那么作用域链是什么样的呢?
初始化的时候作用域链是全局(window),然后执行到test环境中的arguments,,然后是test中的b,然后是test1环境中的arguments,然后是test1环境中的C,然后进入test环境中的d,然后进入全局环境中的e。

深入探讨2

既然我们上面也说到了作用域链的问题,那么我们是否可以人为的改变作用域链呢?思考下,怎么改变呢?那就是当执行到某一环境的时候,人为的去将环境给改掉。js提供三种方法

eval(string)

此方法,传入一字符串,将其中的内容执行,并写入执行的地方,在写的代码中的程序中生成并运行,就好像此代码就在此位置,如下代码

function test(str,a) {
    eval(str);
    console.log(a,b)
}
var b = 2;
test('var b = 3;',1)

输出结果为
image.png
with(obj)

此方法,通常被当做应用同一个对象多个属性的快捷方法,如下代码

var obj = {
  a:1,
  b:2
}
function test(obj) {
   with(obj) {
      a = 2;
  }
}
test(obj);
console.log(obj)

结果为:
image.png

我们来将上面的代码稍微处理下

var obj = {
  a:1,
  b:2
}
function test(obj) {
   with(obj) {
      c = 2;
  }
}
test(obj);
console.log(c)

这个时候我们会发现什么?会发现C值为2,也就是出现了泄漏问题,泄漏到了全局环境中去了

try catch

抛出异常,如下代码

try{
  undefined();
}catch(err){
  console.log(err)
}
console.log(err);

结果是
image.png

所以catch中的作用域为一个独立的块级作用域
至此关于作用域的问题也讲完了。下一章,我们将讲解变量提升问题

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 224,861评论 6 522
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,263评论 3 402
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 172,033评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,999评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 70,000评论 6 400
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,483评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,850评论 3 428
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,827评论 0 279
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,366评论 1 324
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,404评论 3 346
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,525评论 1 355
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,130评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,853评论 3 338
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,293评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,426评论 1 276
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 50,082评论 3 381
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,590评论 2 366

推荐阅读更多精彩内容