文章目录
1 ES6标准入门
什么是ES6?
- ECMAScript6(简称ES6),又称 ECMAScript2015(ES2015)
- 2015年6月正式发布,是 JavaScript语言的下一代标准
为什么要学ES6?
-
更严谨的语法,更高效的编码
-
更新的特性,更多的功能
-
新特性举例:箭头函数的使用场景—数组遍历
-
使用标准前:
-
let arr1 = [1,2,3] arr1.map(function (x)){ return x*x; }
-
使用标准后:
-
let arr2 = [1,2,3] arr2.map(x => x*x)
-
-
主流前端框架(Vue/React/Angular等)、大厂都在用ES6+
-
兼容性解决方案成熟(Babel)
2 开发环境搭建
node.js:Node.js
vscode:Visual Studio Code - Code Editing. Redefined
3 ES6与 JavaScript的关系
JavaScript发展史:
-
2011年6月,ECMAscript5.1版发布,并且成为SO国际标准(SO/EC162622011)
-
截至2012年,所有浏览器都完整的支持 ECMAScript5.1旧版本的浏览器至少支持 ECMAScript3标准
-
2015年6月17日,ECMAScript6发布正式版本,即ECMAScript 2015
-
ECMAScript
- JavaScript
- JScript
- ActionScript
常用的ES6新特性:
- 精简的箭头函数
let sum = (a,b) => a+b
- 严格的变量声明
- let age = 20 // 变量
- const COURSE = “python” //常量
- 更方便的解构赋值
- let [a,…b] = [1,2,3,4]
- Promise容器实现异步编程
new Promise((resolve,reject)=>{})
4 ES6 变量与常量
4.1 变量
声明变量:
var a = 100
let b = 'hello'
let的三大特性:
- 特征一:不存在变量提升,必须要先声明,再使用
console.log(a); // 报错ReferenceError
let a = 2;
- 特征二:不能重复声明
let b = 100;
let b = 'hello' // 报错 SyntaxError
- 特征三:块级作用域,变量只在代码块内有效
function func(){
let n = 5;
if(true){
let n = 10;
}
console.log(n); // n=5
}
4.2 常量
-
什么是常量?
一旦声明,常量的值就不能改变
声明常量:
const PAGE_SIZE = 100;
const PI = 3.1415926;
const的三大特征:
-
特征一:声明必须赋值(必须初始化)
const NAME; // 报错 SyntaxError NAME = 100;
-
特征二:常量是只读的,不能重新赋值
const PI =3.1415926; PI = 3.1415926; // 报错TypeError
-
特征三:块级作用域,只在代码块内有效
if(true){ const PI = 3.1415926 } console.log(PI) // 报错ReferenceError
5 ES6 解构赋值
- 场景一:数组的解构赋值
按顺序将值赋值给对应的变量
let[a,b,c]=[1,2,3];
console.log(a)
console.log(b)
console.log(c)
...
表示解构运算符,将剩余的内容赋值
let[c,...d]=[1,2,3l;
console.log(c)
console.log(d)
解构赋值失败,变量值为 undefined
let[e,f]=[1];
console.log(e)
console.log(f)
防止解构失败,给变量默认值
let[e,f=100]=[1];
console.log(e)
console.log(f)
- 场景二:对象的解构赋值
按顺序将值赋值给对应的变量
let{foo, bar}={foo:'aaa', bar: 'bbb'};
console.log(foo)
console.log(bar)
可以解构对象中的常量、方法
console.log(Math.PI)
let{PI,sin} = Math
console.log(PI)
console.log(sin(PI/2)) // sin(90°)
重新指定变量名称
let{color:sky} = {color:'blue'}
console.log(sky)
复杂对象的解构赋值
let{title,author:{name,age}} = {
title:'新闻标题',
author:{
name:'张三',
age:23
}
}
console.log(name)
console.log(age)
对象解构赋值的应用
$.post(url,data,function({code,objects}){
if(code === 200){
// 请求成功,执行正确的业务逻辑代码
}
})
- 场景三:字符串的解构赋值
字符串可以看做是“伪数组”(注:它不是真的数组)
const [a,b,c,d,e] = 'hello'
console.log(a)
console.log(b)
let{length} = 'hello'
console.log(length)
6 ES6 函数、箭头函数
- 设置默认值
function point(x=0, y=0){
console.log(x)
console.log(y)
}
- 未设置默认值且不传对应参数时,值为 undefined
function point(x, y=0){
console.log(x); // undefined
console.log(y);
}
- 带默认值的参数顺序
温馨提示:请将带默认值的参数放于最后
function point(x=0,y,z){
console.log(x)
console.log(y)
console.log(z)
}
- 注意:参数变量(形参)不可重复声明
function point(x=0, y=0){
let x=0; // 不允许
const y = 1; // 不允许
}
- 当形参为对象时,可使用解构赋值
function fetch(url,{body='', method='GET', headers={}}){
$.ajax({
url,
method
})
}
- 对象中的函数简写
let UserA = {
name:'张三',
age:23,
info:function(){
return this.name+this.age
}
}
箭头函数
- 定义箭头函数
单参数
let f1 = v=>v;
//等同于
let f1 = function(v){
return v;
};
多参数
let f2 = (a,b) => a+b;
//等同于
let f2 = function(a,b){
return a+b;
};
- 函数体包含多条语句,使用{}包含语句块
let f3 = (a,b) => {
console.log(a,b);
return a+b;
}
- 箭头函数的使用场景—数组遍历
let arr1 = [1,2,3]
arr1.map(function(x){
return x*x;
});
// 箭头函数
let arr2 = [1,2,3]
arr2.map(x => x*x);
- 注意:箭头函数体內的this指向定义时所在的对象,而非实例化后的对象(在函数定义时绑定)
let UserC = {
name:'张三',
age:23,
info:() => {
return this.name + this.age
}
}
理解this
指函数执行过程中,自动生成的一个内部对象,是指当前的对象,只在当前函数内部使用
-
运行时跟运行环境绑定
- 浏览器:this=== window
- Node环境:this=== global
-
当函数被作为某个对象的方法调用时,this指向那个对象
再次理解箭头函数中的this(指向定义时所在的对象)
let MyObj = {
a(){
console.log('a',this) // MyObj
setTimeout(()=>{
console.log('timeout',this) // MyObj
},100)
},
b:()=>{
console.log('b',this) // window
}
}
7 JavaScript中的面向对象编程
构造函数
ES6中引入class
关键字实现面向对象编程
clsss Point{
construtor(x,y){ // 构造函数
this.x = x;
this.y = y;
}
toString(){
return '点的位置:('+this.x+","+this.y')';
}
}
- 关于构造函数 constructor
构造函数(constructor)是类的默认方法,通过new命令生成对象实例时,会自动调用该方法。
一个类必须有 constructor方法,如果没有显式定义,一个空的 constructor方法会被默认添加。
- 关于this的指向
类方法中的this指向类的实例
静态方法中的this指向类
静态方法
- 可以直接通过类来调用的方法(无法通过类的实例来调用)
class MyDate{
static validateMonth(month){
month = Number.parseInt(month)
return month>=1 && month<=12
}
}
MyDate.validateMonth(1)
注意:静态方法中的this指的是类,而不是其实例
8 ES6中的继承
ES6中使用 extends关键字实现类的继承
class Animal{
eat(){
return 'Food'
}
}
new Animal().eat()
class Cat extends Animal{
eat(){
return 'Fish'
}
}
new Cat().eat()
- 使用 super关键字调用父类方法
class Cat extends Animal{
eat(){
let rest = super.eat(); //调用父类方法
return rest+'Fish'
}
}
new Cat().eat()
- 类的属性名,可以采用表达式,使用[]来引用
let methodName = 'getArea';
class Square{
['a'+'bc'](){},
[methodName](){
//业务逻辑代码
}
}
9 ES6中的模块化
模块化的好处:
- 增强代码的可维护性
- 增强代码的可阅读性
- 增强代码的可扩展性
Js中的模块化:
-
ES6以前
- 服务器端(NodeJs):CommonJs
- 浏览器端:AMD、CMD
-
模块是对内部逻辑的封装,只对外提供接口
-
一个js文件就是一个模块
-
ES6中使用 export关键字对外暴露接口(导出)
-
ES6中使用 Import关键字导入一个模块
export的使用:
- 方式一:直接导出
export let a=1
export const NAME = 'JavaScript'
export function sayHello(){
console.log('Hey,boy!')
}
- 方式二:批量导出
let a=1 // 变量
const NAME = 'JavaScript' // 常量
// 函数
function sayHello(){
console.log('Hey,boy!')
}
export{a,NAME,sayHello}
通过as关键字指定别名
let a=19
export{a as age}
- 方式三:使用 export default默认导出
// a.js
export default 1
// b.js
let b=2
export default b //可以理解为赋值
// f.js
export default function(){
console.log('from default')
}
- 注意:语句的位置(代码顶层,不能在语句块内)
import的使用
- 方式一:导入需要的部分内容
// 从myFirstModule.js导入需要的函数
import {sayHello} from './myFirstModule.js'
// 执行函数
sayHello()
- 方式二:导入全部内容,使用
as
指定别名
// 从myFirstModule.js导入全部
import * as myModule from './myFirstModule.js'
// 执行函数
myModule.sayHello()
在Node中执行ES6模块
- 设置package.json
{
"type":"module"
}
- 执行命令
node --experimental-modules test.js
第一坑:不能在块级作用域內执行导入导出
if(true){
export let a = 1 // SyntaxError
}
第二坑:不能直接导出变量的值
export 3.1415926 // SyntaxError
第三坑:注意 IMport的顺序
let b = 1
import b from './b.js' //报错
10 ES6编程注意事项
ESIint-—代码静态语法检查
官网:
ESLint - Pluggable JavaScript linter - ESLint中文
Getting Started with ESLint - ESLint中文
- 使用单引号(’)代替双引号(")
- 去掉语句结尾的分号(;)
- 运算符前后的空格
兼容性问题
- 思路一:shim,将不同的AP封装成一种
-
思路二:polyfil
Babel · The compiler for next generation JavaScript (babeljs.io)
如:部分浏览器不支持箭头函数,我们将箭头函数转换成普通函数
babe的功能:
语法转换,将ES6+的语法转换为向后兼容的 JavaScript语法
通过Poyf方式在目标环境中添加缺失的特性通过@babel/polyfill模块)
可转换丿SX语法
Babe是一个 javAscript编译器
Babel的安装
-
第一步,安装 Nodes
-
第二步,安装 cnpm/yarn
- NPM镜像-NPM下载地址-NPM安装教程-阿里巴巴开源镜像站 (aliyun.com)
npm install -g cnpm --registry=https://registry.npm.taobao.org
-
第三步,安装 babel
- cnpm install -g @babel/core @babel/ cli
Babel的使用
- 将箭头函数转换成普通函数
let getYear =() => new Date().getFullYear()
11 Flex布局
什么是Flex布局?
Flex(Flexible box)——弹性布局
Fex布局的兼容性:
基本概念
- 容器(Flex Container)
- 元素项(Flex Item)
- 水平轴,横轴,主轴(main axis)
- 垂直轴,纵轴,交叉轴(cross axis)
Flex容器(Flex container)的属性
-
flex-direction—容器内元素的排列方向
- row(默认值):主轴为水平方向,从左到右
- row-reverse:主轴为水平方向,从右到左
- column:主轴为垂直方向,从上到下
- column-reverse:主轴为垂直方向,从下到上
-
flex-wrap容器内元素的换行行为
- nowrap(默认):不换行
- wrap:换行,首行在上方
- wrap-reverse:换行,首行在底部
-
flex-flow–direction和wrap的复合属性
-
flex-flow: <'flex-direction'>||<'flex-wrap'> 默认值为row nowrap
-
-
justify-content—元素在横轴上的对齐方式
- flex-start(默认值):左对齐
- flex-end:右对齐
- center:居中对齐
- space-between:两端对齐,item之间的间隔相等
- space-around:每个item两侧的间隔相等
-
align-Items元素在纵轴上的对齐方式
- stretch(默认值):占满整个容器的高度
- flex-start:与纵轴起点对齐
- flex-end:与纵轴终点对齐
- center:与纵轴中间对齐
- baseline:与基线对齐
-
align-content—多行元素的对齐方向
- stretch(默认值):占满整个容器的高度fle-start:与纵轴起点对齐
- flex-end:与纵轴终点对齐
- center:与纵轴中间对齐
- space-between:与纵轴两端对齐,item之间的间隔平均分布
- space-around:每根轴线两侧的间隔相等
元素项(Flex item)的属性
- order-排序规则,越小越靠前排列
- 默认为0
- 数值越小,排列越靠前
- flex-grow——放大(撑开)比例
- 0(默认值):如果存在剩余空间,也不放大
- 1:如果存在剩余空间,均分剩余空间
- 既有0,也有1:如果存在剩余空间,0的不撑大,1撑大
>=1
:如果存在剩余空间,按比例分配剩余空间
- flex-shrink—收缩比例
- (默认):如果空间不足,该item将缩小
- flex-basis水平方向的大小
- 如果所有子元素的基准值之和大于剩余空间,则会根据每项设置的基准值,按比率伸缩剩余空间
- auto(默认值):无特定宽度值,取决于其它属性值
- < length>:用长度值来定义宽度不允许负值
- < percentage>:用百分比来定义宽度不允许负值
- content:基于内容自动计算宽度
- flex-grow、shrink、basis的复合属性
- 1:则其计算值为110%
- auto:则其计算值为1 1auto
- none:则其计算值为0 0auto
- 0auto:则其计算值为0 1auto
- align-self-元素在纵轴上的对齐方式
- auto(默认值):父元素的 align-items值,若无,则为stretch
- stretch:占满整个容器的高度
- flex-start:与纵轴起点对齐
- flex-end:与纵轴终点对齐
- center:与纵轴中间对齐
- baseline:与基线对齐