详细学习请参考  阮一峰的ECMAScript 6 入门

letconst的使⽤

es5中使用var来声明全局变量

  es5中我们学习了使用var来声明变量,但是使用var声明变量,会存在变量提升的问题。即变量可以在声明之前使用,值为undefined

  栗子1:

    console.log(a);  // var 的结果:undefined-->变量提升
{
var a = 2;
console.log(a); // 2
}
console.log(a); // var 的结果:2-->变量提升 //在js中一个{},称为作用域,使用var声明变量,会存在变量提升的问题。
//什么是变量提升呢?当解析脚本的时候,当在脚本中遇到var声明的变量,会将 var a;提到最上面去声明。从而导致此问题。由此也会使,a是一个全局的变量
//上面的在局部作用域声明并赋值给a=2,相当于这样将a声明为一个全局作用域的变量,然后在局部作用域对a赋值为2. var a; //声明全局变量
console.log(a); // var 的结果:undefined
{
a = 2; // 在局部作用域对全局变量的a赋值
console.log(a);
}
console.log(a); // var 的结果:2

  

  栗子2:

var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10 //上面代码中,变量i是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。
//每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的函数内部的console.log(i),
//里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,
//导致运行时输出的是最后一轮的i的值,也就是 10。

  

ES6 新增了let命令来声明变量

  ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。与使用var来声明变量相比, 使用let声明变量有以下几个特点:

  1.不存在变量提升

  2.不允许重复声明

  3.块级作用域

1.不存在变量提升

栗子1:

 console.log(a);
// let 的结果:Uncaught ReferenceError: a is not defined
{
let a = 2;
console.log(a); //2
}
console.log(a);
// let 的结果:Uncaught ReferenceError: a is not defined

  

栗子2:

  使用let,声明的变量仅在块级作用域内有效,最后输出的是 6。

var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6 //上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,
//所以最后输出的是6。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,
//从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,
//就在上一轮循环的基础上进行计算。

  另外,for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

 for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc

//上面代码正确运行,输出了 3 次abc。这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。
  

  

2.不允许重复声明

  let不允许在相同作用域内,重复声明同一个变量。

// 报错
function func() {
let a = 10;
var a = 1;
} // 报错
function func() {
let a = 10;
let a = 1;
}

  因此,不能在函数内部重新声明参数。

function func(arg) {//函数的参数和函数内部是同一个作用域,这点和for循环不同
let arg;
}
func() // 报错 function func(arg) {
{
let arg;
}
}
func() // 不报错

  

3.块级作用域

为什么需要块级作用域?

ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。

  第一种场景,内层变量可能会覆盖外层变量。

var num=1;
console.log(num); //1
{
var num = 11;
console.log(num) //11
}
console.log(num); //11-->其实还是变量提升

  第二种场景,用来计数的循环变量泄露为全局变量。

var s = 'hello';

for (var i = 0; i < s.length; i++) {
console.log(s[i]);
} console.log(i); // 5 //上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。

  

let实际上为 JavaScript 新增了块级作用域,而let只能出现在当前作用域的顶层。

栗子

let num=1;
console.log(num); //1
{
let num = 11; //内层作用域重复定义全局变量,只在当前作用域有效
console.log(num) //11
}
console.log(num); //1 //注意区分:
let num=1;
console.log(num); //1
{
num = 11; //在内层作用域内修改全局变量
console.log(num) //11
}
console.log(num); //11 //ES6 允许块级作用域的任意嵌套。内层作用域可以重复定义、可以覆盖(通过赋值的方式)、可以直接使用
//外层作用域的同名变量,而外层作用域可以重复定义、可以覆盖(通过赋值的方式)、不能直接使用内层定义的变量。
{{{{
{let insane = 'Hello World'}
console.log(insane); // 报错,外层不能直接使用内层的变量
}}}};
//上面代码使用了一个五层的块级作用域,每一层都是一个单独的作用域。第四层作用域无法读取第五层作用域的内部变量。 {{{{
let insane = 'Hello World';
{let insane = 'Hello World'} //内层作用域可以定义外层作用域的同名变量
}}}};

  

小结:

  1.不存在变量提升

  var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。

