let
1.let不允许重复声明
let a = 10; let a = 20; console.log(a);
会报错,变量a已经被声明,Uncaught SyntaxError: Identifier 'a' has already been declared
2.let没有声明提前
console.log(a); //ReferenceError let a = 10;
let这样声明会报错
如果用var声明,不会报错
console.log(a); //undefined var a = 10;
3.不会挂载到window上
var a = 1; window.a; //1 let b = 1; window.b; //undefined
4.let声明的变量,存在块及作用域
块级作用域由花括号包括,if语句和for循环里面的{ }也属于块作用域。
{ let a=1; var b=2; } console.log(a); //undefined console.log(b); //2
5.let会产生临时死区
只要块及作用域里有let,
let a =10; function fn1(){ console.log(a); let a = 5; } fn1();//Uncaught ReferenceError: a is not defined
临时死区就是如上代码,a已经声明了,在没有到它赋值的时候,不能使用这个变量,不然会报错。
作用域开始,一直到let a = 5
为止这整一块,都是a
变量的临死性死区,不能使用它
const
const用来声明常量,一旦声明,其值就不能更改,const一旦声明常量,就必须同时初始化。
1.const与let一样,在同一个作用域,const不能重复声明同一常量
2.const 也不能声明提前
3.const也不会挂载到Window上
spreed&rest 收集与展开
运算符spreed
var arr1 = [1, 2, 3,4];
var arr2 = [...arr1, 4, 5, 6];
console.log(arr2);
//(7) [1, 2, 3, 4, 4, 5, 6]
var arr1 = [1,2,3];
var arr2 = [2,3,4];
var arr3 = [5,6,7];
arr1.concat(arr2, arr3);
console.log(arr1.concat(arr2, arr3))
//(9) [1, 2, 3, 2, 3, 4, 5, 6, 7]
var str='bailiban';
var arr3= [...str];
console.log(arr3);
//(8) ["b", "a", "i", "l", "i", "b", "a", "n"]
let obj1 = {
name : "jack",
age : 18,
play : "wan"
}
let obj2 = {
name : "mack",
age : 20
}
console.log(Object.assign({},obj1,obj2))
{name: "mack", age: 20, play: "wan"}
深克隆
var a = [1,2,3];
var b = a;
b.push(4);
console.log(b);
console.log(a);
输出a和b都是1234 这是一个深克隆
浅克隆
var a=[1,2,3];
var b = [...a,4]
console.log(b);//1,2,3,4
console.log(a);//1,2,3
解构化赋值
作用:简化书写长度,提升开发效率
解构数组
var foo = ["one", "two", "three"];
var [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"
var a, b;
[a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2
var [a, ...b] = [1, 2, 3];
console.log(a); // 1
console.log(b); // [2, 3]
...b后面不能加逗号,剩余元素必须是数组的最后一个元素。
解构对象
var {a = 10, b = 5} = {a: 3};
console.log(a); // 3
console.log(b); // 5
当要提取的对象没有对应的属性,变量就被赋予默认值。
箭头函数
作用:函数目的指向性更强,可读性更好,简化代码,提升开发效率
特点:
1.不用写function关键字
2.只能作为函数使用 不能new,没有原型
3.参数不能重复命名
4.返回值可以不写return,
5.内部arguments this 由定义是外围最接近一层的非箭头函数的arguments和this决定其值
function sum(a,b){
return a+b;
};
var sum = function(a,b){
return a+b;
}
在不考虑预编译的情况下,两个的用法是一样的
可以这样简化
let sum = (a,b) => {
return a+b;
}
也可以这样简化
平常写的函数
function sum(x){
return function(y){
return function (z)
return x+y+z;
}
}
}
演变过程
let sum = (x) => {
return (y) => {
return (z) => {
return x+y+z
}
}
}
可以这样简写
var sum1 = sum(1);
var sum2 = sum1(2);
console.log( sum2(3) );
也可以这样简写
let sum = x => y => z => x+y+z;
console.log(sum(1)(2)(3));
箭头函数只能作为函数使用不能new,没有原型,不然会报错
let sum = () => {
this.a = 10;
}
new sum();
this 由定义是外围最接近一层的非箭头函数的this决定其值
let obj = {
abc : "hello",
fun (){
let sum = () => {
console.log(obj.abc);
}
return sum;
}
}
obj.fun()() //hello
map对象
map对象主要是储存内容用的
set() 方法是给Map对象添加一个新元素。返回Map对象.
get() 方法用来获取一个 Map 对象中指定的元素
创建map对象
var map = new Map();
添加值
map.set('name','jack');
map.set('age',23);
取值
map.get(name);
循环
var map = new Map();
map.set("0","zero");
map.set("1","one");
for(var index of map){
console.log(index);
}
输出
(2) ["0", "zero"]
(2) ["1", "one"]
for(var name of map.entries()){
console.log(name)
}
输出
0,zero
1,one
for (var [key,value] of map.entries()){
console.log(key,value)
}
输出
0 zero
1 one
for (var val of map.values()){
console.log(val)
}
输出
zero one
class类和继承
// 父类 class Person { constructor(name){ this.name=name; } showName(){ return`名字是:${this.name}`; } } // 子类 class children extends Person{ constructor(name,skill){ super(name); this.skill = skill; } showName (){ super.showName()//调用父级的方法也是用super,写继承,必须加上的
}
showSkill(){
return`技能为:${this.slill}`; } } let stu1 = new children('jack','游泳') console.log(stu1.showName())
class用extends实现继承,子类继承父类,必须在constructor函数的第一行调用super ( )
promise对象
resolve
函数;reject
函数。new Promise(function(resolve,reject){
if(成功){
resolve(成功的数据)
}else{
reject(失败的原因)
}
})
then方法
then是promise实例状态发生改变的·回调函数,会返回一个新的Promise实例,所以后面可以再另一个then()方法进行链式调用。
let p1 = new Promise(function(resolve, reject){
//当异步代码执行成功时,会调用resolve(...), 当异步代码失败时就会调用reject(...)
setTimeout(function(){
resolve("成功了!"); //代码正常执行!
}, 250);
});
p1.then(function(successMessage){
//successMessage的值是上面调用resolve(...)方法传入的值.
console.log("太好了! " + successMessage);
});
catch方法返回一个promise,用于错误的处理
如果抛出一个错误,就要通过catch( )方法来处理
var p1 = new Promise(function(resolve,reject){
resolve('成功了')
})
p1.then(function(abc){
console.log(abc);
throw '出错了哦';
}).catch(function(err){
console.log(err);
})
all( )方法
var p1 = Promise.resolve('a');
var p2 = Promise.resolve('b');
var p3 = Promise.resolve('c');
上面都是成功,所以输出的是a,b,c
var p1 = Promise.resolve(1),
var p2 = Promise.reject(2),
var p3 = Promise.resolve(3);
Promise.all([p1, p2, p3]).then(function (results) {
//then方法不会被执行
console.log(results);
}).catch(function (e){
//catch方法将会被执行,输出结果为:2
console.log(2);
});
上面P2失败了,状态就为reject
race( ) 一旦参数内有一个值的状态发生的改变,那么该Promise的状态就是改变的状态
var p1 = new Promise(function (resolve,reject){ setTimeout(resolve,300,'one'); }) var p2 = new Promise(function (resolve,reject){ setTimeout(resolve,100,'two'); }) Promise.race([p1,p2]).then(function(data){ console.log(data);//“two” })两个都完成,但 p2 更快
var p3 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, "three");
});
var p4 = new Promise(function(resolve, reject) {
setTimeout(reject, 300, "four");
});
Promise.race([p3, p4]).then(function(value) {
console.log(value); // "three"
// p3 更快,所以它完成了
}, function(reason) {
// 未被调用
});
var p5 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, "five");
});
var p6 = new Promise(function(resolve, reject) {
setTimeout(reject, 100, "six");
});
Promise.race([p5, p6]).then(function(value) {
// 未被调用
}, function(reason) {
console.log(reason); // "six"
// p6 更快,所以它失败了
});