let 区块
let num = 10 ;
for (let i = 0 ;i < 10 ;i++)
{
let num = 0 ;
num += i;
}
document.write(num);
forEach
let arr = [1 ,2 ,3 ,4 ,5 ];
arr.forEach(function (value,index,arry)
{
document.write(value + " " + index + " " + arry);
});
const
if (true ) {
const MAX = 5 ;
}
MAX
const foo = {};
foo.prop = 123 ;
foo.prop
foo = {};
数组的解构赋值
let [a, b, c] = [1 , 2 , 3 ];
let [foo, [[bar], baz]] = [1 , [[2 ], 3 ]];
foo
bar
baz
let [ , , third] = ["foo" , "bar" , "baz" ];
third
let [x, , y] = [1 , 2 , 3 ];
x
y
let [head, ...tail] = [1 , 2 , 3 , 4 ];
head
tail
let [x, y, ...z] = ['a' ];
x
y
z
let [foo = true ] = [];
foo
let { foo, bar } = { foo: "aaa" , bar: "bbb" };
foo
bar
const [a, b, c, d, e] = 'hello' ;
a
b
c
d
e
let arr = [1 , 2 , 3 ];
let {0 : first, [arr.length - 1 ] : last} = arr;
first
last
数组arr的0 键对应的值是1 ,[arr.length - 1 ]就是2 键,对应的值是3 。方括号这种写法,属于“属性名表达式”
用途:
1 )交换变量的值
let x = 1 ;
let y = 2 ;
[x, y] = [y, x];
2 )从函数返回多个值
function example () {
return [1 , 2 , 3 ];
}
let [a, b, c] = example();
3 )函数参数的定义
function f ([x, y, z]) { ... }
f([1 , 2 , 3 ]);
function f ({x, y, z}) { ... }
f({z: 3 , y: 2 , x: 1 });
for…in和for…of
1. 推荐在循环对象属性的时候,使用for ...in ,在遍历数组的时候的时候使用for ...of (for ..of 不能遍历出属性)。
2. for ...in 循环出的是key,for ...of 循环出的是value
3. 注意,for ...of 是ES6新引入的特性。修复了ES5引入的for ...in 的不足
4. for ...of 不能循环普通的对象,需要通过和Object.keys()搭配使用
var student={
name :'wujunchuan' ,
locate :{
country :'china' ,
school :'XMUT'
}
}
for (var key of Object.keys(student)){
// 使用Object.keys()方法获取对象key的数组
console .log(key+": " +student[key]);
}
字符串扩展
indexOf() :返回遇到的第一个值的index,未找到返回-1
includes() :返回布尔值,表示是否找到了参数字符串。
startsWith() :返回布尔值,表示参数字符串是否在原字符串的头部。
endsWith() :返回布尔值,表示参数字符串是否在原字符串的尾部。
repeat() :返回一个新字符串,表示将原字符串重复n次。
//'hello' .repeat(2 )
// "hellohello"
padStart():前补全字符串
padEnd(): 后补全字符串
'x' .padStart(5 , 'ab' ) // 'ababx'
'x' .padStart(4 , 'ab' ) // 'abax'
'x' .padEnd(5 , 'ab' ) // 'xabab'
'x' .padEnd(4 , 'ab' ) // 'xaba'
//字符串模板
let name = "Bob" , time = "today" ;
`Hello ${name}, how are you ${time }?`
字符串必须用``包围 转义无效
tag函数的第一个参数是一个数组,该数组的成员是模板字符串中那些没有变量替换的部分,也就是说,变量替换只发生在数组的第一个成员与第二个成员之间、第二个成员与第三个成员之间,以此类推。
tag(['Hello ' , ' world ' , '' ], 15 , 50 )
String.raw
String.raw 方法,往往用来充当模板字符串的处理函数,返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串,对应于替换变量后的模板字符串。
String.raw ({ raw: 'test' }, 0 , 1 , 2 );
正则匹配
https: //developer.mozilla .org /zh -CN/docs/Web/JavaScript/Guide/Regular_Expressions
数值扩展
1. 进制:
ES6二进制和八进制数值用前缀0 b(或0 B)和0 o(或0 O)表示。
0 b111110111 === 503
0 o767 === 503
2. Number .isFinite(), Number .isNaN() :
Number .isFinite()用来检查一个数值是否为有限的(finite)。
Number .isNaN()用来检查一个值是否为NaN 。
3. Number .isInteger()
Number .isInteger()用来判断一个数值是否为整数。
4. Number .parseInt(), Number .parseFloat()
parseInt ('12.34' )
parseFloat ('123.45#' )
Number .parseInt('12.34' )
Number .parseFloat('123.45#' )
rest 参数
参数代替arguments(...变量名 rest )
function test (...values ) {
let sum = 0 ;
for (let i in values){
sum += values[i];
}
return sum;
}
console.log(test(1 ,23 ,4 ,12 ,541 ,24 ));
函数名
函数.name属性
function foo () { }
foo.name
“箭头”(=>)定义函数
var f = v => v;
上面的箭头函数等同于:
var f = function (v) {return v;};
1. 函数体内的this 对象,就是定义时所在的对象,而不是使用时所在的对象。
2. 不可以当作构造函数,也就是说,不可以使用new 命令,否则会抛出一个错误。
3. 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
4. 不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
function Timer() {
this .s1 = 0 ;
this .s2 = 0 ;
// 箭头函数
setInterval(() => this .s1++, 1000 ) ;
// 普通函数
setInterval (function () {
this .s2++;
}, 1000 ) ;
}
var timer = new Timer () ;
setTimeout (() => console .log('s1: ' , timer.s1), 3100 ) ;
setTimeout (() => console .log('s2: ' , timer.s2), 3100 ) ;
// s1 : 3
// s2 : 0
箭头函数可以让this 指向固定化,这种特性很有利于封装回调函数。
双冒号运算符
函数绑定运算符(::),左边是个对象,右边是函数。该运算符会将左边的对象绑定到右边的函数,即this 对象。
foo::bar;
bar.bind(foo);
foo::bar(...arguments);
bar.apply(foo, arguments );
const hasOwnProperty = Object .prototype.hasOwnProperty;
function hasOwn (obj, key) {
return obj::hasOwnProperty(key);
}
尾调用
function f (x) {
return g(x);
}
ES6 的尾调用优化只在严格模式下开启,正常模式是无效的。
尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用帧,取代外层函数的调用帧就可以了。
函数调用自身,称为递归。如果尾调用自身,就称为尾递归。
递归非常耗费内存,因为需要同时保存成千上百个调用帧,很容易发生“栈溢出”错误(stack overflow)。但对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误。
数组扩展
复制数组
es5 :
const a1 = [1 , 2 ];
const a2 = a1.concat();
a2[0 ] = 2 ;
a1 // [1 , 2 ]
es6 :
const a1 = [1 , 2 ];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;
合并数组
// ES5
[1 , 2 ].concat(more)
// ES6
[1 , 2 , ...more]
var arr1 = ['a' , 'b' ];
var arr2 = ['c' ];
var arr3 = ['d' , 'e' ];
// ES5的合并数组
arr1.concat(arr2, arr3);
// [ 'a' , 'b' , 'c' , 'd' , 'e' ]
// ES6的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a' , 'b' , 'c' , 'd' , 'e' ]
Array.from()
Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。
let arrayLike = {
'0' : 'a' ,
'1' : 'b' ,
'2' : 'c' ,
length : 3
};
// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a' , 'b' , 'c' ]
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a' , 'b' , 'c' ]
Array.of ()
Array.of 方法用于将一组值,转换为数组。
Array.of (3 , 11 , 8 ) // [3 ,11 ,8 ]
Array.of (3 ) // [3 ]
Array.of (3 ).length // 1
copyWithin()
数组实例的copyWithin方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。
target(必需):从该位置开始替换数据。如果为负值,表示倒数。
start(可选):从该位置开始读取数据,默认为 0 。如果为负值,表示倒数。
end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
[1 , 2 , 3 , 4 , 5 ].copyWithin(0 , 3 , 4 )
// [4 , 2 , 3 , 4 , 5 ]
数组实例的 find() 和 findIndex()
数组实例的find方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true 的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined 。
[1 , 4 , -5 , 10 ].find((n) => n < 0 )
// -5
[1, 5, 10, 15].find (function (value, index, arr) {
return value > 9 ;
}) // 10
数组实例的findIndex 方法的用法与find 方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。
[1, 5, 10, 15].findIndex (function (value, index, arr) {
return value > 9 ;
}) // 2
fill ()
用于填充数组
new Array (3 ) .fill (7 )
// [7, 7, 7]
['a ', 'b ', 'c '].fill (7 , 1 , 2 )
// ['a ', 7, 'c ']
上面代码表示,fill 方法从 1 号位开始,向原数组填充 7,到 2 号位之前结束。
数组实例的 entries () ,keys () 和 values ()
for (let index of ['a' , 'b' ].keys()) {
console .log (index) ;
}
// 0
// 1
for (let elem of ['a' , 'b' ].values()) {
console .log (elem) ;
}
// 'a '
// 'b '
for (let [index, elem] of ['a' , 'b' ].entries()) {
console .log (index, elem) ;
}
// 0 "a "
// 1 "b "
includes ()
Array .prototype .includes 方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes 方法类似。该方法的第二个参数表示搜索的起始位置,默认为0。
[1, 2, NaN ].includes (NaN) // true
[1, 2, 3].includes (3 , 3 ) ; // false
[1, 2, 3].includes (3 , -1 ) ; // true
数组的空位
注意,空位不是undefined ,一个位置的值等于undefined ,依然是有值的。空位是没有任何值,in 运算符可以说明这一点。
Array (3 ) // [, , ,]
0 in [undefined , undefined , undefined ] // true
0 in [, , ,] // false
ES6 则是明确将空位转为undefined 。
属性的简洁表示法
const foo = 'bar' ;
const baz = {foo};
baz
const baz = {foo: foo};
function f (x, y) {
return {x, y};
}
function f (x, y) {
return {x: x, y: y};
}
f(1 , 2 )
const o = {
method() {
return "Hello!" ;
}
};
const o = {
method: function () {
return "Hello!" ;
}
};
Object.is()
ES5 比较两个值是否相等,只有两个运算符:相等运算符(==)和严格相等运算符(===)。它们都有缺点,前者会自动转换数据类型,后者的NaN 不等于自身,以及+0 等于-0 。JavaScript 缺乏一种运算,在所有环境中,只要两个值是一样的,它们就应该相等。
ES6 提出“Same-value equality”(同值相等)算法,用来解决这个问题。Object .is就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。不同之处只有两个:一是+0 不等于-0 ,二是NaN 等于自身。
Object .is('foo' , 'foo' )
Object .is({}, {})
Object .is(+0 , -0 )
Object .is(NaN , NaN )
Object.assign()
Object .assign方法用于对象的合并
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object .assign(target, source1, source2);
target
注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。Object .assign方法实行的是浅拷贝,而不是深拷贝。一旦遇到同名属性,Object .assign的处理方法是替换.Object .assign可以用来处理数组,但是会把数组视为对象。
Object .assign([1 , 2 , 3 ], [4 , 5 ])
Object .assign只能进行值的复制,如果要复制的值是一个取值函数,那么将求值后再复制。
const source = {
get foo() { return 1 }
};
const target = {};
Object .assign(target, source)