Javascript学习笔记-ES6语法

ES6带来了Javascript新的变化,新的语法特性,使得之以前版本中需要特性方式才能解决的问题一些问题得到了简化和支持,很大程度上提高了开发效率,扩展了Javascript功能呢。

1. let/const

ES6中增加了两个新的变量声明letconst。ES6之前Javascript是没有明确的块级作用域,{}代码块并不能作为一个完整的作用域来使用(当然函数存在其作用域),使用var声明的变量在外部也可以引用

{ 
  va a = 1; 
}
console.log(a); // 1

letconst的引入使得我们可以产生局部的作用域

{
  let a = 1;
  console.log('inner:a=' + a); // inner:a=1
}
console.log('outer:a=' + a); // Reference Error 

letconst存在以下的特性

  1. 必须要先声明后使用,Javascript不会将let/const声明的变量进行提升,因此也不能使用typeof的值是否是undefined来判断变量是否已经声明。
  2. 在作用域范围内,不能重复声明相同的变量名

// 变量声明无法提前
{
  console.log(a); // ReferenceError
  // typeof a === 'undefined' // ReferenceError
  let a = 1; 
}
// 同名变量只能声明一次
{
  let a = 1;
  let a = 2; // SyntaxError: Identifier 'a' has already been declared
}

letconst声明的区别在于,const通常选择对常量进行修饰,其自带类似Javafinal的效果,一旦声明以后变量的引用不能发生变化,变量引用的内容本身可以发生变化

// 声明一个数字字面量
const a = 1;
a = 2; // TypeError: Assignment to constant variable.
// 声明一个对象的引用
const a = {};
a.a = 1; // 可以正常运行

2. 分离/剩余操作符

ES6引入了分离/剩余...,它有两个用途:

  1. 在对变量赋值的时候可以用来对Javascriptiterable的对象或者iterator进行展开
  2. 在方法声明中变量中使用,可以用来接受剩余参数

// 用于展开
var a = 'abcdef';
var b = [...a]; 
console.log(b); // [a,b,c,d,e,f]
// 可以使用展开效果替代数组的concat
var arr1 = [1,2,3];
var arr2 = [4,5,6]; 
var res = [...arr1, ...arr2]; // [1,2,3,4,5,6];
// 用与函数接受剩余参数
function f(a, ...b) {
  console.log(a);
  console.log(b);
}
f(1,2,3,4,5); // 1, [2,3,4,5]

3. 函数默认值

ES6中函数声明时可以给形参添加默认值,以替代在函数体中对参数进行默认值设定的方式

// ES6之前
function f(a) {
  var tempA = a || 'test'; // 设置默认值
  console.log('a:'+a);
}
f(); // a:test
// ES6
function f(a='test'){
  console.log('a:'+a);
}
f(); // a: test

默认值的设置除了使用字面量,也可以使用表达式,但是使用表达式需要注意表达式中变量的作用域和顺序

function f(a=b, b=1) {
  console.log(a,b);
}
f(); // ReferenceError: b is not defined
// 另一种情况
var b = 2;
function f(a=b, b=1) { // 因为形参中存在b,所以这里的a不能正确赋值
  console.log(a,b);
}
f(); // ReferenceError: b is not defined

使用展开/剩余操作符的形参无法使用这种方式设置默认值

function f(...a = [1,2,3]) {} // SyntaxError: Unexpected token =

4. 对象解构

ES6中的数组和对象,增加了解构的方式来对其进行拆分,将对象或数组的值赋值给某个变量,省略掉中间变量,简化取值写法

// 对数组解构
var [a,b] = [1,2,3,4];
console.log(a); // 1
console.log(b); // 2
// 对对象解构
var {x: vx, y: vy} = {x:1, y: 2};
console.log(vx); // 1;
console.log(vy); // 2;
console.log(x); // ReferenceError
console.log(y); // ReferenceError

其中对于对象的解构需要注意,其中x: vx的意思是,声明一个变量vx,并将对象中x的值赋值给变量vx,也就是说:左侧是指向对象中的属性,:右侧是声明的新的变量,即我们希望赋予的结果,也就是source: target结构
当然如果对象中属新名和我们希望声明的变量名一致,我们可以使用简写

var {x, y} = {x: 1, y: 2}; // 相当于{x: x, y: y} = {x: 1, y: 2};

解构对象如果不存在某属性,那么赋值变量的值就为undefined

var {x, y, z} = {x: 1, y: 2};
console.log(z); // undefined

解构的过程可以使用剩余表达式,也可以设置默认值

// 可以和剩余表达式结合
var [a,...b] = [1,2,3,4];
console.log(a); // 1
console.log(b); // [2,3,4];
// 设置解构默认值
var {x , y: y=2} = {x: 1}; // 可以简写为 var {x, y=2} = {x:1}
console.log(y); // 2
// 省略中间变量交换变量的值
var x = 1;
var y = 2;
[x, y] = [y, x];
console.log(x); // 2
console.log(y); // 1

