JavaScript中的变量

一、变量是什么?

一个变量,就是一个用于存放数值的容器。这个数值可能是一个用于累加计算的数字,或者是一个句子中的字符串。变量的独特之处在于它存放的数值是可以改变的。

变量不是数值本身,它们仅仅是一个用于存储数值的容器。你可以把变量想象成一个个用来装东西的纸箱子。

 

二、声明变量

  • 想要使用变量就需要先声明它,ES5之前使用var关键字来声明变量,现在也可以使用let关键字声明变量。
  • 声明一个变量的语法是在 var 或 let 关键字之后加上这个变量的名字。
    • 检查某个变量是否存在的方法是使用这个变量,如果在运行环境中没有这个变量,就会得到一个报错信息。
Var 变量名字;

Var number; //变量的声明,没有赋值

 //一次性声明多个变量

Var x,y,z,k,j; //都是声明,没有赋值

变量初始化(有var 有变量名字,有值):

变量声明的同时并且赋值了

//存储一个数字

 var number=10;

 //存储一个5

 var number2=5;

 //存储一个人的名字

 var name="小黑";

 //存储真(true)

 var flag=true;

 //存储一个null--->相当于是空

 var nll=null;

 //存储一个对象

 var obj=new Object();

var 会产⽣很多错误,所以在 ES6中引⼊了 let 。let声明的变量不能在声明前使⽤,但是这并不是常说的 let 不会提升,let提升了,在第⼀阶段内存也已经为他开辟好了空间,只是因为这个声明的特性导致了并不能在声明前使⽤

声明变量类型

当您声明新变量时,可以使用关键词 "new" 来声明其类型:

var carname=new String;
var x=      new Number;
var y=      new Boolean;
var cars=   new Array;
var person= new Object;

 JavaScript 变量均为对象。当您声明一个变量时,就创建了一个新的对象。

JavaScript 允许重复声明变量,后声明赋值的覆盖之前的,变量不能重名

var a = 1;
var a = 'x';
console.log(a);
// 输出 'x'

 

三、初始化变量

  • 为新声明的变量赋值就是初始化变量。

 

四、变量的命名规则和规范
  
(一)规则 - 必须遵守的,不遵守会报错

 命名规则:

  • 由字母、数字、下划线、$符号组成,
  • 不能以数字开头
  • 必须以字母开头,$和_符号可以开头,但是不建议这么做
  • 不能是关键字和保留字,例如:for、while。
  • 区分大小写(y 和 Y 是不同的变量)

 

(二)规范 - 建议遵守的,不遵守不会报错

  • 变量名必须有意义
  • 遵守驼峰命名法。首字母小写,后面单词的首字母需要大写。例如:userName、userPassword
  • 应该有对应的数据类型。例如:数字型以小写n开头,var nNum=100; 字符串型以小写s开头,var sName=’小黑’;。


- 下面哪些变量名不合法

  a        //合法
  1      //不合法,因为以数字开头
  age18    //合法
  18age    //不合法,因为数字开头
  name    //不合法

//经过查找资料发现name具有特殊之处,它不是javascript的关键字,也不是保留字,页面在IE浏览器上运行正常,但是Safari,chrome,Firefox和Opera这些浏览器都给函数定义了一个非标准的name属性,是window的自带全局属性,所以在全局声明name变量名会出现访问异常问题。

 

五、变量的类型

全局变量、局部变量

名词:隐式全局变量

未经声明就直接使用的变量就叫隐式全局变量,隐式全局变量是可以被删除的。

/* javascript的关键字 */
break case catch continue default delete do else finally for function if in instanceof new return switch this throw try typeof var void while with

/* javascript的保留字 */
abstract boolean byte char class const debugger double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile

* 块级作用域:一对大括号就可以看成是一块,在这块区域中定义的变量,只能在这个区域中使用,但是在js中在这个块级作用域中定义的变量,外面也能使用;
* 说明:js没有块级作用域,只有函数除外


