ES6的变量声明

在ES5中,变量声明只有var和function以及隐式声明三种,在ES6中则增加了let,const,import和class四种,以下来介绍着七种变量的声明。

var



ES5中最原始的变量声明,用于声明变量,其实JavaScript是弱类型语言,对数据类型变量要求不太严格,所以不必声明每一个变量的类型(这就是下面说的隐式声明,当然这并不是一个好习惯),在使用变量之前先进行声明是一种好的习惯。

1.作用域

使用var声明的变量的作用域是函数作用域(在ES5时代,只有函数作用域和全局作用域两种作用域),在一个函数内用var声明的变量,则只在这个函数内有效。

function test(){
    var a;
    console.log(a);//undefined
}
console.log(a);//ReferenceError: a is not defined

2.变量声明提升

用var声明变量时,只要在一个函数作用域内,无论在什么地方声明变量,都会把变量的声明提升到函数作用域的最前头,所以无论使用变量在变量声明前还是声明后,都不会报错(当然只是声明提前,赋值并没有提前,所以如果使用在声明之前,会输出undefined,但不会报错)。

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

隐式声明



当没有声明,直接给变量赋值时,会隐式地给变量声明,此时这个变量作为全局变量存在。

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

当然要注意,隐式声明的话就没有变量声明提前的功能了,所以下面的使用是会报错的。

function test(){
    console.log(a);//ReferenceError: a is not defined
    a=3;
}

function



用function声明的是函数对象,作用域与var一样,是函数作用域。

function test(){
    function a(){
        console.log(‘d‘);
    }
    a();//‘d‘
}
a();//ReferenceError: a is not defined

同样,function声明也有变量声明提升,下面是两个特殊的例子:

function hello1(a){
       console.log(a); //[Function: a]
    function a(){}
    console.log(a);//[Function: a]
}
hello1(‘test‘);   

function hello2(a){
       console.log(a); //test
    var a=3;
    console.log(a);//3
}
hello2(‘test‘);

这里有涉及到函数中形参的声明,我们可以将以上两个例子看成:

function hello1(a){
    var a=‘test;
       console.log(a); //[Function: a]
    function a(){}
    console.log(a);//[Function: a]
}
hello1(‘test‘);   

function hello2(a){
    var a=‘test;
       console.log(a); //test
    var a=3;
    console.log(a);//3
}
hello2(‘test‘);

可以看到函数对象的声明也提前了,但是在形参变量声明之后(形参的变量声明在所有声明之前)。

当函数对象和普通对象同时声明时,函数对象的声明提前在普通对象之后。

function test(){
    console.log(a);//[Function: a]
    function a(){}
    var a;
    console.log(a);//[Function: a]
}

let



ES6新增的声明变量的关键字,与var类似。

当然,与var也有很大区别:

1.作用域不同

let声明的变量的作用域是块级作用域(之前的js并没有块级作用域,只有函数作用域和全局作用域),var声明的变量的作用域是函数作用域。

{
  let a = 10;
  var b = 1;
}

a // ReferenceError: a is not defined.
b // 1

2.不存在变量声明提升

用var声明变量时,只要在一个函数作用域内,无论在什么地方声明变量,都会把变量的声明提升到函数作用域的最前头,所以无论使用变量在变量声明前还是声明后,都不会报错。而let不一样,与java以及其他语言一样,let声明的变量,在未声明之前变量是不存在的。(js的语法越来越向java靠拢)

console.log(a); // undefined,但是不报错。
console.log(b); // ReferenceError: b is not defined.

var a = 2;
let b = 2;

注意:在使用babel时可能会遇到这样的情况:

console.log(b); //undefined
let b = 2;

babel在翻译es6时,似乎直接将let变为了var,所以运行时也有变量声明提升了,但是在Chrome下运行时是正确的。

3.暂时性死区

所谓暂时性死区,意思是,在一个块级作用域中,变量唯一存在,一旦在块级作用域中用let声明了一个变量,那么这个变量就唯一属于这个块级作用域,不受外部变量的影响,如下面所示。

无论在块中的任何地方声明了一个变量,那么在这个块级作用域中,任何使用这个名字的变量都是指这个变量,无论外部是否有其他同名的全局变量。

暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

暂时性死区的意义也是让我们标准化代码,将所有变量的声明放在作用域的最开始。

var a = 123;
{
 console.log(a);//ReferenceError
  let a;
}

4.不允许重复声明

在相同的作用域内,用let声明变量时,只允许声明一遍。 (var是可以多次声明的)

// 正确
function () {
  var a = 10;
  var a = 1;
}