为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。

  2.不允许重复声明

  let不允许在相同作用域内,重复声明同一个变量。

  注意: for循环括号中设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。 而函数的形参和函数内部是同一个作用域。

  3.块级作用域

  实际上还是利用了let命令不存在变量提升,从而方便作用域的任意嵌套。

  内层作用域可以重复定义、可以覆盖(通过赋值的方式)、可以直接使用外层作用域的同名变量,而外层作用域可以重复定义、可以覆盖(通过赋值的方式)、不能直接使用内层定义的变量。

注意:for循环的花括号不是作用域,只有函数的花括号才是作用域.

const声明一个常量

const声明的变量跟let类似,同样拥有上面的三个特性,但是const声明的是常量。

const声明一个只读的常量。一旦声明,常量的值就不能改变。

const PI = 3.1415;
PI // 3.1415 PI = 3;
// TypeError: Assignment to constant variable.   //上面代码表明改变常量的值会报错。  

const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。

const foo;
// SyntaxError: Missing initializer in const declaration //上面代码表示,对于const来说,只声明不赋值,就会报错。

  

注意:

const命令声明的常量也是不提升,只能在声明的位置后面使用,否则报错。

const声明的常量,也与let一样不可重复声明(包括不能与var/let声明的变量重复)。

const的作用域与let命令相同:只在声明所在的块级作用域内有效。

模板字符串

  传统的 JavaScript 语言,输出模板通常是这样写的(下面使用了 jQuery 的方法)。

$('#result').append(
'There are <b>' + basket.count + '</b> ' +
'items in your basket, ' +
'<em>' + basket.onSale +
'</em> are on sale!'
);

  上面这种写法相当繁琐不方便,ES6 引入了模板字符串解决这个问题。