六、变量的提升

  *使用var 声明变量时存在变量提升,而使用let和const声明的变量和常量存在暂时性死区(TDC)

  在⽣成执⾏环境时,会有两个阶段。第⼀个阶段是创建的阶段,JS 解释器会找出需要提升的变量和函数,并且给他们提前在内存中开辟好空间,函数优先于变量提升,会将函数存⼊内存中,变量只声明并且赋值为 undefined ,在第⼆个阶段,也就是代码执⾏阶段,我们可以直接提前使⽤;

  应该尽量避免变量名和函数名同名,否则会发生相互覆盖的问题.从实际测试效果来看,这种覆盖可以分为两种情况:

  • 定义变量时只使用var定义变量,不分配变量初始值,此时函数的优先级更高,函数会覆盖变量;
  • 定义变量时为变量指定了初始值,此时变量的优先级更高,变量会覆盖函数.
  • 上面代码开始分别定义了名为a、b的函数和变量,由于定义变量a、b时并未指定其初始值,因此不管这些变量放在同名的函数名之前还是之后,变量都会被函数覆盖;

    代码接下来定义了名为c、d的函数和变量,由于定义变量时为c、d变量指定了初始值,因此不管这些变量放在同名的函数名之前还是之后,变量都会覆盖函数.

     

这就是变量和函数的预解析:

  • 变量声明会被顶置,函数声明也会被顶置且比变量更先声明。
  • 变量的声明和赋值语句一起写时,JS引擎在解析时,会将其拆成声明和赋值2部分,声明置顶,赋值保留在原来位置。
  • 声明过的变量不会再重复声明。
var a=1;
var a=2;
 
//赋值覆盖相当于:
var a;
//a=1;
a=2;
 
//声明覆盖相当于:
//var a=1;
var a=2;

JavaScript 允许变量被重复声明,在声明变量时 JavaScript 会自行判断这个变量是否已经被声明了,如果已经被声明(即已经存在),那么重复声明(即除了变量的非首次声明)会被跳过,不再执行声明的操作。

JavaScript 变量的值是可以被重复赋值的,最后的赋值是这个变量最后的结果。

 

JavaScript 允许重复定义函数

JavaScript 没有重载这个概念,它仅依据函数名来区分函数。

后定义的同名函数覆盖之前的,与参数无关。

var a = 100;
function a() {
    return "function";
}
console.log(a);     //输出 100
console.log(a());   
/*
报错
Uncaught TypeError: a is not a function
    (anonymous function) @test.html:9

 

变量提升和暂时性死区

  我们使用var声明变量,在声明之前可以使用,这种情况我们俗称:变量提升;

  使用let和const声明变量之前不能使用,会直接报错,我们称这种情况:暂时性死区。

  “变量提升”VS“暂时性死区”该如何定义?

  • 与通过  var 声明的有初始化值 undefined 的变量不同,通过 let 声明的变量直到它们的定义被执行时才初始化。在变量初始化前访问该变量会导致 ReferenceError。该变量处在一个自块顶部到初始化处理的“暂存死区”中。
  • JS代码是即时编译与执行的,一个函数作用域会拥有一个执行上下文,执行上下文是一块存储空间。执行上下文内又有一个名为[变量环境」和「词法环境」的东西。
  • 由var和function声明的变量,在代码编译完成后,执行之前,其变量名和值就被存储在变量环境中了,所以在代码执行阶段的任何时刻,都可以调用它们,自然也能在声明语句之前调用了。
  • 由const和let声明的变量,在代码编译完成后、执行之前,其变量名被存储在词法环境中,代码执行过程中会从依据[词法环境→变量环境→闭包/上一个作用域」的顺序来查找变量,而词法环境所存储的值被要求只有在声明语句之后才能调用。所以会存在暂时性死区,但变量又确确实实被执行上下文提前记住了,所以可以把暂时性死区理解为「变量暂时不能使用的阶段」

七、全局变量污染

  1. var定义变量时可以省略var关键字的特性,也就是变量可以不用var声明而直接使用,此时这个变量会默认当作window的属性,这就会导致变量污染;
  2. var声明变量时,同作用域中可以重复声明同名的变量,这也会导致变量的污染;
  3. 在全局作用域中使用var声明变量时,变量会自动变成window的属性,这会污染全局变量;
  4. 当代码非常多,开发周期长,你又不记得之前是否定义过这个变量,此时赋值之前定义过的变量就会污染全局变量。

解决全局变量污染可以通过几种方式:

  • 使用严格模式“use strict”
  • 使用立即执行函数IIFE(匿名函数自调用【闭包】Immediately Invokable Function Expressions)方式解决全局污染
  • 使用对象包裹

posted on 2019-12-13 11:02  前端码牛  阅读(102)  评论(0编辑  收藏  举报

导航