欢迎访问万博易官网

关键字

JS怎么使用单个let或者const关键字同时给多个变量赋相同的值?

发布时间:2020-04-02 23:02

y = x;

2、声明变量与非声明变量区别

变量声明定义的时候无论出现在代码的什么位置,都会在执行代码之前,将声明的变量添加到当前执行环境的作用域(上下文)中,该变量与undefined绑定在一起除非到了执行变量初始化语句或者除非之前已经声明了这个变量,添加带作用域中的变量是不可配置的,这就是变量提升。在使用该变量的时候,会解析执行表达式,返回值,这个值可能是没有经过执行初始化的undefined。返回undefined也很好的提醒程序员该变量没有初始化。

非变量声明不会再执行之前处理,永远是在执行的时候进行处理。也就是说,当在执行代码的时候,遇到了一个未经声明的标识符,经过解析执行创建这个标识符,在严格模式下会直接返回引用类型错误,非严格模式下,会在全局对象中添加这个标识符和对应的值这个变量是可以配置的。在使用这个变量的时候,如果在创建之前使用,无论是否在严格模式下都会抛出异常。

以下是详细描述:

(1)声明变量在执行代码之前解析创建,所以变量提升;非声明变量在执行时候解析创建,不存在变量提升。

console.log(x,y); // x undefined y 抛出异常

var x = 12;

y = 34;

console.log(x,y);// 12 34

因为在执行之前进行的变量定义初始化,所以x,但是执行的时候由于没有执行x = 12所以x为undefined;但是对于y来说是在执行的时候才会创建的,所以在创建之前使用只能抛出异常。当执行完x = 12,执行y = 34.会发现y没有创建,所以会尽可能的去创建它,由于在非严格模式下,所以得逞了。之后再使用x,y都会被赋值了。

(2)声明变量是被创建在当前执行环境的词法作用域中,非声明变量在严格模式下不会创建抛出异常,在非严格模式下会作为属性创建在全局对象中。

function f(){

f = 12;

var z = 2;

}

f();

z = -1;

console.log(f,z);//12 -1

函数中f变量是非声明变量,所以在非严格模式下降添加到全局对象中作为一个属性而存在,但是函数中的z则添加带f函数所创建的执行环境中,所以在函数外部无法访问到。值得注意的是,虽然在函数外部也定义了一个z = -1但是这个z不是通过声明变量定义的,所以也会添加到全局对象中。

(3)声明变量所在的词法环境是不可配置的,而非声明变量所在的全局对象是可以配置的。所谓的配置就是指可以删除该属性,或者修改该属性的特性。

var x = 12;

z = -1;

console.log(x,z);//12 -1

delete x;

delete z;

console.log(x,z);//z is not defined证明z删除了但是x没有删除

(4)没有执行初始化的声明变量typeof为undefined,但是非声明变量也为undefined

console.log(typeof x);//undefined

console.log(typeof z);//undefined

var x = 12;

z = -1;

3、注意事项

(1)尽可能的使用声明变量方式进行变量声明,摒弃非声明变量的方式,只有这样才能不会将变量添加到全局中去污染全局变量属性,以便发生意想不到的效果,并且还可以提高性能。

(2)通过使用严格模式可以限制上述问题之外,还可以提醒程序员使用变量声明,防止使用未经声明的变量。

(3)不能依赖于变量提升。

(4)应该避免重复声明相同的变量,最多使用赋值语句对变量值的修改。

(5)由于javascript是一个弱类型的语言,所以在覆盖变量值得时候尽可能不要更改一个变量的类型。

(6)注意的是typeof检测一个变量的类型,如果为undefined的话,除了这个变量声明了但是没有初始化的意思之外,很可能该变量使用过非声明变量方式创建的,或者这个变量就是不存在。

所以总结一句就是在严格模式下使用var声明变量,不能依赖于变量提升、js弱类型、typeof检测undefined、不能重复声明变量。

可以看出ES5标准中的var存在的问题是不少的,但是最重要的一个问题就是没有块作用域这一概念,这完全取决于之前的设计,因为在ES5标准中仅仅说对全局、函数、eval、catch块才会创建词法环境,对于for等语法块是不创建的,导致不存在块级作用域从而使用很耗性能的闭包代替。在ES6中出现了let关键字声明变量,这个可以解决一些问题。

二、使用let声明变量

1、详细介绍

在执行之前,只要进入一个块级作用域比如全局、函数、{}等。不会和var一样对let进行所谓的变量提升,而是将通过let声明的变量标识符保存起来,以便于判断接下来是否含有命名冲突,也服务于‘暂存死区’,直到开始执行代码。到执行到声明语句的时候,才会正式的创建,如果没有初始化则赋值为undefined,否则初始化标识符。(对于为什么赋值为undefined而不是null或者其他,前面文章中有介绍)

对于全局变量中的let不会添加到全局对象中去。这是和全局中的var的区别之一,对于全局中的var,在执行代码之前会将标识符添加到与这个执行环境绑定的词法环境中去,但是又因为这个词法环境与全局对象是绑定在一起的,所以会将全局的变量声明都作为全局对象的属性存在。Let声明的变量和var不一样,他并不会去破坏全局对象,而是当执行到let语句的时候创建一个块词法作用域,而将let声明的变量添加到这个词法作用域中去。

var x = 'global';

let y = 'global';

console.log(this.x); // "global"

console.log(this.y); // undefined

在全局中使用let,避免了将全局属性添加到全局对象中,减少了对全局对象的污染。

在执行代码之前,定义绑定初始化的时候,在处理let声明表达式的时候,如果该表达式在当前处理的词法环境中存在则抛出异常。在E5标准中,如果对同一个变量进行了两次声明是不会报错的只不过后一个声明仅仅当做赋值表达式在使用,这个会产生一些问题,比如发生了命名冲突还不知道,导致代码逻辑错误,从而只能依托程序员提高警惕避免重复命名。E6中的let很好的避免了这种重复声明的问题,只要在let声明之前无论什么方式创建的变量,只要与let声明语句位于同一个块中,同名就会抛出异常。

if (x) {

let foo;

let foo; // 冲突

}

switch (x) {

case 0:

let foo;

break;

case 1:

let foo; // 冲突

break;

}

这个switch中所有的case都处于同一个块作用域中的,这个要注意了。

function f(foo) {

let foo; //与参数冲突

}

f(12);

var x = 12;

let x = -1;//与var声明的变量冲突

function f() {

var x = 12;

if (true) {

let x = -1;//不在同一个块作用域不冲突

console.log(x);//-1

}

console.log(x);//12

}

f();

TAG标签:怎么(21)多个(7)同时(5)关键字(29)或者(2)使用(15)const(2)单个(1)变量(1)

上一篇:上一篇:一加6/6T国行正式推送安卓10稳定版 新增短信关键字拦截

下一篇:下一篇:盘点“党建2015”五个关键字:严实规责廉