变量必定要在声明后使用,不然报错。es6
var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 10
变量i是var声明的,在全局范围内都有效。因此每一次循环,新的i值都会覆盖旧值,致使最后输出的是最后一轮的i的值。ajax
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6
上面代码中,变量i是let声明的,当前的i只在本轮循环有效,因此每一次循环的i其实都是一个新的变量,因此最后输出的是6。json
只要块级做用域内存在let或const命令,则变量会被绑定在这个区域内,不受外层做用域的变量影响。凡在声明以前使用了变量,则会报错。
注意,若是使用了let或const,typeof 就不安全了数组
var tmp = 123; if (true) { tmp = 'abc'; // ReferenceError let tmp; }
let a = 10; var a = 1; //Uncaught SyntaxError: Identifier 'a' has already been declared
或安全
let a = 10; let a = 1; //Uncaught SyntaxError: Identifier 'a' has already been declared
而且ES6规定,块级做用域之中,函数声明语句的行为相似于let,在块级做用域以外不可引用。数据结构
const只保证变量指向的地址不变,不保证该地址的数据不变。async
const foo = {}; foo.prop = 123; console.log(foo.prop); // 123 foo = {}; // TypeError: "foo" is read-only
若是真的想将对象冻结,应该使用Object.freeze方法。函数
const foo = Object.freeze({}); // 常规模式时,下面一行不起做用; // 严格模式时,该行会报错 foo.prop = 123; // Can't add property prop, object is not extensible
1.解构失败则是undefined,若有默认值则取默认值
2.左右解构不一样则抛error测试
// 报错 let [foo] = 1; let [foo] = false; let [foo] = NaN; let [foo] = undefined; let [foo] = null; let [foo] = {};
上面的表达式都会报错,由于等号右边的值,要么转为对象之后不具有Iterator接口(前五个表达式),要么自己就不具有Iterator接口(最后一个表达式)。ui
事实上,只要某种数据结构具备Iterator接口,均可以采用数组形式的解构赋值。例如set数据类型和Generate函数
解构赋值容许默认值,在定义的时候直接赋值便可
var [x=1]=[,3]; console.log(x) // x = 1
注意,ES6内部使用严格相等运算符(===),判断一个位置是否有值。因此,若是一个数组成员不严格等于undefined,默认值是不会生效的。
对象的解构与数组有一个重要的不一样:数组的元素是按序排列的,取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
对象解构赋值的内部机制:先找到同名属性,而后再赋给对应的变量。真正被赋值的是后者,而不是前者。
var {foo,bar} = {foo:'aaa',bar:'bbb'} 等价于 var {foo:foo,bar:bar} = {foo:'aaa',bar:'bbb'}
默认值生效的条件一样是,对象的属性值严格等于undefined。
注意赋值时不能让大括号在行首
var x; {x} = {x: 1}; // 会报错,由于JavaScript引擎会将{x}理解成一个代码块 var x; ({x} = {x:1}); // 正确写法
字符串也能够解构赋值。这是由于此时,字符串被转换成了一个相似数组的对象。
解构赋值时,若是等号右边是数值和布尔值,则会先转为对象。
function move({x = 0, y = 0} = {}) { return [x, y]; } move({x: 3, y: 8}); // [3, 8] move({x: 3}); // [3, 0] move({}); // [0, 0] move(); // [0, 0] 注意对比与下面代码的区别 function move({x, y} = { x: 0, y: 0 }) { return [x, y]; } move({x: 3, y: 8}); // [3, 8] move({x: 3}); // [3, undefined] move({}); // [undefined, undefined] move(); // [0, 0] 此处是给{x,y}这个对象设置了默认值,而不是给x,y分别设置了默认值
1.变量交换
[x, y] = [y, x];
2.从函数返回多个值
function example() { return [1, 2, 3]; } var [a, b, c] = example();
3.函数参数的定义
function f([x, y, z]) { ... } f([1, 2, 3]);
4.提取JSON数据
var jsonData = { id: 42, status: "OK", data: [867, 5309] }; let { id, status, data: number } = jsonData;
5.函数参数默认值
jQuery.ajax = function (url, { async = true, beforeSend = function () {}, cache = true, complete = function () {}, crossDomain = false, global = true, // ... more config }) { // ... do stuff }; // 指定参数的默认值,就避免了在函数体内部再写var foo = config.foo || 'default foo';这样的语句。
6.遍历Map结构
var map = new Map(); map.set('first', 'hello'); map.set('second', 'world'); for (let [key, value] of map) { console.log(key + " is " + value); } // first is hello // second is world
7.输入模块的指定方法
const { SourceMapConsumer, SourceNode } = require("source-map");
es5中超过ffff值的Unicode字符只能用两个字节表示,可是es6增长了大括号方式
es5: "\uD842\uDFB7" // "𠮷" "\u20BB7" // " 7" es6: "\u{20BB7}" // "𠮷"
还能够在变量中拼接Unicode编码
let hello = 123; hell\u{6F} // 123
1.codePointAt 获取字符的码点,10进制
codePointAt方法是测试一个字符由两个字节仍是由四个字节组成的最简单方法。
function is32Bit(c) { return c.codePointAt(0) > 0xFFFF; } is32Bit("𠮷") // true is32Bit("a") // false
2.String.fromCodePoint() 返回传入码点的对于字符
3.字符串Iterator接口新增,能够用for of遍历字符串
4..at()能返回给定位置的字符串,容许超过FFFF的字符被返回,es5中对应的是charAt
5.includes() 判断字符串中是否包含传入的字符
6.startsWith() 判断字符串的起点是不是传入的字符
7.endsWith() 判断字符串的终点是不是传入的字符
8.repeate() 重复某字符
9.padStart() 补全开头
10.padEnd() 补全结尾
嵌入变量${}
空格、缩进、换行会在输出是保留,能够trim消除
字符串模板嵌套
二进制 0b开头
八进制 0o开头
Number.isNaN
Number.isFinite
Number.isInteger
在JavaScript内部,整数和浮点数是一样的储存方法,因此3和3.0被视为同一个值。
Number.EPSILON 极小的偏差常量
JavaScript可以准确表示的整数范围在-2^53到2^53之间(不含两个端点),超过这个范围,没法精确表示这个值。
Number.isSafeInteger() 安全整数范围
trunc 化零为整
sign 判断正负数
cbrt 计算平方根
clz32 返回一个32位二进制
**指数运算