ES6初始记录(较乱)

转码器:babel,允许用ES6的语法来写程序,而不用考虑现有环境是否支持。

EcmaScrip是规范,JavaScript是实现。
Es6包含ecma2015 ecma2016 ecma2017,一般是指ecma2015。

let 和 const

顶层对象的属性:
ES5 顶层对象的属性与全局变量是等价的。
ES6 开始全局变量不都是顶层对象的属性了,只有var、function定义的才算,let、const、class定义的不算顶层对象的属性。

const与let一样:

  • 块级作用域内有效
  • 声明不会提升,需先声明再使用(暂时性死区)
  • 不允许重复声明
  • const声明只读常量,声明对象时指对象地址不可变,但对象内容可改变(需立即初始化)
  • 另:对象冻结可使用Object.freeze( obj )。

ES5声明变量有2种方式:var + function
ES6声明变量有6种方式:var + function + let + const + import + class

ES5只有全局+函数作用域,无块级作用域(导致:内部变量覆盖外部变量、for计数变量外泄为外部变量等)
ES6 let只在块级作用域内有效,可以替换立即执行函数了IIFE。{let a;…..}

ES5不允许在块级作用域中声明函数,但是浏览器真正实现是:允许声明函数,而且会提升至作用域前面。
ES6明确允许在块级作用域中声明函数,而且浏览器环境和非浏览器环境表现不同:
- 浏览器环境:相当于var声明,会提升(提升至所在全局||函数作用域头部),赋值延后(函数声明会提升至所在块级作用域头部)。
- 非浏览器环境:相当于let声明,不会提升,只在当前块级作用域有效。
所以:为了表现一致,尽量不在块级作用域内声明函数,若必须声明,则使用 函数表达式方式 ,而非函数声明方式。

let为js新增了块级作用域,声明变量,只在当前代码块内有效。
立即执行函数表达式IIFE(Immediately-Invoked Function Expression):(function(){})();

变量的解构赋值

解构赋值的规则:只要等号右边不是对象,就现将其转换成对象。
解构赋值:数组、对象、字符串、数值、布尔值、函数参数等的解构赋值。

** 对象的解构赋值 **
模式不会被赋值,被赋值的是模式后面的变量:

let {loc: first, glo:last} = {loc:123, glo: 456};//loc和glo是模式,first和last才是真正赋值的变量

对于已经声明的变量进行解构赋值时,需要加上小括号,因为不加的话,js会将行首的花括号解释为代码块,引起语法错误。

let x;
{x} = {x:1}; //SyntaxError: syntax error
({x} = {x:1}); //正确

解构赋值的几个好处:

  1. 提取JSON数据的值;
  2. 函数参数定义默认值;
  3. 提取某对象或模块的方法;

字符串的扩展

对字符串进行操作的时候,要注意常规字符(两字节)和辅助字符(四字节)的区别。
unicode是世界上所有的字符集,是一种二进制的表示方法,但是并没有规定存储方式。UTF-8和UTF-16、UTF-32就是其具体的存储实现,具体区别可以阅读阮一峰老师的两篇文章,参考:

字符串的扩展重点:

  • 码点大括号表示法: '\u{20BB7}'
  • 对于传统for循环无法识别的大于0xFFFF的码点,for...of可以正确识别
  • normalize() repeat() includes() startsWith() endsWith()等函数
  • 模板字符串:`xxxxxx ${variable} yyy ${func()}` //引入变量时使用${}

正则的扩展

正则表达式新增flags属性,返回修饰符

  • ES5:/abc/ig.source 返回正文abc
  • ES6:/abc/ig.flags 返回修饰符ig
  • 新增修饰符u和y,u代表可以处理unicode大于0xFFFF的字符,y类似于g,只是y是从剩余字符中的第一个位置开始匹配,g是只要剩余字符中匹配即可。
  • /abc/ig.sticky是否设置了粘连属性y
  • 提案:RegExp.escape()函数对字符串进行转义
  • 提案:/abc/s.dotAll属性,修饰符/s:点代表一切字符

数值的扩展

  • 二进制和八进制表示法(0B和0O)
  • 新增一些方法:Number.isNaN() .isFinite() .parseInt() .parseFloat() .isSafeInteger()
  • 未解决js浮点运算的bug,引入一个极小常量Number.EPSILON
  • Math对象扩展了一些函数:.trunc() .sign()等

数组的扩展

  • 增加一些方法:Array.from() 将类数组转换成数组;Array.of()将一组值转换成数组,解决Array构造函数参数不等的歧义问题
  • [].find() .findIndex() .entries() .keys() .values() .includes()等方法
  • 尽量避免出现空位,防止表现不一致引起问题

