最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 【轻聊前端】小角色,大用途——变量

    正文概述 掘金(灵感__idea)   2021-02-27   448

    上篇文提到,不论什么程序语言,都在做三件事:

    数据存储、数据处理、数据传输

    本文就聊存储。

    存储,即为数据找到一个空间来存放,这个空间的载体就是“变量”。

    JavaScript发展到现在,数据类型没有大的变化,但声明数据的方式发生过明显变化。

    先看数据类型。

    数据类型

    JavaScript当中的数据类型有7种(原本是6种,ES6之后新增一种):

    字符串(String)、数字(Number)、布尔(Boolean)、Null、Undefined、符号(Symbol)、对象(Object)

    它们又分为基础类型引用类型

    基本类型可理解为——不可再分的,不包含任何其他类型的类型,存在空间中的就是值本身。

    如:String、Number、Boolean、Null、Undefined、Symbol

    而引用类型,存的是一个地址,这个地址又可以存放各种不同类型的数据,包括“基本类型”和“引用类型”。

    如:Object、Array等。

    用一个简单的例子来看它们的区别。

    基本类型

    var a = 3;
    var b;
    b = a;
    a = 4;
    console.log(a);  //4
    console.log(b);  //3
    

    引用类型

    var c = {
        name:'张三'
    } 
    var d;
    d = c;
    console.log(d.name);  //张三
    c.name = '李四';
    console.log(d.name);  //李四
    

    可以看出,基本类型在传递时,相当于把值拷贝了一份,二者相互不影响,而引用类型的赋值行为仅仅传递了地址,它们指向的仍是同一个空间,所以一个变另一个也会变。

    注意措辞:“赋值行为”。并非不能够做到相互不影响,只是单纯地“赋值”做不到。

    这就引出了前端圈经常讨论的话题——深拷贝浅拷贝,先提一下,不细说,领会引用类型是什么即可。

    关于基本数据类型,看似不打眼,但几乎每份前端笔试题里都会有它,也正因为平时不太在意,写错、写漏、多写的情况经常发生,应该怎么记呢?

    • String和Number很好记,只有数字能够进行数学运算,而字符串通常用来表示文本信息。

    • Boolean,用于条件判断,true(真)/false(假)。

    • Null,只有值null;

    • Undefined,只有值undefined;

    前面三种较好理解,只需注意后两种。

    从逻辑上说,null是空对象指针,访问不存在的对象时会是null,也常用null来初始化一个尚未赋值的对象;

    Undefined是为了区分null和未赋值变量而添加的,“未赋值变量”包括基本类型变量、数组中没有值的索引位及未定义值的对象属性等。

    如此以来,前五种基本类型就记住了,再加上ES6新增的Symbol,就是完整的基本类型。

    至于同样很常见的Object、Array、Function之类,都不是,为什么,它们符合“不可再分,不包含任何其他类型”吗?显然不~

    变量声明

    ES6之前,声明一个变量只能用 var 关键词,ES6之后多了 let 和 const。

    后两者和前者的区别就是,后两者使得JavaScript当中具备了块级作用域

    提到“块级作用域”,就先讲一下什么是作用域

    顾名思义,作用域就是能够起作用的区域,起什么作用?——可获取,可操作

    作用域跟什么有关呢?跟在哪里声明有关,即声明位置决定作用域

    而且作用域遵循“由内向外”的查询规则,先就近在小的范围查询,查不到再往外,直到全局作用域。

    ES6之前,JavaScript当中最为大家熟知的就是“全局作用域”和“函数作用域”。

    var

    比如:

    • 在代码的最外层定义一个变量a
    var a;
    

    它就属于全局,其他任何代码都可以对其进行访问或者修改。

    • 在函数当中定义一个变量a
    function test(){
      var a = 10;
    }
    test();
    console.log(a)  //Uncaught ReferenceError: a is not defined
    

    会得到a并没有定义的报错。

    但也存在另一种“疏忽”的情况,就是未使用 var 关键字

    function test(){
      a = 10;
    }
    test();
    console.log(a)  //10
    

    这时a会暴露到全局,又可以被访问,这类疏忽最好不要犯。

    只有“函数”才有自己的作用域吗?严格说不是,但因为那些语句少有使用场景且背离最佳实践,所以暂不了解也没有影响。

    letconst

    ES6之前没有真正被广泛定义的“块级作用域”。

    “块”是指“代码块”,被大括号包裹起来的一段代码可以看做一个代码块。如if、while、function等。

    JavaScript当中的变量除了被定义在全局,就是被包裹在各种代码块中,但并不代表它们被限制在了代码块中。

    let、const,和var最明显的三点不同。

    • 将变量限制在了代码块
    • 不可重复定义
    • 不会被提升

    一个个看.

    块作用域

    
    if(true){
        let a = 4;
        const b = 6;
    }
    console.log(a,b)  //undefined undefined
    

    我们在if条件判断的代码里定义了两个变量a,b,外部访问均为undefined,这说明,在if代码块的外部无法正常访问代码块内定义的变量。

    重复定义

    if(true){
        let a = 4;
        var a = 6;
    }
    Uncaught SyntaxError: Identifier 'a' has already been declared
    

    变量a已经被let声明,就不能再次被声明。

    不被提升

    前面没有说提升,放在这里刚好做比较。

    使用 var 声明的变量,在其作用域内会被提升到最顶部,以便被其他代码使用。

    function test(){
      console.log(a)  //undefined
      var a = 10;
    }
    test();
    

    咦,这不是 undefined 么,也不是 10 啊,提升到哪了?

    “坑”就在此。

    var a;  //这叫'声明'
    var a = 10; //这是在声明的同时定义初始值
    

    所以,提升只是声明被提升,而赋值未提升,才会看到上面输出的是undefined。

    当然,变量提升不止如此,函数(function)同样,可以在声明函数的前面使用,到函数部分再详聊。

    上面说了最明显也是最重要的三个区别,还有一个区别,即在全局定义变量时,使用 var ,变量属于全局对象 window,而使用 let 和 const 不会这样。

    再来看 let 和 const

    function test(){
        console.log(a,b);
        let a = 10;
        const b = 10;
    }
    test();  //Uncaught ReferenceError: Cannot access 'a' before initialization
    

    这段代码甚至没走到声明变量的地方就报错了,在初始化之前不能访问变量a,就证明 let 和 const 的声明不会被提升。

    值得说明的是,虽然ES6之前的 var 存在提升的现象,但比较提倡的做法仍是在所属代码块的顶部将所有变量一起定义,而不是随意散落在代码段中,ES6中增加了 let 和 const 后更是如此,像这样:

    function test(){
       let a = "",
       	   b = 0,
           c = true;
       //其他代码
    }
    

    说完 let、const 和 var 的区别,说说 let 和 const 的区别。

    const 可看做 constant 的缩写,constant 的意思是“固定的、常量”,即不可修改。

    所以,const 在声明的同时必须赋值,且在使用范围内不可修改

    其实ES6之前,我们就需要在程序中定义常量,且约定常量使用大写字母和下划线结合的方式命名,比如:MAX_COUNT。

    至于是否可变,就靠程序员来遵守规则,程序员往往是不可靠的...

    const的出现从语言层面加了限制,使其不可更改。

    const a = 7;
          a = 8;
    //Uncaught TypeError: Assignment to constant variable.
    

    可以看到,用 const 定义了一个变量并赋值之后,改变它的值时就报错了。

    but,并不是用 const 声明的一切都不可更改,const声明的限制只应用到变量类型的最外层。换句话说,如果变量类型为基本类型,其本身不可更改,如果是引用类型,则引用类型本身受限制,键不受限制。

    像下面这样就可以正常运行。

    const a = {
        name:'张三'
    } 
    a.name = '李四';
    console.log(a.name)  //李四
    

    综上,现在定义变量依然可以使用 var,但多数项目中都已被 let 或 const 占据,所以,在确定值不变的情况下就用 const,否则可使用let。

    变量命名

    很多人在刚学编程时不会想到,命名会是个让人头疼的问题。

    有几个方面原因:

    一、本身词汇量匮乏

    二、每个变量都会有关联变量,无形中增加了用词量

    三、不仅意思要对,还不宜太生僻

    四、要考虑适用范围,较通用还是更具体,某种程度上也会形成一个“命名空间”。

    大致需要遵循如下几个原则:

    • 表意

    较为明晰地表达意思,比如:

    是什么,isXX

    有什么,hasXX

    干什么,getXX

    等等。

    • 统一/通用

    业界通用结合团队通用,这样一来,不论是团队进新人,还是你突然要介入一个新项目,都不用花太多时间或沟通成本来搞懂程序的意图和逻辑。

    • 少定义全局

    一、全局变量是一直存在的,长期占用内存。

    二、全局变量全局可用,这就为其修改增加了不确定性,增加了意外出现的风险。

    所以多数情况下,我们只需定义必要的全局变量,其他变量定义在局部就好。

    • 少定义变量

    语言本身对变量的定义是不限制的,所以容易变得随意,减少不必要的变量定义,可以适量减少存储空间、传递次数和处理环节。

    但也不必矫枉过正,还是要兼顾“简洁、高效、易读”,仅仅简洁了,却很难读,就得不偿失了。

    附赠

    • 常见面试题之 变量如何存储?

    基本类型存储在中,引用类型存储在中。

    栈:只能在某一端进行添加或者删除的数据结构,比较形象的比喻是“叠盘子”,后进先出。存取速度较快,但数据大小和生命周期确定。

    堆:生活中有“书堆”、“垃圾堆”等,指可动态分配的空间,用于动态分配和释放程序所使用的对象。因为对象可以扩展,放在堆中可以不断扩展。

    • 常见面试题之 for循环——输出几?
    for ( var i=1; i<=5; i++) { 
        setTimeout( function timer() { 
            console.log( i ); 
            }, i*1000 ); 
    }
    

    setTimeout是定时器函数,由“时间间隔”和“回调函数”组成,可以在某间隔时间后执行特定动作,如上是打印一个值。

    按道理,这段代码应该是隔一秒输出一个数字,从1到6。

    实际情况是,连续输出5个6,为什么?

    一、for中用var定义的变量会泄露到全局

    二、setTimeout是异步函数,javascript代码在浏览器中执行的任务是有优先顺序的,当异步函数执行的时候,外层循环已经进行完毕,即i的值已经被加到6。

    ES6之前,解决这个问题的常见方法是“闭包”,这个后面会聊,但ES6之后,有了更方便的处理方案,就是使用let来声明变量i。修改如下:

    for ( let i=1; i<=5; i++) { 
        setTimeout( function timer() { 
            console.log( i ); 
            }, i*1000 ); 
    }
    

    这个时候,当循环每进行一次,变量i都进入了一个独立的作用域当中,然后被单独输出,就会得到预期的结果。

    总结

    到此,关于“变量”的讨论告一段落。

    标题叫“小角色,大用途”,因为变量就像是程序大楼的一砖一瓦,很不起眼,却无处不在。

    常用的数字、字符、对象、函数、数组等等,不论简单或是复杂,都是数据,都存储在变量中。

    不仅如此,变量还能起到“缓存”的作用,比如,经常会获取页面DOM元素的时候将其保存在一个变量内,然后拿这个变量去做其他的事,或者把从数据库当中请求回来的值存到一个变量中,后续再用直接拿变量的值,毕竟DOM查询和发请求拉数据都需要时间,这无疑节省了时间。

    编程正是由于变量的存在而被赋予无限可能,如果没有变量,都是固定的值,就没有变化和个性可言,有了变量,就能在需要的时候产生不同的数据,构成各种丰富的、个性化的网页内容。

    聊的够多了,我们下篇见。

    博文链接:【轻聊前端】小角色,大用途——变量

    上一篇:【轻聊前端】打好基本功,跟我轻松学原生


    起源地下载网 » 【轻聊前端】小角色,大用途——变量

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元