// 报错,Duplicate declaration "a"
function () {
  let a = 10;
  var a = 1;
}

// 报错,Duplicate declaration "a"
function () {
  let a = 10;
  let a = 1;
}

const



const用来声明常量,const声明的常量是不允许改变的,只读属性,这意味常量声明时必须同时赋值, 只声明不赋值,就会报错,通常常量以大写字母命名。

阮一峰大神的书里说,在严格模式下,重新给常量赋值会报错,普通模式下不报错,但是赋值无效。但是测试了一下,无论是严格还是非严格模式,都会报错。

const A = 1;
A = 3;// TypeError: "A" is read-only

const和let类似,也是支持块级作用域,不支持变量提升,有暂时性死区.

注意:如果声明的常量是一个对象,那么对于对象本身是不允许重新赋值的,但是对于对象的属性是可以赋值的。

const foo = {};
foo.prop = 123;

foo.prop// 123

foo = {} // TypeError: "foo" is read-only

import



ES6采用import来代替node等的require来导入模块。

import {$} from ‘./jquery.js‘

$对象就是jquery中export暴露的对象。

import命令接受一个对象(用大括号表示),里面指定要从其他模块导入的变量名。注意:大括号里面的变量名,必须与被导入模块对外接口的名称相同。

如果想为输入的变量重新取一个名字,import命令要使用as关键字,将输入的变量重命名。

import { New as $ } from ‘./jquery.js‘;

注意,import命令具有提升效果,会提升到整个模块的头部,首先执行。

class



ES6引入了类的概念,有了class这个关键字,当然,类只是基于原型的面向对象模式的语法糖,为了方便理解和开发而已,类的实质还是函数对象,类中的方法和对象其实都是挂在对应的函数对象的prototype属性下。

我们定义一个类:

//定义类
class Person {
  constructor(name, age) {
        this.name = name;
        this.age = age;
  }
  setSex(_sex) {
        this.sex=_sex;
  }
}

constructor方法,就是构造方法,也就是ES5时代函数对象的主体,而this关键字则代表实例对象,将上述类改写成ES5格式就是:

function Person(name, age){
          this.name = name;
        this.age = age;
}

Person.prototype. setSex = function (_sex) {
          this.sex=_sex;
}

所以说,类不算什么新玩意,大多数类的特性都可以通过之前的函数对象与原型来推导。

1.所有类都有constructor函数,如果没有显式定义,一个空的constructor方法会被默认添加(有点类似java了)。当然所有函数对象都必须有个主体。

2.生成类的实例对象的写法,与ES5通过构造函数生成对象完全一样,也是使用new命令。

class B {}
let b = new B();

3.在类的实例上面调用方法,其实就是调用原型上的方法,因为类上的方法其实都是添加在原型上。

b.constructor === B.prototype.constructor // true

4.与函数对象一样,Class也可以使用表达式的形式定义。

let Person = class Me {
      getClassName() {
        return Me.name;
      }
};

相当于

var Person = function test(){}

5.Class其实就是一个function,但是有一点不同,Class不存在变量提升,也就是说Class声明定义必须在使用之前。

全局变量



全局对象是最顶层的对象,在浏览器环境指的是window对象,在Node.js指的是global对象。

ES5之中,全局对象的属性与全局变量是等价的,隐式声明或者在全局环境下声明的变量是挂在全局对象上的。

ES6规定,var命令,function命令以及隐式声明的全局变量,依旧是全局对象的属性;而let命令、const命令、class命令声明的全局变量,不属于全局对象的属性。

var a = 1;
console.log(window.a) // 1

let b = 1;
console.log(window.b) // undefined

函数的形参



函数的形参,隐藏着在函数一开始声明了这些形参对应的变量。

function a(x,y){}
可以看成
function a(){
    var x=arguments.length <= 0 || arguments[0] === undefined ? undefined : arguments[0];
    var y=arguments.length <= 1 || arguments[1] === undefined ? undefined : arguments[1];
}

当然在ES6下默认声明就是用的let了,所以函数a变成:

function a(){
    let x=arguments.length <= 0 || arguments[0] === undefined ? undefined : arguments[0];
    let y=arguments.length <= 1 || arguments[1] === undefined ? undefined : arguments[1];
}

所以在ES6中会有以下几个问题:

function a(x = y, y = 2) {
  return [x, y];
}

a(); // 报错,给X赋值时y还未被let声明。  

function a(x,y) {
  let x;//相当于重复声明,报错。
}

--------本文属于摘要
时间: 2024-11-12 11:38:29

ES6的变量声明的相关文章