JS中数组的迭代方法:

方法 举例
forEach:对数组中的每一项执行操作 arr.forEach(function(v, i, arr){return v+1;})
every:每一项都满足某条件则返回true if(arr.every(function(v,i,arr){return v > 2;})){}
some:只要有一项满足某条件则返回true if(arr.some(function(v,i,arr){return v > 2;})){}
map:对数组每一项进行操作,返回数据组成新数组返回 var newArr = arr.map(function(v, index, arr){return v*2;});
filter: 对数组进行过滤,满足条件的项组成新数组返回 var newArr = arr.filter(function(v, index, arr){return v > 10;});
reduce:对数组的相邻两项进行操作 var sum = arr.reduce(function(sum, item){return sum+item;}, 0)
includes:数组是否包含某值 if(arr.includes(2)){}

函数的扩展

  • 参数默认值:双重默认值 function({x=0,y=0} = {}){...},尽量将定义了默认值的参数放于参数的尾部,方便省略

  • (function(a,b,c=1){}).length //2 返回函数的预期参数个数(不含指定了默认值的参数和rest参数)

  • rest参数:只能是尾参数

  • 扩展运算符:... 将数组转换成逗号分隔的数据序列

  • 箭头函数=>:this指向定义时的作用域(this始终指向定义时的this,而非运行时的this)

  • 函数绑定运算符(双冒号** ::**)obj::method 绑定this

  • 尾调用、尾递归调用(先做了解):尾调用-函数的最后一步是调用另一个函数,内部函数可以不用再维护外部函数的调用栈信息。

对象的扩展

  • 属性名表达式 obj['a'+'bc'] = 111; 简洁属性表示法 let obj = {x, y};
  • Object.keys() .values() .entries()
  • Null传导运算符** ?:** 判断对象是否存在,防止报错 person?.user?.p1?.age
  • 对象的扩展运算符** ...** 单纯的解构赋值可以读取对象的继承属性,扩展运算符的解构赋值只能读取对象自身的属性
var o = Object.create({ x: 1, y: 2 });//x y算继承属性
o.z = 3;

let { x, ...m } = o;
x // 1---单纯的结构赋值
m // {z: 3} --- 扩展运算中的解构赋值
  • 对象属性的遍历5种方法
for...in //返回对象自身和继承的可枚举属性
Object.keys() //返回对象自身可枚举属性
Object.getOwnPropertyNames() //返回对象自身所有属性(包括不可枚举)
Object.getOwnPropertySymbols() //返回对象自身Symbols属性
Reflect.ownKeys() //返回对象自身symbol类型和字符串类型的属性(不管是否可枚举)
方法 适用范围 描述
for...in 数组、对象 获取可枚举的实例和原型属性名(返回键名)
Object.keys() 数组、对象 返回可枚举的实例属性名组成的数组
Object.getOwnPropertyNames() 数组、对象 返回除原型属性以外的所有属性(包括不可枚举的属性)名组成的数组
for…of 可迭代对象(Array Map Set等) 返回属性值(返回键值)
Reflect.ownKeys() 对象自身的所有属性,包含symbols属性和不可枚举属性
  • object.is(p1, p2):同值判断 基本等同于全等===,不同:
    object.is(+0, -0);//false
    object.is(NaN, NaN);//true
  • Object.assign(target, source1, source2):对象合并,浅拷贝,只拷贝对象自身的属性,继承(prototype上的属性)+不可枚举的属性都不会拷贝到。
    首参不能是null、undefined,否则报错;
    处理数组时:
    Object.assign([1, 2, 3], [4, 5]) // [4, 5, 3] 按照下标进行覆盖合并
    Object.create(原型 | null,实例属性设置):只有显示的指定属性设置的enumrabe等属性才可以。属于ES5

Symbol

ES6新增原始数据类型Symbol,表示独一无二的值(对象属性名可以保证不会冲突)。Symbol给我感觉用处不是很顺畅,很别扭的感觉。

  • Symbol(str):参数表示对Symbol实例的描述,不能用new(不是对象);Symbol值不能进行隐士字符串转换,只能显示转换String(Symbol('aa')) or Symbol('aa').toString(),也不能转换成数值,但是可以进行布尔换算
  • Symbol值作为属性名时,只能用[]引用,不能用点.获取(用点默认代表字符串属性)
  • Symbol.for('aa') 是全局登记的值:每次会先搜索给定参数的值是否存在,如果已经存在,则返回,否则新建一个值返回。Symbol.keyFor(Symbol.for('aa'))返回Symbol.for()注册的值的描述。
