1. let 与var区别
不同之处:
—- let变量所在的代码块内有效,而var没有块级作用域的概念,只有全局变量和局部变量的概念;
—- let声明的变量不存在变量提升,未声明变量使用变量会报错,var 声明的变量存在变量提升;
—- let存在暂时性死区;暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
—- let不允许在相同作用域下重复声明同一个变量;
—-let声明的变量不会与顶层对象挂钩,而var声明的变量与顶层对面挂钩。
关于const:
const声明的是常量,不允许修改。同样不存在变量提升,变量暂时性死区。针对于基础数据来说,const保证的其实是变量指向的那个内存地址不得改动,而不是值不可以改动。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的。
const foo = {};
foo.hello = 'hi';//不会报错;
foo = {};//会报错;
2. 关于解构赋值
解构赋值的定义:可以按照一定模式,从数组和对象中提取值,对变量进行赋值
let [a,b,c] = [1,2,3] //类似于let a = 1,b = 2,c = 3;
let [foo, [[bar], baz]] = [1, [[2], 3]];
let [head, ...tail] = [1, 2, 3, 4];//head = 1, tail = [2,3,4]
//当等式右边不为数组时,则会出现报错情况。
let [foo] = 1;
let [foo] = Null;
//对于set解构的解构赋值
let [x, y, z] = new Set(['a', 'b', 'c']);
x //'a'
y //'b'
同时解构赋值允许默认值
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
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] = []; // ReferenceError x引用y时,y还未声明
针对于对象的解构赋值,但是需要找到同名的属性,当未找到时,则是undefined.
let {foo} = {foo:'bar'};//foo 'bar'
let { baz } = { foo: "aaa", bar: "bbb" };
baz // undefined
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
函数参数的解构赋值
function add([x,y]) {
return x+y;
}
console.log(add([1,2]));
3. 字符串的扩展
ES6为字符串添加了遍历接口,可以使用for…of进行遍历
for(let key of 'foo'){
console.log(key);
}
且遍历器最大优点是可以识别大于0xFFFF的码点
var text = String.fromCodePoint(0x20BB7);
for (let i = 0; i < text.length; i++) {
console.log(text[i]);
}
// " "
// " "
for (let i of text) {
console.log(i);
}
// 可以识别
同时提供了新的三种方法,includes(),startWith,endsWidth,第二个参数表示开始搜索的位置
var s = 'Hello world!';
s.startsWith('Hello') // true 参数是否在原字符的头部
s.endsWith('!') // true 参数是否在原字符的尾部
s.includes('o') // true 是否找到了参数字符串
repeat表示将原字符串重复n次,padStart()用于头部补全,padEnd()用于尾部补全。
'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""
'x'.padStart(5, 'ab') // 'ababx'
'x'.padEnd(4,'ab') // 'xaba'
最大的优点,ES6引入了模板字符串,${}可以引入js变量和调用函数。用反引号应用,且可以嵌套模板
var obj = {x: 1, y: 2};
`${obj.x + obj.y}` //3
模板编译:该模板使用<%…%>放置JavaScript代码,使用<%= … %>输出JavaScript表达式。
var template = `
<ul>
<% for(var i=0; i < data.supplies.length; i++) { %>
<li><%= data.supplies[i] %></li>
<% } %>
</ul>
`;
4. 函数的扩展
ES6允许给函数参数添加默认值。同时需要注意的是参数变量是默认申明的,不需要重复声明。
function log(x,y = 2) {
console.log(x+y);
}
log(2,3); //5
//可以与解构赋值一起使用。
function m2({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
同时可以通过函数的length属性,即将返回没有指定默认值的参数个数
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
关于箭头函数
需要注意的点:1.当箭头函数不需要参数或需要多个参数,就用一个圆括号代表参数部分;2.当代码块的语句大于一句时,则需要用大括号将它们括起来,并且使用return语句返回。3:箭头函数返回一个对象时,必须要使用
//基本语法:
var f = () => 5;
let getTempItem = id => ({ id: id, name: "Temp" });//返回对象必须加括号
同时其他注意点为:
1. 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象
2. 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
3. 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
4. 不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
{
function Timer() {
this.s1 = 0;
this.s2 = 0;
// 箭头函数
setInterval(() => this.s1++, 1000);//箭头函数绑定this,指向定义时所在的对象
// 普通函数
setInterval(function () {
this.s2++; // this指向window
}, 1000);
}
var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 3100); // 3
setTimeout(() => console.log('s2: ', timer.s2), 3100); //0
}
箭头函数可以绑定this对象,大大地减少了显式绑定this对象的写法。同时可以使用双冒号来绑定对象
5. 数组的扩展
1.扩展运算符
var arr1 = [1,2];
var arr2 = [3,4];
var arr = [...arr1,...arr2];
console.log(arr);//[1,2,3,4]
与解构赋值结合
const [first, ...rest] = [1, 2, 3, 4, 5];
first //1
rest //[2,3,4,5]
函数的返回值
var dateFields = readDateFields(database);
var d = new Date(...dateFields);
实现了Iterator接口的对象
var nodeList = document.querySelectorAll('div');
var array = [...nodeList];
Map 和 Set 结构,Generator 函数
let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
let arr = [...map.keys()]; // [1, 2, 3]
let value = [...map.values()] //'one','two','three'
2.Array.from()
Array.from方法用于将两类对象转为真正的数组,同时只要部署了Iterator接口的数据结构,都可以转换为数组。
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
Array.from()的另一个应用是,将字符串转为数组,然后返回字符串的长度
Array.of()用于将一组值转换为数组。
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
数组实例的find()和findIndex(),前者是用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。后者是找出位置,若未找到,则返回-1;
[1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
}) // 10
[1, 5, 10, 15].findIndex(function(value, index, arr) {
return value > 9;
}) // 2
fill()为填充数组,entries(),keys()和values()——用于遍历数组
for (let index of ['a', 'b'].keys()) {
console.log(index);
}
// 0
// 1
Array.prototype.includes()方法返回一个布尔值,表示某个数组是否包含给定的值,
[1, 2, 3].includes(2) // true
[1, 2, 3].includes(4) // false
[1, 2, NaN].includes(NaN) // true
6.对象的扩展
ES6允许在对象之中,直接写变量。
function f(x, y) {
return {x, y};
}
// 等同于
function f(x, y) {
return {x: x, y: y};
}
f(1, 2) // Object {x: 1, y: 2}
Object.js用来判断两个值是否严格相等,Object.assign()用来判断两个对象是否严格相等。Object.assign是进行值的浅拷贝而不是深拷贝。对象拷贝得到的是这个对象的引用。
Object.is('foo', 'foo')
// true
Object.is({}, {});
Object.assign(var target = { a: 1 };
var source1 = { b: 2 };
var source2 = { c: 3 };
Object.assign(target, source1, source2);)//将source中的对象合并到target中。