ES6变量声明 ------ let and const

在ES5中,声明变量的方式只有一种, 那就是var, 如var mes ="hello", 但是用var声明变量有一个比较奇怪的地方,就是变量声明的提升,比如在函数中,无论我们声明变量的代码写在什么地方,它都是在函数顶部声明变量,在全局作用域下,则是在script标签顶部声明变量,这就有点郁闷了,因为按照我们正常的思维方式,我们代码是一行一行写的,只有用到某个变量的时候,才进行声明变量,并且声明变量后,只有它后面的代码才可以用,现在成了,我们在后面声明变量,在前面也可以用了,这不符合我

ES6学习笔记之变量声明let,const

最近用淘宝的weex做了个项目,最近稍微闲下来了.正好很久没有接触RN了,所以趁这个机会系统的学习一下ES6的相关知识. 孔子说:没有对比就没有伤害.所以我们要拿ES6和ES5好好对比的学习.这样才能明白es6是多少的好,积极的拥抱她! 1.let 用let声明的变量,只会在let命令所在的代码块内有效. let的块状作用域 我们来看一个简单的例子: 'use strict'; { let name = 'cloud'; var age = 21; } name;//ReferenceError

ES6和ES5变量声明的区别(var let const)

// es5的语法与es6的语法区别 // var let const console.log(name);//undefine,不会报错,因为变量声明会提到作用域的最前面 var name="aa"; for(var i=1;i<7;i++){ console.log(i); } console.log(i);//8,不会报错因为var声明的变量没有块级作用域 /** * 总结 var 声明的变量,声明语句会提到作用域的最前面,并且没有块级作用域 */ console.log(

ES6的强大变量声明

ES6是javascript的新特性,今天来说说声明变量 过去我们声明变量,都是一个一个声明,现在有了一种新的声明方式,它可以将一个多个变量同时声明,声明后变量同时存在一个集合中,集合的数据类型是对象(object).使用这种声明方式,可以使我们书写程序的过程中思路更加清晰,可以将同一事件下的所有变量集合起来,可以将相同意义的变量集合起来. 这样的变量声明方式叫做“模式匹配” 之所以叫做模式匹配,是因为等号两边的模式是一样的 var a = 1; var b = 2; var c = 3; 这是

学习es6之(变量的解构赋值)

数组的解构赋值 ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构. 以前,为变量赋值,只能直接指定值. let a = 1; let b = 2; let c = 3; ES6可以写成下面这样. let [a, b, c] = [1, 2, 3]; 上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值. 本质上,这种写法属于"模式匹配",只要等号两边的模式相同,左边的变量就会被赋予对应的值,下面是一些使用嵌套数组进行解构的例子. let [foo, [[

js 变量声明易混淆的几点知识

这是我 JavaScript 学习过程中遇到的一些容易混淆的地方,趁着有时间,做了一个整理. 变量提升 变量与函数名提升优先级 js 作用域内有变量,这个很好理解,但有一些细节需要注意. console.log(foo); // 函数 function foo(){ console.log("函数声明"); } console.log(foo); // 函数 var foo = "变量"; console.log(foo); // 变量 当变量名与函数名同名,且都提

TypeScript 变量声明

ES6 中,变量声明一共有6种,分别是var.function .let.const.class和import. let 基本语法:let 变量名 :类型.其中类型不是必须的. 1.用于声明变量,其用法似于var. let name = 'Sunny' 2.所有声明的 let 变量仅在let命令所在的代码块(块级作用域)内有效. function f(input: boolean) { let a = 100; if(input) { let b = a + 1; // 运行正确 return

变量声明关键字var ,let,const

今天带大家了解的是比较有趣的几个变量声明关键字var,let,const. 我们在最初接触JS的时候,变量是我们重要的一个组成部分,在使用时规定必须要先进行声明,否则网页将会报错: console.log(b); //b is not defined ,表示我们并没有对变量进行声明,却要调用变量b,这时网页报错b未被定义,这时我们又了解到了声明关键字var的存在,利用声明关键字对变量进行声明: var a; console.log(a); //undefined,a未被赋值所以为undefine

TypeScript的变量声明

1.全新的变量声明方式 let和const是JavaScript ES6中新添加的变量声明方式.let在很多方面与var是相似的,但是它可以避免一些在JavaScript里常见一些问题. 而const则是对let的一个增强,它将阻止对一个变量再次赋值(二次赋值). 因为TypeScript是JavaScript的超集,所以它本身就支持let和const. ⒉var声明 原文地址:https://www.cnblogs.com/fanqisoft/p/11828839.html