Symbol('aa') === Symbol('aa') //false
Symbol.for('aa') === Symbol.for('aa') //true
Symbol.keyFor(Symbol.for('aa')) //'aa'
Symbol.keyFor(Symbol('aa'))//undefined
  • 定义了一些内置的Symbol值,用于指向语言内部的方法

Map和Set数据结构

数据集合:ES5 -> Array+Object ,ES6 -> Map+Set

--- Set

类似于没有重复值的数组。键名和键值完全一样。

//操作方法 add delete has clear
var set = new Set([1,2,3,2,3]);//[1,2,3]
set.add(4);//[1,2,3,4]
set.size;// 4
set.delete(1);
set.has(2);
set.clear();//清空

//遍历方法 .keys() .values() .entries() .forEach()
let set = new Set(['red', 'green', 'blue']);

for (let item of set.keys()) {
  console.log(item);
}
// red
// green
// blue

for (let item of set.values()) {
  console.log(item);
}
// red
// green
// blue

for (let item of set.entries()) {
  console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]

set.forEach((value,key,set) =>console.log(value+':'+key) );
--- WeakSet

与set类似,但是只保存对象类型的数据,是对象类型数据的弱引用,目的是防止内存泄漏。常用方法有:add has delete,无法遍历

--- Map
// 操作方法 set get has delete clear
var map = new Map([ ['name', 'fss'], ['age', 27] ]);
map.set('job', 'computer').set('xx', 'aa');
map.get('xx');//'aa'
map.size;//3 条目个数
map.has('job');//true

//遍历方法 map.keys() .values() .entries() forEach()
--- WeakMap

与Map结构类似,键名只能是对象类型,弱引用,防止内存泄漏。常用方法:get set has delete,无法遍历。

Proxy

对对象的一层代理拦截,修改对象操作的默认行为。

//handler为{}时,代表无拦截效果;handler内部定义了一些内置的拦截方法:get set apply construct等
var proxy = new Proxy(target, handler);

var handler = {
  get: function(target, name) {
    if (name === 'prototype') {
      return Object.prototype;
    }
    return 'Hello, ' + name;
  },

  apply: function(target, thisBinding, args) { //一般函数调用时拦截函数
    return args[0];
  },

  construct: function(target, args) {//构造函数调用时拦截函数
    return {value: args[1]};
  }
};

var fproxy = new Proxy(function(x, y) {
  return x + y;
}, handler);

fproxy(1, 2) // 1
new fproxy(1,2) // {value: 2}
fproxy.prototype === Object.prototype // true
fproxy.foo // "Hello, foo"
  • Proxy.revocable 目标对象不允许直接访问,只能通过代理访问,访问结束,收回代理权,不允许再访问
  • Proxy代理时,目标对象内部的this指向proxy代理对象

Reflect

  • 与Proxy类似,Proxy handler中有的方法Reflect也都有,只不过Proxy是自定义拦截行为,Reflect实现的是对象的原生行为。
  • 观察者模式:函数自动观察数据对象,一旦数据对象发生变化,函数自动执行。(懵懵懂懂???)

Promise

  • 异步编程的一种解决方案(传统方法:回调函数和事件),可以这样理解Promise:一个容器,保存着异步编程操作的结果(未来完成)。
  • 状态有2种,要么成功resolved || fulfilled,要么失败rejected
  • 提供一些API:
var promise = new Promise(resolve, rejected);//新建后立即执行,无法中断
promise.then(resolveFunc, rejectedFunc)
.then(resolveFunc)//链式写法
.catch(function(){})//状态为rejected时执行,resolveFunc执行出错时也执行
  • Promise.all([p1,p2,p3])所有参数状态都为resolved时,整体才为resolved;有一个失败,则整体rejected
  • Promise.race([p1,p2,p3])只要有一个实例状态改变,则整体状态改变,执行相应处理函数
  • Promise.resolve() .rejected() 将参数先转换为Promise对象,再执行相关函数
  • .done() .finally() 区别是:finally不管怎样都会执行,done总是在回调链的尾端,保证抛出任何错误(捕捉错误的)。
  • Promise.try() 模拟try模块,尝试运行同步函数 Promise.catch()

遍历器Iterator接口

为各种不同的数据结构(Array、Object、Map、Set)提供一种统一的访问机制(即for...of)。只要部署了Symbol.iterator(默认指向该对象的遍历器接口,必须要有next方法)属性的数据结构,就被称为部署了遍历器接口。

Generator函数