5. 字面量简写

ES6中创建对象的时候,可以使用属性和方法有一种简写的方式

var x = 1;
// ES6之前写法
var o = {
    x: x,
    f: function() {}
}
// ES6提供简写
var o = { 
  x, //  相当于 x: x
  f() {} // 将:function直接省略
}; 

6. 计算属性名

ES6之前如果属性名是一个变量,我们很难通过一般的手段给对象增加变量属性(应该只能通过Object.defineProperty定义属性),ES6中增加了[]的语法来满足需求

var x  = 'vx';
var o = {
  [x]: 1,
  [x+ 'f']() {}
}
console.log(o); // {vx: 1, vxf: function}

7. 原型对象关联

ES6新增Object.setPrototypeOf(target, source)方法来进行对象的原型对象__proto__的关联操作

// ES6之前
var o1 = {};
var o2 = {
  __proto__: o1
}
// ES6
Object.setPrototypeOf(o2, o1);

如果对象中使用了方法简写声明,可以使用super参数来获取该对象的原型对象

var o1 = {
  f() { console.log('o1'); }
}
var o2 = {
  f() {
    super.f(); 
    console.log('o2');
  }
}
Object.setPrototypeOf(o2, o1);
o2.f(); // o1, o2

8. 模板语法

ES6使用模板语法,可以替代字符串拼接的方式来构建含有变量的字符串。模板语法使用了反引号作为标志,使用${}的插值方式获取变量引用

// ES6之前只能使用+号进行字符串拼接
var name = 'patrick';
console.log('Hi, ' + name + ' welcome!');
// ES6之后使用模板语法
console.log(`Hi, ${name} welcome!`);

同时相比于字符串拼接,模板语法可以使用多行的写法,而字符串拼接不可以

var name = 'patrick';
console.log(`Hi, ${name}
                      welcome`);

模板语法除此以外还有一个比较有意思的用途,我们可以定义一个特殊的函数,来获取模板语法中的不可变部分和插值部分

var name = 'patrick';
function f(strings, ...values){
  console.log(strings);
  console.log(values);
}
f`Hi, ${name} welcome` // ["Hi, ", " welcome", raw: Array(2)], ['patrick']

其中strings中存在一个属性raw,其表示的是原本的字符串内容,相当于String.raw的结果

console.log('Hello, \r\n patrick welcome');
console.log(String.raw`Hello, \r\n patrick welcome`);

9. 箭头函数

ES6的箭头函数简化了匿名函数的写法,箭头函数由三部分组成:参数,箭头,函数体。在函数体部分,如果不使用{}则会将表达式结果作为匿名函数返回值,使用{}可以支持多行语句

function f(callback) {
  var v = callback();
  console.log('v:' + v);
}
f(() => 1);
f(() => {
  console.log('callback');
  return 1;
})

如果在对象方法属性中使用了箭头函数,且在箭头函数中使用了this关键字,则需要注意this关键字的作用域上下文。

var a = 'outer';
var o = {
  a: 'inner',
  f: () => {
    console.log(this.a);
  }
}
o.f(); // outer
o.f.apply({a: 'apply'}); // outer

10. for of 循环

ES6中增加了for of循环来对所有的iteratable对象(对象中有[Symbol.iterator]属性)进行遍历,其中内置对象中String, Array, GeneratorCollections/TypedArray已经实现了[Symbol.iterator]属性,可直接遍历

for(let s of 'abc') {
  console.log(s); // a  b c
}

11. 正则表达式

ES6中增加了两个新的正则表达式标志符,使用u来扩展字符串中unicode字符的匹配,使用y来扩展处理匹配位置(操作reg.lastIndex来实现),并提供了reg.flags来获取正则表达式使用到的修饰符。

12. 数字字面量

ES6中对八进制的数字字面量提供了0o的方式,替代了以前八进制的写法0

console.log(0o17); // 15

13. Unicode处理

ES6中对于BMP(0x0000 -> 0xFFFF)以外的Unicode提供了新的支持方式\u{},并在对含有unicode字符串进行长度判断时,要注意unicode字符所占有长度可能会带来的问题

14. Symbol

ES6新的基本类型symbol,可以用来定义常量取代代码中的Magic Number。通过Symbol(str)创建,也可以通过Symbol.for(str)创建,两者区别在于后者会去查找是否已经使用Symbol.for创建相同keysymbol对象,已经创建则返回改symbol,否则创建新的symbol对象

var s1 = Symbol('key');
var s2 = Symbol('key');
var s3 = Symbol.for('key');
var s4 = Symbol.for('key');
console.log(s1 === s2); // false;
console.log(s1 === s3); // false
console.log(s3 === s4); // true

可以通过Symbol.keyFor()的方法获取到使用Symbol.for创建的Symbol所使用的字符串key

var key = Symbol.keyFor(Symbol.for('my key'));
console.log(key); // my key

参考:

《你不知道的Javascript(ES6&Beyond)》

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容