ES6标准之基础
let和const命令
ES6新增let命令,用于声明变量,是块级作用域。
let声明的变量不会像var声明的变量发生“变量提升”现象,所以,变量一定要在声明后使用,不然就会报错。
暂时性死区:只要块级作用域内存在let命令,它所声明的变量就会“绑定”在这个区域,不再受外部的影响。即在代码块内,使用let命令声明变量之前,这个变量都是不可用的,这在语法上称为“暂时性死区”。
ES6规定暂时性死区和不存在变量提升,主要是为了减少运行时的错误,防止在变量声明前就使用这个变量,导致意外,这样的错误在ES5中很常见。
let不允许在相同作用域内重复声明同一个变量。
const命令用来声明常量,声明了之后就不能再改变,所以在声明的时候就必须赋值,这个命令同样是块级作用域,同样存在暂时性死区。
对于用const声明的对象,变量名不会指向对象的数据,而是指向对象所在的地址,所以用const声明的复合类型变量中的数据是可以改变的,这点需要当心!
变量的解构赋值
解构:ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被成为解构。如下:
//ES5
var a = 1;
var b = 2;
var c = 3; //ES6
var [a, b, c] = [1, 2, 3]; //嵌套
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo;//
bar;//
baz;// //如果等号右边不是可以遍历的结构,就无法匹配就会报错。解构赋值是允许设置默认值的,在ES6内部使用'==='来判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效的。例如:
[x, y = 'b'] = ['a', undefined];//x='a',y='b'
[x = 1] = [null];//x=null默认值可以引用解构赋值的其他变量,但该变量必须已经声明。例如:
let [x = 1, y = x] = []; //x=1; y=1
let [x = 1, y = x] = [2]; //x=2; y=2
let [x = 1, y = x] = [1, 2]; //x=1; y=2
let [x = y, y = 1] = []; //报错,因为x在使用y作为其默认值的时候y还没有被声明对象的解构赋值:
var {foo, bar} = {foo: "aaa", bar:"bbb"};
foo //"aaa"
bar //"bbb"
对象的解构赋值和数组有一个重要的不同:数组的元素是按次序排列的,变量的取值由它的位置来决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
对象的解构赋值可以很方便地将现有对象的方法赋值到某个变量。例如:
let {log, sin, cos} = Math;
//这样就可以把取对数、正弦、余弦3个方法赋值到对应的变量上面,用起来很方便;字符串也可以解构赋值,因为字符串会被转换成一个类似数组的对象。例如:
const [a, b, c, d, e] = 'hello';
a // 'h'
b // 'e'
c // 'l'
d // 'l'
e // 'o' let {length : len} = 'hello';
len //数值和布尔值的解构赋值:解构赋值时,如果等号右边是数值或布尔值,则会先转为对象。
函数参数也可以解构赋值,例如:
function add([x,y]){
return x + y;
} add([1, 2]) //变量的解构赋值的用途很多,简洁易读:
交换变量的值
[x, y] = [y, x]
;从函数返回多个值;
example(){ return [1, 2, 3];
}[a, b, c] = example();
函数参数的定义;
//有序
function f([x, y, z]){...};
f([1, 2, 3]); //无序
function f({x, y, z}){...};
f({z:3, y:2, x:1});提取JSON数据,可以快速提取json对象中的数据;
字符串的扩展
ES6加强了对Unicode的支持,并且扩展了字符串对象。
ES5对字符串对象提供了CharAt方法,返回字符串给定位置的字符。但是该方法不能识别码点大于0xFFFF的字符。于是在ES7中提供了一个at方法,可以识别Unicode编号大于0xFFFF的字符。
includes(),startsWith(),endsWith()方法。JS中只有indexOf方法可以用来确定一个字符串是否包含在另一个字符串中,ES6又提供了三种方法:
includes():返回布尔值,表示是否找到了参数字符串;
startsWith():返回布尔值,表示参数字符串是否在源字符串的头部;
endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部;
repeat(),repeat方法返回一个新字符串,表示将原字符串重复n次。
padStart(),padEnd():ES7推出了字符串补全长度的功能。如果某个字符串长度未达指定长度,会在头部或尾部补全。padStart用于头部补全,padEnd用于尾部补全。如果原字符串的长度大于或等于指定的最小长度,则返回原字符串。例如:
'x'.padStart(5, 'ab') //'ababx'
'x'.padStart(4, 'ab') //'abax' 'x'.padEnd(5, 'ab') //'xabab'
'x'.padEnd(4, 'ab') //'xaba' 'xxx'.padStart(2, 'ab') //'xxx'
正则的扩展
在ES5中,RegExp构造函数只能接受字符串作为参数
var regex = new RegExp("xyz", "i");
。在ES6中允许RegExp构造函数接受正则表达式作为参数,这时会返回一个原有正则表达式的拷贝。ES6新增了使用大括号表示Unicode字符的表示法,这种表示法在正则表达式中必须加上u修饰符才能识别。例如:
/\u{61}/.test('a'); //false
/\u{61}/u.test('a'); //trueES6为正则表达式新增了flags属性,会返回正则表达式的修饰符。ES5的source属性会返回表达式的正文。
数值的扩展
ES6提供了二进制和八进制数值的新写法,分别用前缀0b(或0B)和0o(或0O)来表示。从ES5开始,在严格模式中,八进制数值就不再允许使用前缀0表示,ES6进一步明确,要使用0o前缀表示。
Number.isFinite(),Number.isNaN():ES6在Number对象上面新提供了这两个方法,分别用于检查Infinite(是否非无穷)和NaN这两个特殊值。
Number.parseInt(),Number.parseFloat():ES6将全局方法parseInt()和parseFloat()移植到了Number对象上。这样是为了逐步减少全局性的方法,使语言逐步模块化。
//ES5
parseInt(''); //ES6
Number.parseInt(''); Number.parseInt === parseInt; //trueNumber.isInteger():该方法用来判断一个值是否为整数。
新增了一个极小的常量Number.EPSILON,当我们做计算的时候,如果误差可以小于这个常量,那么就可以认为计算的结果是正确的。
Number.isSafeInteger():JavaScript能够准确表示的整数范围在-2{53}到2{53}之间,超出的就不能精确表示了,该函数用来判断一个数是否落在这个范围之内。
Math对象的扩展,ES6在Math对象上新增了17个与数学相关的方法:
Math.trunc():用于去除小数部分,返回整数部分;
Math.sign():用于判断一个数到底是正数、负数还是0,整数返回1,负数返回-1,0返回0,-0返回-0,其他返回NaN;
Math.cbrt():计算一个数的立方根;
Math.clz32():返回一个数的32位无符号数有多少个前导0;
Math.imul():返回两个数以32位带符号整数形式相乘的结果,返回的也是一个带符号整数,例如:
Math.imul(-1, 8); //-8
Math.fround():返回一个数的单精度浮点数形式;
Math.hypot():返回所有参数平方和的平方根,例如:
Math.hypot(3, 4);//5
还有一些和对数运算、三角函数运算、指数运算相关的方法。
数组的扩展
Array.from():将类似数组的对象和可遍历的对象转为真正的数组;
Array.of():将一组数值转换为数组,例如:
Array.of(3, 11, 8) //[3,11,8]
fill()方法,使用给定值填充数组,例如:
new Array(3).fill(7) //[7,7,7]
数组实例的entries()、keys()、和values()方法,主要用来遍历数组,keys()是对键名的遍历,values()是对键值的遍历,entries()是对键值对的遍历;
函数的扩展
ES6之前不能直接为函数的参数指定默认值,所以经常有
x = x || "XXX"
这样的写法,ES6允许为函数的参数设置默认值,就可以这样写function test(x, y = "xxx"){};
,这样的设计还有一个好处就是开发人员阅读别人的代码一眼就能看出来在调用这个接口哪些参数是可省的。此外,这种写法还可以和解构赋值结合使用,非常灵活。函数的length属性修改,如果函数中的参数有指定默认值,那么length就不会把这个参数计算进去,例如:
(function(a=5){}).length;//0
作用域问题,如果一个参数的默认值是一个变量,那么这个变量所处的作用域与其他变量的作用域规则是一样的,先是当前函数的作用域,然后才是全局作用域;
ES6引入了rest参数(形式为"...变量名"),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入其中,例如:
function add(...values){
let sum = 0;
for(var val of values){
sum += val;
}
return sum;
}
add(2, 5, 3); //
//add函数是一个求和函数,利用rest参数可以向该函数传入任意数目的参数。扩展运算符,三个点(...),作用是把一个数组转为用逗号隔开的参数序列。例如:
console.log(1,...[2,3,4],5);//1 2 3 4 5
;扩展运算符替代数组的apply方法,扩展运算符可以直接把数组拆开,例如:
//ES5
function f(x,y,z){};
var args = [0,1,2];
f.apply(null, args); //ES6
function f(x,y,z){};
var args = [0,1,2];
f(...args);扩展运算符提供了数组合并的新方法:
//ES5
[1,2].concat(more)
//ES6
[1,2, ...more]扩展运算符还可以与解构赋值结合;
ES6还写入了函数的name属性,可以返回函数名,虽然这个属性很早就被各个浏览器支持了,但是在ES6才正式写入;
箭头函数:ES6允许使用"箭头"(=>)定义函数,例如:
var sum = (num1, num2) => num1 + num2;
//等价于
var sum = function(num1, num2){
return num1 + num2;
}使用箭头函数有几个注意点:
函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象。在js中this的指向是可以改变的,但是在箭头函数中this的指向是不变的;
不可以当作构造函数。也就是说,不可以使用new命令;
不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用ES6中的rest参数代替;
不可以使用yield命令,因此箭头函数不能用作Generator函数;
函数绑定:在ES6之后的ES7版本中有一个提案是函数绑定运算符(::),双冒号左边是一个对象,右边是一个函数。这个运算符会自动将左边的对象作为this绑定到右边的函数上面,例如:
foo::bar(...arguments)等价于bar.apply(foo,arguments;)
。感觉函数绑定这个设计非常的便捷,不需要在显式的去绑定一下上下文,期待该提案的通过(目前babel已经支持这个写法了);尾调用:就是指某个函数的最后一步是调用另一个函数;
尾调用优化:尾调用之所以与其他调用不同,就在于其特殊的调用位置。函数调用的时候会在内存形成一个‘调用记录’,又称为‘调用帧’,保存调用位置和内部变量等信息。如果在函数A内部调用函数B,那么在A的调用帧上方还会形成一个B的调用帧。等到B执行结束再返回给A,B的调用帧才消失。如果B的内部调用了C,那么还会产生一个调用帧,以此类推,所有调用帧会形成一个‘调用栈’。然而尾调用是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息都不会再用到了,直接用内层函数的调用帧取代外层函数的即可;
尾递归:函数调用自身称为递归,如果尾调用自身就称为尾递归。递归非常耗费内存,因为需要同时保存成千上百个调用帧,很容易stackoverflow。但对于尾递归来说,只存在一个调用帧,所以永远不会发生“栈溢出”错误。例如:
//这是一个阶乘函数,计算n的阶乘,最多需要保存n个调用记录,复杂度为O(n)。
function factorial(n){
if(n === 1) return 1;
return n * factorial(n - 1);
}
//改写成尾递归,只保用一个调用记录,则复杂度为O(1);
function factorial(n, totla){
if(n === 1) return total;
return factorial(n - 1, n * total);
}由此可见‘尾调用优化’对于递归操作的意义非常重大,所以一些函数式编程语言将其写入了语言规格。ES6也是如此,第一次明确规定,所有ECMAScript的实现,都必须部署‘尾调用优化’。这就是说,在ES6中,只要使用尾递归,就不会栈溢出,节省内存。
ES6标准之基础的更多相关文章
- ES6标准中的import和export
在ES6前, 前端使用RequireJS或者seaJS实现模块化, requireJS是基于AMD规范的模块化库, 而像seaJS是基于CMD规范的模块化库, 两者都是为了为了推广前端模块化的工具 ...
- ES6标准
1. ES6标准感觉越来越向传统语言靠拢了,以后写到ES6的标准都记录下: ,,]; // =>操作符 array.forEach(v => console.log(v)); 是不是简化了 ...
- python linecache标准库基础学习
#python标准库基础之:linecacge:高效读取文本文件#说明与作用"""可以从文件或者导入python模块获取文件,维护一个结果缓存,从而可以更高效地从相同文件 ...
- C 标准库基础 IO 操作总结
其实输入与输出对于不管什么系统的设计都是异常重要的,比如设计 C 接口函数,首先要设计好输入参数.输出参数和返回值,接下来才能开始设计具体的实现过程.C 语言标准库提供的接口功能很有限,不像 Pyth ...
- ES6标准入门之变量的解构赋值简单解说
首先我们来看一看解构的概念,在ES6标准下,允许按照一定模式从数组和对象中提取值,然后对变量进行赋值,这被称作解构,简而言之粗糙的理解就是变相赋值. 解构赋值的规则是,只要等号右边的值不是对象或者数组 ...
- ES6标准简介之Babel转码器解说
ES6是ECMAScript 6的简称,是JavaScript语言的下一代标准,现在基于jquery库的前端开发js所使用的标准是ES5(ECMAScript 5).ES6已于2015年6月正式发布. ...
- ES6标准入门 2/26
第一章 ECMAScript6 简介 1.首先经典开头,ECMAScript跟JavaScript的关系,前者是后者的规格,后者是前者的一种实现.在日常场合中,这两个词是可以互换的. 2.ES6可以泛 ...
- 【学习笔记】ES6标准入门
这里简要记录一下对自己感触比较深的几个知识点,将核心的应用投放于实际的项目之中,提供代码的可维护性. 一.let和const { // let声明的变量只在let命令所在的代码块内有效 let a = ...
- python calendar标准库基础学习
# -*- coding: utf-8 -*-# 作者:新手__author__ = 'Administrator'#标准库:日期时间基础学习:calendar:处理日期#例1import calen ...
随机推荐
- iOS NSCache缓存类的了解
前言: 最近面试时,问到了限定并发数的视频下载,当时回答的时通过GCD_barrier 处理,回来想想也可以通过NSCache处理,所以顺便复习一下,这个知识点. 一,关于NSCache说明 说明 ...
- Java开发想尝试大数据和数据挖掘,如何规划学习?
大数据火了几年了,但是今年好像进入了全民大数据时代,本着对科学的钻(zhun)研(bei)精(tiao)神(cao),我在17年年初开始自学大数据,后经过系统全面学习,于这个月跳槽到现任公司. 现在已 ...
- Node项目的Restful化
提倡Restful风格的目的或者作用主要是,结构清晰.符合标准.易于理解.扩展方便. 个人把Restful简单粗暴地理解为:路由不包含动词. 怎么做到路由不包含动词呢?答案是,启用常用的GET和POS ...
- vue:不同环境配置不同打包命令
修改prod.env.js 'use strict'const target = process.env.npm_lifecycle_event;if (target == 'build') { // ...
- 15 个 Android 通用流行框架大全(转载)
1. 缓存 DiskLruCache Java实现基于LRU的磁盘缓存 2.图片加载 Android Universal Image Loader 一个强大的加载,缓存,展示图片的库 Picas ...
- python之requests模块快速上手
安装 pip3 install requests 使用 发送请求 import requests r = requests.get('http://www.baidu.com') 还可以如下方式发送不 ...
- 引入css的两种方式
摘自:https://www.cnblogs.com/gyjWEB/p/4831646.html 在HTML中引入css的其中的两个方法: 1.如果使用链接式,需要使用如下的语句引入外部css文件: ...
- openshift 容器云从入门到崩溃之六《Source-to-Image》
上次说到了怎么在oc上面部署应用而且说道了怎么定义模板部署应用,也许你会奇怪那个我代码打包编译在哪一步,那就要说道oc的s2i流程了 下面是基本s2i流程 1.制作base-image镜像 要使用s2 ...
- Kafka笔记1(初步认识)
Kafka 被称为“分布式提交日志”或“分布式流平台” 文件系统或数据库提交日志用来提供所有事务的持久记录,通过重放这些日志重建系统状态,同时Kafka数据是按照一定顺序持久化保存的,可以按需读取 K ...
- 027-Session状态提供程序
Session分三种:1.InProc(进程内)-默认就是这种-速度快/但内存小/易丢失进程外:可以在IIS或ASPNET服务意外关闭时继续保持状态,注意此时存储到session中的对象必须支持序列化 ...