ES6提供的异步编程解决方案,可以理解成一个状态机,封装了多个内部状态。

  • 语法
function* generatorFunc(){//带有星号*
    //some code 
    yeild 'status1';//函数内部可以用yeild定义状态
    //some code 
    yeild 'status2';
    //some code 
    yeild 'status3';
    //some code 
    return 'status4'; //可以没有
}
var geneFunc = generatorFunc();
geneFunc.next();//{value:'status1', done: false} 
geneFunc.next();//{value:'status2', done: false} 
geneFunc.next();//{value:'status3', done: false} 
geneFunc.next();//{value:'status4', done: true}
geneFunc.next();//{value:undefined, done: true}  
  • Generator函数像正常函数一样调用,但是函数并不是立即执行,调用生成函数后,返回一个遍历器对象,第一次调用next方法,函数从头开始执行到yeild语句,返回一个状态;后续再调用next,从上次停止的地方开始执行至下一个yeild或者函数最后。(提供函数暂停执行
  • yeild和return的异同:都可以返回紧跟其后的表达式的值;但是yeild不能用在普通函数中,只能在生成器函数中使用;return只执行一次,yeild可以执行多次;
  • yeild用在表达式中,必须使用圆括号:不知道有啥用???
console.log('Hello' + yield); // SyntaxError
console.log('Hello' + yield 123); // SyntaxError

console.log('Hello' + (yield)); // OK
console.log('Hello' + (yield 123)); // OK

foo(yield 'a', yield 'b'); // OK 函数参数和赋值时,可以不用圆括号
let input = yield; // OK
  • yeild语句本身没有返回值,每次返回undefined(var x = yeild 123;//x是undefined);next方法可以传入一个参数,当做 (上一次) yeild语句的返回值,好处:可以在生成函数运行之后,再次向函数内注入值。
function* foo(x) {
    var y = 2 * (yield (x + 1));
    var z = yield (y / 3);
    return (x + y + z);
}

var a = foo(5);
a.next() // Object{value:6, done:false}
a.next() // Object{value:NaN, done:false}
a.next() // Object{value:NaN, done:true}

var b = foo(5);
b.next() // { value:6, done:false }
b.next(12) // { value:8, done:false }
b.next(13) // { value:42, done:true }

二十三:SIMD

(目前JS引擎基本不支持,可以仅作了解)

SIMD:单指令 多数据(single instruction / mutiply data)
SISD:单指令 单数据(single instruction / single data)--- JS默认运算模式

SIMD是js操作CPU对应指令的接口,完成多个数据的运算,广泛用于3D图形运算、物理模拟等运算量超大的项目之中。

SIMD提供12种数据类型,总长度都是128个二进制位。

Float32x4:四个32位浮点数
Float64x2:两个64位浮点数

Int32x4:四个32位整数
Int16x8:八个16位整数
Int8x16:十六个8位整数

Uint32x4:四个无符号的32位整数
Uint16x8:八个无符号的16位整数
Uint8x16:十六个无符号的8位整数

Bool32x4:四个32位布尔值
Bool16x8:八个16位布尔值
Bool8x16:十六个8位布尔值
Bool64x2:两个64位布尔值

每种数据类型被x符号分隔成两部分,后面的部分表示通道数,前面的部分表示每个通道的宽度和类型。比如,Float32x4就表示这个值有4个通道,每个通道是一个32位浮点数。
利用SIMD的一些静态方法,可以完成一些运算,具体就不展开介绍了,可以参考链接:http://es6.ruanyifeng.com/#docs/simd

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

推荐阅读更多精彩内容

  • 一、ES6简介 ​ 历时将近6年的时间来制定的新 ECMAScript 标准 ECMAScript 6(亦称 ...
    一岁一枯荣_阅读 6,051评论 8 25
  • 三,字符串扩展 3.1 Unicode表示法 ES6 做出了改进,只要将码点放入大括号,就能正确解读该字符。有了这...
    eastbaby阅读 1,510评论 0 8
  • 以下内容是我在学习和研究ES6时,对ES6的特性、重点和注意事项的提取、精练和总结,可以做为ES6特性的字典;在本...
    科研者阅读 3,109评论 2 9
  • 功能: 根据 PinyinType 类型指定要获取的是全拼或者拼音首字母 依赖: 源码:
    翼徳阅读 1,639评论 0 1
  • 前两天我家大狗问了我一个问题"一个女生接受了一个男生的所有示好,各种送礼物搞暧昧都乐享其中,为什么还不给男生一点表...
    皙妃娘娘阅读 5,106评论 1 1