$('#result').append(`
There are <b>${basket.count}</b> items
in your basket, <em>${basket.onSale}</em>
are on sale!
`);

  模板字符串(template string)是增强版的字符串,用反引号(`)标识。它(模板字符串)可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量(插入变量使用${})。

// 普通字符串
`In JavaScript '\n' is a line-feed.` // 多行字符串
`In JavaScript this is
not legal.` console.log(`string text line 1
string text line 2`); // 字符串中嵌入变量
let name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

  

箭头函数

  es5的普通函数中使用function关键字来声明函数.

//普通函数:es5需要这样来定义函数
function add() {
return 5;
}
add()
// 函数表达式:即匿名函数的函数名声明在等号左边(如果不声明函数名则会报错)
let add2 = function(){
return 5;
};
add2()
// 自执行函数:在匿名函数的基础上
(function(x,y){
return x+y;
})(1,2);
// 闭包函数:这里就不写了,以免你懵逼...
  .......

  ES6 允许使用“箭头”(=>)定义函数。

//语法规则
//箭头函数 等价于 匿名函数
(形参)=>{函数体} ================> function(形参){函数体} //栗子
let add3 = (a,b)=>{
let c = a+b;
return a+b+c;
};
console.log(add3(3,4)); //等价于
let add3 = function(a,b){
let c = a+b;
return a+b+c;
};
console.log(add3(3,4));

  如果形参只有一个,可以省略圆括号;如果函数体的代码块部分只有一条语句,并且是返回值语句,则可以省略花括号。栗子:

var f = v => v;

// 等同于
var f = function (v) {
return v;
};

  如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。

var f = () => 5;
// 等同于
var f = function () { return 5 }; var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
return num1 + num2;
};

  如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。

// 报错
let getTempItem = id => { id: id, name: "Temp" }; // 不报错
let getTempItem = id => ({ id: id, name: "Temp" });

  如果箭头函数只有一行语句,且不需要返回值,可以采用下面的写法,就不用写大括号了。

let fn = () => void doesNotReturn();

  

es6中对象的声明

  对象(object)是 JavaScript 最重要的数据结构,(类似于Python中的对象,有属性和方法这两种成员,写法类似于Python中的字典,花括号中是键值对的形式)。ES6 对它进行了重大升级。

//es6中类的定义以及调用==>更接近Python等其他高级语言的类的定义方式
class Student{
//对象的单体模式:其实就是普通函数的简单写法,所以this的指向和普通函数是一样的,都是指向调用该方法的对象
constructor(name,age){//构建函数
this.name = name;
this.age = age;
}
fav(){//单体模式
console.log(this.name);
}
}
//实例化
let s1 = new Student('alex',18);
s1.fav();

  

属性的简洁表示法

  ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"} // 等同于
const baz = {foo: foo};

  上面代码中,变量foo直接写在大括号里面。这时,属性名就是变量名, 属性值就是变量值。下面是另一个例子。

function f(x, y) {
return {x, y};
} // 等同于 function f(x, y) {
return {x: x, y: y};
} f(1, 2) // Object {x: 1, y: 2}

 

方法的简洁表示法

  除了属性简写,方法也可以简写(,这样的书写方式我们称为对象的单体模式)。

const o = {
method() {
return "Hello!";
}
}; // 等同于 const o = {
method: function() {
return "Hello!";
}
};

  下面是一个实际的例子。

let birth = '2000/01/01';

const Person = {

  name: '张三',

  //等同于birth: birth
birth, // 等同于hello: function ()...
hello() { console.log('我的名字是', this.name); } };

  这种写法用于函数的返回值,将会非常方便。

function getPoint() {
const x = 1;
const y = 10;
return {x, y};
} getPoint()
// {x:1, y:10}

  简洁写法在打印对象时也很有用。

let user = {
name: 'test'
}; let foo = {
bar: 'baz'
}; console.log(user, foo)
// {name: "test"} {bar: "baz"}
console.log({user, foo})
// {user: {name: "test"}, foo: {bar: "baz"}}

  上面代码中,console.log直接输出userfoo两个对象时,就是两组键值对,可能会混淆。把它们放在大括号里面输出,就变成了对象的简洁表示法,每组键值对前面会打印对象名,这样就比较清晰了。

小结: 对象的三种声明方式

//普通函数:字面量方式创建对象,等价于fav:function()
let person = {
name:'超哥',
age:18,
fav(){
// this指的是person
console.log(this.name);
}
}; person.fav();//person对象调用的fav方法,则fav方法中的this指的就是person对象 //箭头函数
let person2 = {
name:'超哥2',
age:188,
fav:()=>{
// this指的是person的父类,也就是谁定义了person对象,这里是window对象
console.log(this);
}
}; person2.fav();//person对象调用的fav方法,则fav方法中的this指的是person对象的父类 //es6中类的定义以及调用==>更接近Python等其他高级语言的类的定义方式
class Student{
//对象的单体模式:其实就是普通函数的简单写法,所以this的指向和普通函数是一样的,都是指向调用该方法的对象
constructor(name,age){
this.name = name;
this.age = age;
}
fav(){
console.log(this.name);
}
}
let s1 = new Student('alex',18);
s1.fav();

   

this的指向

  关于this的指向,⼤家不要看调用方法的对象是谁,要看被调用的方法此时在当前对象内部 使⽤的是普通函数和对象的单体模式写法,还是箭头函数。

    1.如果是普通函数或者对象的单体模式写法,那么该this指向调用函数的对象。

    2.如果是箭头函数,this指向调用函数时的对象的上下⽂(也就是⽗类) 。

//普通函数:字面量方式创建对象,等价于fav:function()
let person = {
name:'超哥',
age:18,
fav(){
// this指的是person
console.log(this.name);
}
}; person.fav();//person对象调用的fav方法,则fav方法中的this指的就是person对象 //箭头函数
let person2 = {
name:'超哥2',
age:188,
fav:()=>{
// this指的是person的父类,也就是谁定义了person对象,这里是window对象
console.log(this);
}
}; person2.fav();//person对象调用的fav方法,则fav方法中的this指的是person对象的父类 //es6中类的定义以及调用==>更接近Python等其他高级语言的类的定义方式
class Student{
//对象的单体模式:其实就是普通函数的简单写法,所以this的指向和普通函数是一样的,都是指向调用该方法的对象
constructor(name,age){
this.name = name;
this.age = age;
}
fav(){
console.log(this.name);
}
}
let s1 = new Student('alex',18);
s1.fav();

  对于箭头函数,函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。 

												

三天精通Vue--ES6的常用语法的更多相关文章

  1. 三天精通Vue教程

    在这里更新作为后端工程师想要快速掌握Vue需要看的重点内容,三天精通教程,加油! 学前摘要 ES6的常用语法 Vue的常用语法

  2. es6的常用语法

    最常用的ES6特性 let, const, class, extends, super, arrow functions, template string, destructuring, defaul ...

  3. 黑马eesy_15 Vue:常用语法

    自学Java后端开发,发现14 微服务电商[乐优商城]实战项目,在介绍完SpringCloud后就要肝前端的基础知识ES6语法和Vue.js 所以本篇博客作为入门Vue练习记录的过程,目的是供自学后端 ...

  4. vue学习(一)ES6常用语法

    1 ES6常用语法 1.1 变量提升 例① # 变量提升 <div id="app"> </div> <script> console.log( ...

  5. ES6常用语法

    ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015. 也就是说,ES6就是ES2015. ...

  6. Vue常用语法及命令

    1,Vue常用语法 vue常用语法之变量的定义 // 1,变量相关 // 变量的提升 var username = "雪雪"; var username ; console.log ...

  7. ES5与ES6常用语法教程之 ②解构语法糖、声明变量异同

    js常用语法系列教程如下 es5与es6常用语法教程(1) es5与es6常用语法教程(2) es5与es6常用语法教程(3) es5与es6常用语法教程(4) es5与es6常用语法教程(5) es ...

  8. ES6 常用语法知识汇总

    ES6模块化如何使用,开发环境如何打包? 1.模块化的基本语法 /* export 语法 */ // 默认导出 export default { a: '我是默认导出的', } // 单独导出 exp ...

  9. day67:Vue:es6基本语法&vue.js基本使用&vue指令系统

    目录 Vue前戏:es6的基本语法 1.es6中的let特点 1.1.局部作用域 1.2.不存在变量提升 1.3.不能重复声明 1.4.let声明的全局变量不从属于window对象,var声明的全局变 ...

  10. ES6的介绍和常用语法

    本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. 前言 ECMAScript 是 JS 的语言标准.而 ES6 是新的 J ...

随机推荐

  1. 用itemloader提取,清洗数据的技巧

    def parse_item(self, response): item_loader = NewItemLoader(NewItem(), response) item_loader.add_xpa ...

  2. windows环境下 mysql 忘记root密码时的解决办法

    1,停止MYSQL服务,CMD打开DOS窗口,输入 net stop mysql 2,在CMD命令行窗口,进入MYSQL安装目录 比如E:\Program Files\MySQL\MySQL Serv ...

  3. 【CF285E】Positions in Permutations(动态规划,容斥)

    [CF285E]Positions in Permutations(动态规划,容斥) 题面 CF 洛谷 题解 首先发现恰好很不好算,所以转成至少,这样子只需要确定完一部分数之后剩下随意补. 然后套一个 ...

  4. Java8 Optional总结

    分类专栏: Java   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/HEYUTAO00 ...

  5. 实现外网远程桌面内网的电脑和外网访问内网的FTP

     基于之前两篇文章搭建了ngrok实现了内网穿透,用过了http和https的协议完成了外网访问内网的网站,这一篇教大家用tcp协议实现外网远程桌面内网的电脑和外网访问内网的FTP. 一.外网远程桌面 ...

  6. python 练习题:将列表中的大写字母转换成小写

    将列表中的大写字母转换成小写如果list中既包含字符串,又包含整数,由于非字符串类型没有lower()方法,L1 = ['Hello', 'World', 18, 'Apple', None]请修改列 ...

  7. DSAPI CMD命令行进程代理

    DSAPI.文件.CMD命令行进程代理,是用来和CMD.exe或指定exe进行输出重定向的简化使用工具,可隐藏或显式地启动一个cmd.exe,并将输出流.输入流和错误流重定向至代理,通过事件触发方式与 ...

  8. vue 强制刷新 demo 神器

    this.$forceUpdate() /*关键句,强制更新dom*/

  9. SpringMVC数组参数

    前端 var moduleids = moduleArr.join(','); //一定要切换成,分割的字符串传到后台 后台 @RequestParam List<String> modu ...

  10. 小程序动态设置style,使用内部数据