美文网首页
ES6初始记录(较乱)

ES6初始记录(较乱)

作者: shanshanfei | 来源:发表于2016-11-29 15:46 被阅读0次

转码器: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

相关文章

  • ES6初始记录(较乱)

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

  • React中ES6和ES5的不同之处

    组件类的定义 es5 es6 状态初始化 es5 }) es6 属性初始化 es5 es6 组件抛出 es5 es...

  • React&React-Native 学习笔记(持续更新)

    在es6写法中,初始化props不再用getDefaultProps方法,而应该使用 在es6写法中,初始化sta...

  • 初始记录

    从今天开始 每天都要写日记哦~ 盼望着盼望着,春节还没有来,2019年的一月份却就这样结束了。浑浑噩噩的,感觉还没...

  • 创建对象及属性修饰

    对象初始化方法: ES5方法: 字面量方法: ES6方法: 使用ES6的Object.create(Object....

  • const,let,var 变量声明

    ES6前有全局作用域和函数作用域,声明变量用var。ES6 后新增块作用域。 1.Const 定义常量,初始化时必...

  • ES6: Object

    ES6: Object 方法定义 语法更加简介 Get 和 Set 方法较 ES5 没有变化, 不过 Get 方法...

  • 贵班男生宿舍较乱。。

    昨天是军训的第一天!军训开启仪式结束后,各个班级便开始了长达七周的军事化训练!巧合的是,我们班的教官竟然是我16级...

  • 日期处理

    时间格式 yyyy-MM-dd HH:mm 日历部分 较乱 补充

  • Android-JS交互beta

    Android 与 Js 较互 html: test.html: Android端: WebView初始化: Js...

网友评论

      本文标题:ES6初始记录(较乱)

      本文链接:https://www.haomeiwen.com/subject/bsgapttx.html