一、javaScript组成:
包括:ECMAScript,DOM,BOM
1.ECMAScript:javascript核心语法,不依赖平台
如:定义变量,if,switch,for,数组Api,字符串API,正则Api…
2.DOM:(Document Object Model)针对浏览器标签操作 例如:获取id,获取类名,获取标签名
注:操作真实DOM,引起重绘和回流–>才引出虚拟DOM
重绘:主要指页面颜色的改变,不影响DOM的空间变化 color,background
回流:指页面元素的尺寸(width,padding,height,margin),位置的变化:left,top,bottom,right等
tranform:translateX(300px)
重绘未必引起回流,但回流一定引起重绘
3.BOM:(Browser Object Model)主要针对浏览器相关API的操作
history: history.go(),history.back() pusState,popState,replaceState
navigator:跟浏览器系统信息相关
navigator.userAgent
参考:https://developer.mozilla.org/zh-CN/docs/Web/API/Navigator
location:主要获取浏览器地址栏相关的信息
location.search
location.href
location.hash
参考:https://developer.mozilla.org/zh-CN/docs/Web/API/Location
二、ECMA6/7/8…新增特性
ES6 ES2015 … ES11 ES2020
了解ES6/7/8/9/最新进展:https://github.com/tc39/proposals/blob/master/finished-proposals.md
let和const: 重点
let 定义变量
const 定义常量
1.你说一下let和var的区别
相同点:都是定义变量
区别:
1.是否有变量提升 var有变量提升,let没有
2.是否能重复定义 var允许重复定义变量,let不允许重复定义
3.是否有块级作用域 { }
全局作用域:在函数外部定义的范围
局部作用域:在函数内部定义的范围
块级作用域:在{ }大括号中定义范围
2.你说一下let和const的区别
let 定义变量
const 定义常量,是不能修改的,如果要修改,将常量定义成对象的形式,这样,就可以给对象中的属性进行修改
symbol:是ES6新增的基本数据类型
number,string,boolean,null,undefined,symbol(ES6新增)
symbol:定义的值是唯一性
两个symbol类型的值永远不等
例如:
var s1=Symbol()
var s2=Symbol()
s1=== s2
false
扩展运算符( ... )
扩展运算符(也称展开操作符)两层作用:
1.将数组转换成数据列表 [a,b,c,d]--->a,b,c,d
例如:
var arr1=[666,777,888]
var arr2=['hello','vuejs']
var result=[...arr1,...arr2]
2.将数据列表转换成数组 a,b,c,d--->[a,b,c,d]
3.展开对象
var result={...obj1,...obj2}
或
result=Object.assign({},obj1,obj2)
例如:
function sum1(str,...args) {
var result=0;
for(var i=0;i<args.length;i++) {
result+=args[i]
}
return result;
}
sum1('请输入',20,30,40)
class类
定义一个类:
class Person {
constructor(a,b) {
//构造器
this.属性=a
}
方法1() {}
方法2() {}
方法3() {}
}
继承一个类:
class Child extends Person {
constructor(a,b) {
super() //代表父类
//构造器
this.属性=a
}
方法1() {}
方法2() {}
方法3() {}
}
set和map:
set:理解成是一个不重复的数组
将set类型的数据转换成数组:
var s=new Set()
Array.from(s)
或[...s]
var s=new Set()
s.add()
s.has()
s.delete()
s.size
例如:数组去重:
var arr=[3,34,23,2,2,23,23,3,34,34,34,45]
[...new Set(arr)]
map:理解成是一个对象,增强了对象key的数据类型,以前只能是字符串,现在对象的属性可以是做任意的数据类型!
{
"name":'jack',
'10':'abc',
'undefined':999
}
var m1=new Map()
m1.set(属性名,值) //设置
m1.get(属性名) //获取
m1.delete(属性名) //删除
//遍历Map类型获取所有值
for(var [key,value] of m1) {
console.log(key)
console.log(value)
}
Promise:重点
1.用于处理回调地狱的异步解决方案
具体实现:
function waiting() {
return new Promise((resolve,reject)=>{
setTimeout(function() {
//console.log(2)
reject('哈哈')
},2000)
})
}
waiting().then(res=>{
console.log(1)
console.log('res:',res)
console.log(3)
}).catch(error=>{
console.log('error:',error)
})
.then
.catch
.race
.finally
Promise.all([waiting(),waiting2(),waiting3()])
.then(res=>{
}).catch(res=>{
})
async/await(ES2017) 重点
串行执行:必须先执行第一个异步,将第一个异步的结果返回传递给第二个异步函数,再执行第二个异步的操作过程
//第一个函数
function waiting() {
return new Promise((resolve,reject)=>{
//我这里只是用setTimeout来模拟axios,
setTimeout(function() {
resolve('第二个接口返回')
},2000)
})
}
//第二个函数
function waiting2() {
return new Promise((resolve,reject)=>{
//我这里只是用setTimeout来模拟axios,
setTimeout(function() {
reject('第二接口返回')
},2000)
})
}
async function handleFn() {
console.log(1)
//串行执行,先等待第一个函数返回
let res=await waiting()
console.log('res:',res)
//再等待第二个函数返回
let res2=await waiting2(res)
console.log(res2)
}
并行:两个接口同时执行
function waiting() {
return new Promise((resolve,reject)=>{
//我这里只是用setTimeout来模拟axios,
setTimeout(function() {
resolve('第二个接口返回')
},2000)
})
}
function waiting2() {
return new Promise((resolve,reject)=>{
//我这里只是用setTimeout来模拟axios,
setTimeout(function() {
reject('第二接口返回')
},2000)
})
}
async function handleFn() {
console.log(1)
//并发执行,waiting(),waiting2()两个接口都成功返回才返回结果
let res=await Promise.all([waiting(),waiting2()])
console.log('res:',res)
console.log('end')
}
handleFn().catch(res=>{
console.log('error:',res)
})
解构赋值
ES6变量的解构赋值本质上是“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予匹配的右边的值,如果匹配不成功变量的值就等于undefined
箭头函数 重点
箭头函数特点一:没有自己的this对象,其this对象为所在环境
特点二 :没有arguments参数 可以用...rest代替
特点三:不能使用构造函数,不可使用new命令,否则会报错
module(export,import)
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代现有的 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
// ES6模块
import { stat, exists, readFile } from 'fs';
上面代码的实质是从fs模块加载3个方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高。当然,这也导致了没法引用 ES6 模块本身,因为它不是对象。由于 ES6 模块是编译时加载,使得静态分析成为可能。有了它,就能进一步拓宽 JavaScript 的语法,比如引入宏(macro)和类型检验(type system)这些只能靠静态分析实现的功能。除了静态加载带来的各种好处,ES6 模块还有以下好处:
(1)不再需要UMD模块格式了,将来服务器和浏览器都会支持 ES6 模块格式。目前,通过各种工具库,其实已经做到了这一点
(2)将来浏览器的新 API 就能用模块格式提供,不再必要做成全局变量或者navigator对象的属性
(3)不再需要对象作为命名空间(比如Math对象),未来这些功能可以通过模块提供
generator
generator(生成器)是ES6标准引入的新的数据类型。一个generator看上去像一个函数,但可以返回多次。
ES6定义generator标准的哥们借鉴了Python的generator的概念和语法,如果你对Python的generator很熟悉,那么ES6的generator就是小菜一碟了。如果你对Python还不熟,赶快恶补Python教程!。
我们先复习函数的概念。一个函数是一段完整的代码,调用一个函数就是传入参数,然后返回结果:
function foo(x) {
return x + x;
}
var r = foo(1); // 调用foo函数
函数在执行过程中,如果没有遇到return语句(函数末尾如果没有return,就是隐含的return undefined;),控制权无法交回被调用的代码。
generator跟函数很像,定义如下:
function* foo(x) {
yield x + 1;
yield x + 2;
return x + 3;
}
generator和函数不同的是,generator由function*定义(注意多出的*号),并且,除了return语句,还可以用yield返回多次。
大多数同学立刻就晕了,generator就是能够返回多次的“函数”?返回多次有啥用?
还是举个栗子吧。
我们以一个著名的斐波那契数列为例,它由0,1开头:
0 1 1 2 3 5 8 13 21 34 ...
要编写一个产生斐波那契数列的函数,可以这么写:
function fib(max) {
var
t,
a = 0,
b = 1,
arr = [0, 1];
while (arr.length < max) {
[a, b] = [b, a + b];
arr.push(b);
}
return arr;
}
// 测试:
fib(5); // [0, 1, 1, 2, 3]
fib(10); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
函数只能返回一次,所以必须返回一个Array。但是,如果换成generator,就可以一次返回一个数,不断返回多次。用generator改写如下:
function* fib(max) {
var
t,
a = 0,
b = 1,
n = 0;
while (n < max) {
yield a;
[a, b] = [b, a + b];
n ++;
}
return;
}
直接调用试试:
fib(5); // fib {[[GeneratorStatus]]: "suspended", [[GeneratorReceiver]]: Window}
直接调用一个generator和调用函数不一样,fib(5)仅仅是创建了一个generator对象,还没有去执行它。
调用generator对象有两个方法,一是不断地调用generator对象的next()方法:
var f = fib(5);
f.next(); // {value: 0, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 2, done: false}
f.next(); // {value: 3, done: false}
f.next(); // {value: undefined, done: true}
next()方法会执行generator的代码,然后,每次遇到yield x;就返回一个对象{value: x, done: true/false},然后“暂停”。返回的value就是yield的返回值,done表示这个generator是否已经执行结束了。如果done为true,则value就是return的返回值。
当执行到done为true时,这个generator对象就已经全部执行完毕,不要再继续调用next()了。
第二个方法是直接用for ... of循环迭代generator对象,这种方式不需要我们自己判断done:
'use strict'
function* fib(max) {
var
t,
a = 0,
b = 1,
n = 0;
while (n < max) {
yield a;
[a, b] = [b, a + b];
n ++;
}
return;
}
模板字符串
,用`(反引号)标识,用${}将变量括起来。上面的例子可以用模版字符串写成下面这样:
$("#result").append(
`He is <b>${person.name}</b>and we wish to know his${person.age}.that is all`
);
这样的做法就简洁了很多,我们不需要再使用大量的""和+来拼接字符串和变量。
for of
......
ES2015+如果正常跑在浏览器上,都要通过babel去编译转换成ES5才能正常在浏览器运行