一、var
1、作用域
使用var声明的变量的作用域,在一个函数内用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);//报错
a=3;
}
三、function
用function声明的是函数对象,作用域与var一样,是函数作用域
function test(){
function a(){
console.log("d");
}
a();
}
test();//d
a();//Uncaught ReferenceError:a is not defined
四、let
ES6新增的声明变量的关键字
与var的区别
1、作用域不同
let声明的变量的作用域是块级作用域
{
let a = 10;
var b = 1;
}
a // ReferenceError: a is not defined.
b // 1
2、不存在变量声明提升
console.log(a); // undefined,但是不报错。
console.log(b); // ReferenceError: b is not defined.
var a = 2;
let b = 2;
3、暂时性死区
无论在块中的任何地方声明了一个变量,那么在这个块级作用域中,任何使用这个名字的变量都是指这个变量,无论外部是否有其他同名的全局变量。
var a = 123;
{
console.log(a);//ReferenceError :a is not defined
let a;
}
4、不允许重复声明
在相同的作用域内,用let声明变量时,只允许声明一遍
// 正确
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
六、import
ES6采用import来代替node等的require来导入模块
import {$} from './jquery.js'
$对象就是jquery中export暴露的对象。
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;
}
八、全局变量
全局对象是最顶层的对象,在浏览器环境指的是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;//相当于重复声明,报错。
}