三天精通Vue--ES6的常用语法
详细学习请参考 阮一峰的ECMAScript 6 入门
let和const的使⽤
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
直接输出user
和foo
两个对象时,就是两组键值对,可能会混淆。把它们放在大括号里面输出,就变成了对象的简洁表示法,每组键值对前面会打印对象名,这样就比较清晰了。
小结: 对象的三种声明方式
//普通函数:字面量方式创建对象,等价于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的常用语法的更多相关文章
- 三天精通Vue教程
在这里更新作为后端工程师想要快速掌握Vue需要看的重点内容,三天精通教程,加油! 学前摘要 ES6的常用语法 Vue的常用语法
- es6的常用语法
最常用的ES6特性 let, const, class, extends, super, arrow functions, template string, destructuring, defaul ...
- 黑马eesy_15 Vue:常用语法
自学Java后端开发,发现14 微服务电商[乐优商城]实战项目,在介绍完SpringCloud后就要肝前端的基础知识ES6语法和Vue.js 所以本篇博客作为入门Vue练习记录的过程,目的是供自学后端 ...
- vue学习(一)ES6常用语法
1 ES6常用语法 1.1 变量提升 例① # 变量提升 <div id="app"> </div> <script> console.log( ...
- ES6常用语法
ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015. 也就是说,ES6就是ES2015. ...
- Vue常用语法及命令
1,Vue常用语法 vue常用语法之变量的定义 // 1,变量相关 // 变量的提升 var username = "雪雪"; var username ; console.log ...
- ES5与ES6常用语法教程之 ②解构语法糖、声明变量异同
js常用语法系列教程如下 es5与es6常用语法教程(1) es5与es6常用语法教程(2) es5与es6常用语法教程(3) es5与es6常用语法教程(4) es5与es6常用语法教程(5) es ...
- ES6 常用语法知识汇总
ES6模块化如何使用,开发环境如何打包? 1.模块化的基本语法 /* export 语法 */ // 默认导出 export default { a: '我是默认导出的', } // 单独导出 exp ...
- day67:Vue:es6基本语法&vue.js基本使用&vue指令系统
目录 Vue前戏:es6的基本语法 1.es6中的let特点 1.1.局部作用域 1.2.不存在变量提升 1.3.不能重复声明 1.4.let声明的全局变量不从属于window对象,var声明的全局变 ...
- ES6的介绍和常用语法
本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. 前言 ECMAScript 是 JS 的语言标准.而 ES6 是新的 J ...
随机推荐
- 用itemloader提取,清洗数据的技巧
def parse_item(self, response): item_loader = NewItemLoader(NewItem(), response) item_loader.add_xpa ...
- windows环境下 mysql 忘记root密码时的解决办法
1,停止MYSQL服务,CMD打开DOS窗口,输入 net stop mysql 2,在CMD命令行窗口,进入MYSQL安装目录 比如E:\Program Files\MySQL\MySQL Serv ...
- 【CF285E】Positions in Permutations(动态规划,容斥)
[CF285E]Positions in Permutations(动态规划,容斥) 题面 CF 洛谷 题解 首先发现恰好很不好算,所以转成至少,这样子只需要确定完一部分数之后剩下随意补. 然后套一个 ...
- Java8 Optional总结
分类专栏: Java 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/HEYUTAO00 ...
- 实现外网远程桌面内网的电脑和外网访问内网的FTP
基于之前两篇文章搭建了ngrok实现了内网穿透,用过了http和https的协议完成了外网访问内网的网站,这一篇教大家用tcp协议实现外网远程桌面内网的电脑和外网访问内网的FTP. 一.外网远程桌面 ...
- python 练习题:将列表中的大写字母转换成小写
将列表中的大写字母转换成小写如果list中既包含字符串,又包含整数,由于非字符串类型没有lower()方法,L1 = ['Hello', 'World', 18, 'Apple', None]请修改列 ...
- DSAPI CMD命令行进程代理
DSAPI.文件.CMD命令行进程代理,是用来和CMD.exe或指定exe进行输出重定向的简化使用工具,可隐藏或显式地启动一个cmd.exe,并将输出流.输入流和错误流重定向至代理,通过事件触发方式与 ...
- vue 强制刷新 demo 神器
this.$forceUpdate() /*关键句,强制更新dom*/
- SpringMVC数组参数
前端 var moduleids = moduleArr.join(','); //一定要切换成,分割的字符串传到后台 后台 @RequestParam List<String> modu ...
- 小程序动态设置style,使用内部数据