js基础-类型、值和变量(下)

pic-2017-10-17.jpg

15、变量

首先,我们需要了解一下变量的定义:

变量是存储信息的容器。

为什么需要变量呢,不止js里面,程序里面的数据来源都要有根有据,比如

alert(a);

为什么会发生错误呢,a是什么东西,有声明过了吗,所以也就需要变量来存储数据了,让数据来源有根据,而不是无中生有(当然也有特殊情况,下面我们在讨论)。在js程序中,如果我们使用变量之前会先声明变量。

变量的声明用var关键字。
var a="";
var b=true;
var fn=function(){ //dosomething}
var date=new Date();
var obj={};
var arr=[];
var num=123;
var nullStr=null
var uf=undefined;
var pat= /\d+/;//匹配一个或多个数字

比如从上面可以看出,变量的类型是任意的,js是弱类型语言,js的变量可以是任意类型的。
上面代码,多数用到var,我们可以简写多个变量声明的方式,比如

var a=1;
var b=2;//等价于var a=1, b=2;

值得注意的是:如果围在var什么语句中给变量赋值,也就是只是声明了,但没有值,那么在给这个变量赋值之前,这个变量的值是undefined

var a;console.log(a); //undefined

这里涉及到了变量的什么提前的知识,有兴趣的可以参考我之前写的文章js(四):提升。这里我们不深入研究下去。
当我们使用var对同一变量重复声明是没问题的;

var a=1;
var a=2;
var a=3;

这种重复声明和赋值有点类型我们css中,同名选择器的时候,后面的样式会覆盖前面的属性。

但是要记得的是,给一个没有什么过的变量赋值,在非严格模式下是没有错误的,但是在严格模式下会报错。

a=2;
console.log(a);
"use strict";
a=2;console.log(a);

上面例子,一个在非严格模式下执行的时候,a会变成window下的属性,也就是全局变量。

另一个在严格模式下执行,程序会报错。
因此,我们写代码的时候,应该始终使用var来声明变量。(关于这些知识,都涉及到了js更加深层次的知识与原理性的东西,以后我们会详细来研究)

既然我们用var声明了变量,那么这些变量的作用范围,我们可以先理解为变量的作用域了。

在全局作用域中声明的变量是全局变量,相对的也有局部变量。类似

var win="window"
function fn(){ 
      var win="obj"; 
      console.log(win);
}
console.log(win);
fn();
console.log(win);

在上面例子中我们假设,win所处的环境是全局环境,那么win就是全局变量,并且变量win的值为'windoq',而在函数fn里面的win变量所处于函数fn的局部环境中,所有里面的win是局部变量,第一个输出和第二个输出我们是毫无疑问的,第三个再次输出win也是全局的,因为两个所处不同环境的两个分别用var定义的win变量是不一样的。我们改一下代码可以看出区别:

var win="window";
function fn(){ 
      win="obj"; //改动地方 没有用win声明 
      console.log(win);
}
console.log(win);
fn();
console.log(win);

同名属性,在局部中没有用var什么,但是赋值了,也就相当于改变了全局作用域下的同名属性的值,所有执行函数fn后,win的值被改变了。

(值得注意的是,前面说过:在严格模式下,给未经声明的变量赋值会包类型错误,这个例子就算在严格模式下也不会保存,因为win已经在全局作用域下用var声明过了,函数体内仅仅只是赋值操作)。

15、函数作用域和声明提前

块级作用域

在一些强类型编程语言中,比如C,花括号{}内的每一段代码都有各种的作用域,而且变量在声明他们的代码段之外是不可见的,这就是块级作用域,而js在ES6之前的js版本是没有块级作用域的。这里我们先不涉及到ES6的知识,后面我们再详细了解。所以取而代之地使用了函数作用域。 变量再声明他们的函数体以及这个函数体嵌套的任何函数体内都是有定义的。例如

function foo(){
       var a=1; //这里面的变量只有再函数里面才可以访问
       var b=2;
}

js的函数作用域是指函数内声明的所有变量再函数体内始终可见,这意味这变量再声明之前甚至已经可用。js的这个特性别非正式的称为声明提前,即js函数里声明的变量(但不涉及复制)都被“提前"只函数体的顶部。我们直接看代码

var a="global"; //全局变量、
function foo(){ 
      console.log(a);
      var a="local" //局部变量 
      console.log(a);
}

第一个console.log输出什么?是undefined,而不是global或者local,而第二个毫无疑问是local了。
上述过程等价与:将函数内的声明提前至函数顶部,同时变量初始化留在原来的位置,有兴趣深入了解原理的同学可以参考我写的文章提升。

由于js没有块级作用域,因此我们常常可以见到别人写代码的时候将变量声明放在函数体顶部,而不是将声明靠近放在使用变量之外。这种做法使得他们的源代码非常清晰地反应真实的变量作用域

function foo(){
       var iTarget=null; //现在函数体顶部声明 
        ....
       iTarget=.... //只用用与赋值等等操作了
}
作为属性的变量

当声明一个JavaScript全局变量时,实际上是定义了全局对象的一个属性。当使用var声明一个变量时,创建的这个属性是不可配置的,也就是说这个变量无法通过delete运算符删除。可能你已经注意到了,如果你没有使用严格模式并给一个未声明的变量赋值的话,JavaScript会自动创建一个全局变量。以这种方式创建的变量是全局对象的正常的可配值属性,并可以删除它们:

var a = 1; // 声明一个不可删除的全局变量
 b = 2; // 创建全局对象的一个可删除的属性 ,(在严格模式下会报错)
this.c = 3; // 同上 delete a // => false: 变量并没有被删除 delete b // => true: 变量被删除 
delete this.c // => true: 变量被删除

为什么使用var的变量就不可配置了,这个涉及到了属性的特性的知识,有兴趣的朋友可以查下资料了解和深入下,这里我们简单的了解一下:

  1. 作为对象,每个属性(变量)下都有几个属性(属性的特性),其中configurable,这个属性确定了属性(变量)名字能否更改,变量能否被删除。true的话,可以更改,可删除;反之,不能更改,不能删除。
  1. 在用var 声明变量时,JS解析器会默认把configurable设为false,所以它不能改名字,不能被删掉。

js全局变量是全局对象的属性,上面在非严格模式下,this在全局下指向的是全局对象,(关于this指向这个知识,我们以后再来详细探讨)也就是window。

作用域链

简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。在学习作用域链之前,我们简单看几个例子了解下全局作用域和局部作用域。

全局作用域
var a="window";
functin a(){ //dosomethind}

假设上面代码代码的最顶级的位置(也就是没有任何函数嵌套,所有当前的作用域就是全局作用域),全局作用域就是在全局环境下变量与函数的可访问范围,这个范围就是控制着变量和函数的可见性和声明周期,任何在全局作用域下的都可以访问到全局变量a和全局函数a(),

局部作用域
function b(){ 
      var foo="123"; 
      function bar(){
             //dosomething
       }
}
console.log(foo) //报错 bar() 报错

我们知道,js里面函数也是对象,在函数花括号{}里面的定义的变量、函数等,我们在函数外面是访问不到的,这就是函数的局部作用域。和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部,所有在一些地方也会看到有人把这种作用域称为函数作用域。

局部作用域拥有对全局作用域的访问权限,在函数嵌套中,被嵌套的函数拥有对外层函数作用域的访问权限,比如

//全局作用域
function foo(){
       var a=1; //foo函数作用域(局部作用域) 
       function bar(){
             var b=2; 
             function fn(){
                   var c=3 
             }
         }
}

上面函数里面嵌套了多层函数,a、bar()是foo的局部变量,以此类推,变量c在fn()定义,fn()的作用域包含着fn()花括号{}里面的作用域、bar()、foo()和全局作用域,在fn中可以访问到变量它的外层作用域包括全局作用域,以此类推。

但是全局作用域不能访问到变量a以及所嵌套的标识符(变量、函数,对象等),我们把作用域想象成一条线条,他们组成了一个单向的,由内而外的线,如



图中,黄色的线的箭头代表可以访问的作用域,他们形成一系列的链条就是作用域链了(本人理解),作用域链定义了一系列作用域嵌套时候,变量与函数的可见性和生命周期。

当定义一个函数时,它实际上保存一个作用域链。当调用这个函数时,它创建一个新的对象来存储它的局部变量,并将这个对象添加至保存的那个作用域链上,同时创建一个新的更长的表示函数调用作用域的“链”。对于嵌套函数来讲,事情变得更加有趣,每次调用外部函数时,内部函数又会重新定义一遍。

js基础-类型、值和变量到这里了。
如有错误,欢迎批评,对本文有什么不理解的地方话也可以留言评论交流!!!
原创文章by zhengyepan
欢迎访问我的个人网站zhengyepan.com
欢迎讨论交流~

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

推荐阅读更多精彩内容

  • 我眼中的js编程(1)主要介绍了js是用来做什么的,这一篇开始及以后总结js具体该怎么用。本篇总结了作用域内变量和...
    闫浩奇阅读 523评论 0 5
  • 第一章: JS简介 从当初简单的语言,变成了现在能够处理复杂计算和交互,拥有闭包、匿名函数, 甚至元编程等...
    LaBaby_阅读 1,628评论 0 6
  • 个人理解的基础功能有:1: GPS信号获取的稳定性,以及丢失后的轨迹弥补算法;2: GPS漂移信号的过滤以及修正;...
    知否读书阅读 690评论 0 0
  • 好久没有写东西了,感觉忘了写东西的感觉,就像忘了理想一般。前一个月我还生活在希望之中,可生活还是生活。回家一趟突然...
    107fe232d81b阅读 484评论 0 0
  • 今天写的这些,算是一篇随笔,一篇关于无常的自白。 文/蔷薇Viki 我总觉得,做什么事情都有第一步。很多事情很难,...
    蔷薇笔迹阅读 840评论 4 3