1. 在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”。
如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。凡是在声明之前就使用这些变量,就会报错。
2. Array构造器的常用方法
//2.1 map(统一加权)
let arr = [1,2,3,4];
let a = arr.map((item,index,arr)=>{
return item*2;
})
//输出结果:a=[2,4,6,8]
//2.2 filter(筛选)
let arr =[1,2,3,4];
let a = arr.filter((item,index,arr)=>{
return item>2;
});
//结果:a=[3,4]
//2.3 sort(排序)
let arr = [3,4,2,1];
let a = arr.sort((a,b)=>{
return a-b;
})
// 结果:a = [1,2,3,4]
//2.4 push(入栈)
let arr = [1,2,3,4];
let a = arr.push(5);
//结果:a=[1,2,3,4,5]
//2.5 pop(出栈)
let arr = [1,2,3,4];
let a = arr.pop();
//结果:a=[1,2,3]
//2.6 every(全部数据检测)
let arr = [1,2,3,4];
let a = arr.every((item)=>{
return item>1;
})
//输出结果:a=False;
2.1 ES6新方法
2.1.1 of方法
传统构造器new Array()
创建Array时,参数没有明确定义类型,容易混乱,new Array(3)
会生成一个长度为3的空数组。而使用of,输入的参数只能是内容,Array(3)
的输出结果是[3]
。
2.1.2 from方法
通常使用querySelectorAll
返回的页面元素是NodeList
类数组,转换成数组需要另外处理。而使用from方法,返回的是数组类型。
let items = Array.from(document.querySelectorAll("li"))
//items反馈数组类型为Array
2.1.3 find方法
ES6之前,数组的indexOf
lastIndexOf
是不支持条件检索的,而新的find方法可以支持。
let user =[{index:0},{index:3}];
user.find((item,index)=>item.index>2)
//结果:{index:3}
3. Promise构造器:它的作用是指定某个任务完成后,可以根据这个任务执行的不同结果,去执行不同的下一个任务。
简单的说就是一个容器,里面保存着某个异步操作的结果。Promise可以根据三种状态去执行不同的回调函数:
- pending:初始状态,还未完成时触发。
- fullfilled:完成后触发。
- rejected:失败后触发。
function newAsync(){
return new Promise((resolve,reject)=>{
setTimeout(reject,700);
setTimeout(resolve,500);
}
)
newAsync().then(()=>{
console.log("resolve");
}).catch(()={
console.log("reject");
})
4.Event Loop 是一个异步处理结构,用于查询、等待和发送消息和事件。
JS主线程在遇到异步任务时,会调用异步API触发异步进程,主线程栈执行完毕,为空后,会主动向异步任务队列接任务,异步任务完毕,会插入任务队列,重复这个动作,这个过程就是Event Loop事件循环。
Event Loop异步任务分为宏任务和微任务。宏任务(MacroTask):一般是用户发起的任务,如 setTimeout
,setInterval
,script(主代码块) ,setImmediate
,I/O和 UI rendering。微任务(MicroTask):一般是操作系统引擎发起的任务,如new MutationObserver
, new Promise()
,process.nextTick(Nodejs)
和Object.observe
。
Event Loop执行优先级:同步任务>微任务>宏任务。
console.log(1);
//同步任务
setTimeout(function(){
console.log(2);
//宏任务
},0);
new Promise((resolve,reject)=>{
console.log(3);
//同步任务
resolve();
console.log(4);
//同步任务
}).then(()={
console.log(5);
//微任务
})
console.log(6);
//同步任务
//输出结果依次是:1 3 4 6 5 2
5.迭代器
早期的数据遍历不同的数据类型处理方式不同,后期发展的迭代器优化了数据遍历的问题:
let str = "hello";
let iterator = str[Symbol,iterator]();
console.log(iterator.next());//{value:'h',done:false}
console.log(iterator.next());//{value:'e',done:false}
console.log(iterator.next());//{value:'l',done:false}
console.log(iterator.next());//{value:'l',done:false}
console.log(iterator.next());//{value:'o',done:false}
console.log(iterator.next());//{value:'undefined',done:true}
注:迭代器只能往前取值,不会后退;用iter函数可以返回一个可迭代对象的迭代器。
6.生成器
列表所有数据都在内存中,数据太多会非常占据内存。但如果列表元素按照某种逻辑推算出来,那就可以在循环中不断推算出后续元素,就不用创建完整的列表,从而节省空间。
function* generator(){
//使生成器函数执行暂停,yield的值返回给生成器的调用者
yield 1;
yield 2;
yield 3;
}
let gen = generator();
console.log(gen.next());//{value:1,done:false}
console.log(gen.next());//{value:2,done:false}
console.log(gen.next());//{value:3,done:false}
console.log(gen.next());//{value:undefined,done:true}
7.类
类作为对象的模版,只是一个语法糖。class关键字只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
声明类具有以下两种方式:
//第一种:声明类
class Person{
constructor(age,sex){
this.age = age;
this.sex = sex;
}
speak(){
return `${this.age},${this.sex}`
}
}
//创建Person类的实例对象
let Jack = new Person(12,"男");
console.log(Jack.speak());
//第二种
const MyClass = class [className][extends]{
}
7.静态方法
static关键字为类定义了一个静态方法。静态方法不会在类的实例上被调用,相反会被类本身调用。
class ClassWithStaticMethod{
static staticMethod(){
return "has called" ;
}
}
console.log(ClassWithStaticMethod.staticMethod());
8.继承
原型式继承,就是在一个函数中创建一个临时性的构造函数,将参数传入的对象作为这个构造函数的原型,最后返回这个构造函数的实例对象。
let person = {
name:"Jack".
friends:["Marry"]
};
let newPerson = new Object(person);
newPerson.friends.push("Tom");
console.log(newPerson.friends);//Marry,Tom
构造函数继承,在子对象的构造函数中调用父对象的构造函数,通过调用apply()
和call()
方法实现。
function SuperType(){
this.name = "Jack";
}
function SubType(){
SuperType.call(this);
//或SuperType.apply(this,arguments);
}
var instance = new SubType();
console.log(instance.name);//Jack