我们通常用 `let`和 `const`来声明, `let`表示变量、`const` 表示常量。 `let` 和 `const`都是块级作用域。块级作用域可以理解为在{}大括号内的代码块。
let 定义的变量不会被变量提升;let的作用域是在它所在当前代码块,不会被提升到当前函数的最顶部。
function ha() {
if(flag) {
let test = 'hello Doraemon~';
} else {
//test is not defined
console.log(test)
}
}
再来说说const ,
const 定义的常量不能被修改,const定义的对象所指向的地址不能改变,对象的属性值可以改变(改变指针指向就会报错。因为对象是引用类型的,P中保存的仅是对象的指针,这就意味着,const仅保证指针不发生改变,修改对象的属性不会改变对象的指针,所以是被允许的。也就是说const定义的引用类型只要指针不发生改变,其他的不论如何改变都是允许的。)
TDZ(暂时性死区)
我们都知道,JS引擎扫描代码时,如果发现变量声明,用 var 声明变量时会将声明提升到函数或全局作用域的顶部。但是使用 `let` 或者 `const`,会将声明关进一个小黑屋也是TDZ(暂时性死区),只有执行到变量声明这句语句时,变量才会从小黑屋被放出来,才能安全使用这个变量。
console.log(a); // undefined
var a = 'hello';
// 上面的代码相当于
var a;
console.log(a);
a = 'hello';
//而 let 就不会被变量提升
console.log(a); // a is not defined
let a = 'hello';
模板字符串解决了 ES5 在字符串功能上的痛点。
第一个用途:字符串拼接。将表达式嵌入字符串中进行拼接,用 反引号 ` 和
${}` 来界定。
//ES5
var name = 'King'
console.log('hello' + name)
//es6
const name = 'King'
console.log(`hello ${name}`) //hello King
第二个用途,在ES5时我们通过反斜杠(\)来做多行字符串或者字符串一行行拼接。ES6反引号(``)直接搞定。
// es5
var msg = "Hi \
man!";
// es6
const name = 'Lys', age = 23;
const template = `
${name}
${age}
`;
箭头函数最直观的三个特点。()=>{}
function
关键字来创建函数return
关键字this
关键字,箭头函数没有自己的this,它的this是继承而来,默认指向在定义它时所处的对象,而不是执行时的对象。// ES5
var arr1 = [1, 2, 3];
var newArr1 = arr1.map(function(x) {
return x + 1;
});
// ES6
let arr2 = [1, 2, 3];
let newArr2 = arr2.map((x) => {
x + 1
});
箭头函数小细节:当你的函数有且仅有一个参数的时候,是可以省略掉括号的;当你函数中有且仅有一个表达式的时候可以省略{}
let arr2 = [1, 2, 3];
let newArr2 = arr2.map(x => x + 1);
JavaScript语言的this对象一直是一个令人头痛的问题,运行上面的代码会报错,这是因为setTimeout中的this指向的是全局对象。
class Animal {
constructor() {
this.type = 'animal';
}
says(say) {
setTimeout(function() {
console.log(this.type + ' says ' + say);
}, 1000);
}
}
var animal = new Animal();
animal.says('hi'); //undefined says hi
解决办法:
// 传统方法1: 将this传给self,再用self来指代this
says(say) {
var self = this;
setTimeout(function() {
console.log(self.type + ' says ' + say);
}, 1000);
}
// 传统方法2: 用bind(this),即
says(say) {
setTimeout(function() {
console.log(this.type + ' says ' + say);
}.bind(this), 1000);
}
// ES6: 箭头函数
// 当我们使用箭头函数时,函数体内的this对象,就是定义时所在的对象
says(say) {
setTimeout(() => {
console.log(this.type + ' says ' + say);
}, 1000);
}
注:箭头函数不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
解构可以简化数组和对象中信息的提取。在ES6之前,我们需要一个一个获取对象信息;ES6后,解构能让我们从对象或者数组里取出数据存为变量,具体来看下面的代码:
// ES5
var people1 = {
name: 'bai',
age: 20,
color: ['red', 'blue']
};
var myName = people1.name;
var myAge = people1.age;
var myColor = people1.color[0];
console.log(myName + '----' + myAge + '----' + myColor);
// ES6
let people2 = {
name: 'ming',
age: 20,
color: ['red', 'blue']
}
let { name, age } = people2;
let [first, second] = people2.color;
console.log(`${name}----${age}----${first}`);//ming----20----red
rest arguments (rest参数)解决了 es5 复杂的 arguments
问题
function foo(x, y, ...rest) {
return ((x + y) * rest.length);
}
foo(1, 2, 'hello', true, 7); // 9
第一个用途:组装数组
let color = ['red', 'yellow'];
let colorful = [...color, 'green', 'blue'];
console.log(colorful); // ["red", "yellow", "green", "blue"]
第二个用途:获取数组除了某几项的其他项
let num = [1, 3, 5, 7, 9];
let [first, second, ...rest] = num;
console.log(rest); // [5, 7, 9]
promise:就是一个对象,用来传递异步操作的消息;可以将异步操作以同步操作的流程表达出来;
缺点:无法取消promise,一旦新建它,就会立即执行;
promise对象有两个特点:
1:对象的状态不受外界影响;有三种状态:Pending(进行中),Resolved(以完成),Rejected(已失败)。
只有异步操作的结果可以决定当前的状态;
2:一旦状态改变,就不会再变;Promise对象的状态改变只有两种可能,从pending->resolved或者从pending->rejected;
就算改变已经发生了,你再对promise对象添加回调函数,也会立即得到这个结果;
基本用法:
promise对象是一个构造函数,接受一个函数作为参数;该函数的两个参数分别是resolve和reject。它们是两个函数,由JavaScript引擎提供;
resolve函数作用是:将promise对象的状态从“未完成”变为“成功”;在异步操作成功时调用,并将异步操作的结果作为参数传递出去;
reject函数作用是:将promise对象的状态从“未完成”变为“失败”;在异步操作失败时调用,并将异步操作报出的错误作为参数传递出去;
promise实例生成后,可以用then方法接收两个回调函数作为参数,第一个是对象状态变为resolved时调用,第二个是状态变为rejected时调用,不一定提供;
Promise.prototype.then():
then()方法返回的是一个新的promise实例,因此可以采用链式写法;
如果依次指定了两个回调函数,第一个回调函数完成之后,就会返回结果作为参数传入第二个回调函数;
Promise.prototype.catch():
catch()方法返回的是一个promise()对象,因此可以采用链式写法;
catch是then(null,rejection)的别名,用于指定发生错误时的回调函数;
promise对象的错误具有“冒泡”的性质,会一直向后传递,直到被捕获为止;
Promise.all():
用于将多个promise实例包装成一个新的promise实例;
接收一个数组作为参数;如果数组中存在不是promise实例的,会先调用Promise.resolve方法,将参数转化为promise实例;
var p = Promise.all([p1,p2,p3]);
p的状态是由p1,p2,p3决定
1:只有p1,p2,p3状态都变为resolved时,p才会是resolved;
2:只要p1,p2,p3有一个状态变为rejected,p就会是rejected;
Promise.race():
用于将多个promise实例包装成一个新的promise实例;
只要有一个实例率先改变状态,p的状态就跟着改变,那个率先改变promise实例的返回值就传递给p的回调函数;
Promise.resolve():
将现有对象转化为promise对象,返回promise实例的状态从一开始就是resolved,所以回调函数会立即执行;
Promise.reject():
该方法也会返回一个新的promise实例,状态为rejected;
var getJSON = function(url){
var promise = new Promise(function(resolve,reject){
var XHR = new XMLHttpRequest();
XHR.open("get",url);
XHR.onreadystatechange = handler;
XHR.responseType = "json";
XHR.setRequestHeader("Accept","application/json");
XHR.send();
function handler(){
if(this.readyState !==4){
return ;
}
if(this.status === 200){
resolve(this.response);
}else{
reject(new Error(this.statusText));
}
}
});
return promise;
}
promise.then(function(value){
//code
},function(value){
//code
});
promise.catch(function(error){
//code
});