1. let
let
相较于var
的最大好处是创建了块级作用域,此外也不存在变量提升。
{
let a = 10;
var b = 1;
}
console.log(a) // ReferenceError: a is not defined.
console.log(b) // 1
没有块级作用域所引起的问题:用来计数的循环变量被泄露为全局变量。
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5
2. const
const
声明一个只读的常量。一旦声明,常量的值就不能改变。const
一旦声明就必须立即初始化,不能留到以后赋值。const
也有块级作用域,也不存在变量提升。
const
本质上并不是保证变量的值不得改动,而是变量指向的那个内存地址不得改动。
- 对于数值、字符串、布尔值等,值就保存在变量指向的那个内存地址,因此等同于常量。
- 对于对象、数组,变量所保存的只是一个指针,
const
只能保证这个指针指向的对象不能改变,而指针所指向的对象的内部属性是可以改变的。> 盒子不能变,而盒子里面的东西可以变。
3. 字符串
几个新增的函数:at()
、startsWith()
、endsWith()
、includes()
、repeat()
、padStart()
、padEnd()
、matchAll()
//at
'𠮷'.charAt(0) // "\uD842"
'𠮷'.at(0) // "𠮷"
// startsWith、endsWith、includes
let s = 'Hello world!';
s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true ,这里表示针对前n个字符
s.includes('Hello', 6) // false
// repeat
'x'.repeat(3) // "xxx"
// padStart、padEnd
// 第一个参数指定字符串的最小长度,第二个参数是用来补全的字符串。
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(4, 'ab') // 'xaba'
引入了使用反引号(`)的模板字符串。
4. 函数
参数的默认值
允许为参数设定默认值,并可直接写在参数定义的后面。
function log(x, y = 'World') {
console.log(x, y);
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
rest / spread操作符(…)
rest
被用于函数传参,是为了获取函数的多余参数,在传参时可把参数转为数组。
// rest参数的写法1
const sortNumbers = (...numbers) => numbers.sort();
sortNumbers(5,6,8,1,4) // [1, 4, 5, 6, 8]
// rest参数的写法2
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
let add = sum(...values) =>(values.sum());
add(2, 5, 3) // 10
spread
则用于函数调用,其参数是数组,效果是将其展开为独立元素。
function foo(x,y,z) {
console.log(x,y,z);
}
let arr = [1,2,3];
foo(...arr); // 1 2 3
name属性
.name
方法返回函数的函数名。
function foo() {}
foo.name // "foo"
箭头函数
使用“箭头”(=>
)定义函数,圆括号代表参数部分。
let sum = (num1, num2) => num1 + num2;
const isEven = n => n % 2 == 0;
const square = n => n * n;
// 简化回调函数
[1,2,3].map(function (x) {
return x * x;
});
[1,2,3].map(x => x * x);
如果箭头函数直接返回一个对象,必须在对象外面加上括号。
// 报错
let getTempItem = id => { id: id, name: "Temp" };
// 不报错
let getTempItem = id => ({ id: id, name: "Temp" });
使用的注意点:
(1)函数体内的this
对象,是定义时所在的对象,而不是使用时所在的对象;
(2)不可以当作构造函数(不可以使用new
命令);
(3)不可以使用arguments
对象,如果要用,可以用rest
代替;
(4)不可以使用yield
命令,因此箭头函数不能用作 Generator 函数。
对apply、call和bind的回顾
三种写法用于显式绑定this
对象。
apply
方法的第一个参数是要绑定给this的值,第二个参数是一个参数数组。call
方法第一个参数是要绑定给this的值,从第二个参数开始传入参数列表。bind
方法第一个参数是this
的指向,从第二个参数开始传入的参数列表,返回值是函数。【注意:bind
方法所创建的新函数的this
值是传递给bind()
的第一个参数,而其余参数则作为新函数的参数】
// bind
function fn(a, b, c) {
return a + b + c;
}
var _fn = fn.bind(null, 10);
var ans = _fn(20, 30); // 60
双冒号运算符
双冒号运算符(::
)又称函数绑定运算符,其左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this
对象),绑定到右边的函数上面。
foo::bar;
// 等同于
bar.bind(foo);
foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);
5. 数组
一些常用的方法
数组求最大值:
var arr = [1, 2, 3, 89, 46]
// apply
var maxApply = Math.max.apply(null,arr) // 89
// call
var maxCall = Math.max.call(null, arr[0], arr[1], arr[2], arr[3], arr[4]) // 89
// spread...
let maxSpread = Math.max(...arr) // 89
数组追加:
// apply
// 注:push()方法的返回值是新的长度
var arr1 = [1,2,3];
var arr2 = [4,5,6];
var total = [].push.apply(arr1, arr2); // 6
// 也可以用Array.prototype.push.apply(arr1, arr2);
console.log(arr1) // [1, 2, 3, 4, 5, 6]
console.log(arr2) // [4, 5, 6]
// spread
arr1.push(...arr2);
数组复制:
const a1 = [1, 2];
const a2 = a1;
a2[0] = 2;
a1 // [2, 2]
// 直接复制仅复制了指向底层数据结构的指针,而非克隆一个全新的数组。
const a3 = [...a1];
a3 // [1, 2]
数组合并(浅拷贝):
const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];
// ES5
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]
// ES6
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
字符串转数组
[...'hello']
// [ "h", "e", "l", "l", "o" ]
Array.of()
Array.of
方法用于将一组值转换为数组。
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.from()
Array.from
方法用于将类似数组的对象(Array-Like Objects,例如NodeList,arguments,字符串等具有length
属性的对象)和可遍历的对象(Iterable Objects,例如Map和Set等)转为真正的数组。
// NodeList对象
let ps = document.querySelectorAll('p');
Array.from(ps).filter(p => {
return p.textContent.length > 100;
});
// arguments对象
function func1(a, b) {
console.log(arguments[0]);
console.log(arguments[1]);
let args = Array.from(arguments);
console.log(args)
}
func1(1, 2); /*
> 1
> 2
> [1, 2] */
6. Promise对象
7. Iterator
8. Generator函数
Generator 函数是 ES6 提供的一种异步编程解决方案。
执行 Generator 函数会返回一个遍历器对象,它可以依次遍历 Generator 函数内部的每一个状态。
Generator 函数比普通函数多了两个特征。一是function
关键字与函数名之间有一个星号;二是函数体内部使用yield
表达式,定义不同的内部状态。
调用 Generator 函数后并不执行函数,也不返回函数运行结果,而返回一个指向内部状态的指针对象(遍历器对象),下一步必须调用遍历器对象的next
方法,使得指针移向下一个状态。
每次调用遍历器对象的next
方法,就会返回一个有着value
和done
两个属性的对象。value
属性表示当前的内部状态的值,是yield
表达式后面那个表达式的值;done
属性是一个布尔值,表示是否遍历结束。