1.ES6常用语法
ES6模块化的使用和编译环境
ES6的开发环境已经普及使用
浏览器环境支持却不好(需要开发环境编译代码)
关于JS众多的模块化标准
- 没有模块化
- AMD成为标准,require.js
- 前端打包工具,使得nodejs模块化可以被使用
- ES6出现,想统一现在的模块化标准
1.模块化基本语法
//util1.js
export default{
a:100,
b:200
}
//util2.js
export function f1(){
console.log("f1...");
}
export function f2(){
console.log("f2...");
}
//main.js
import default as utils from "./util1.js"
import {f1,f2} from "./util2.js"
f1();
f2();
utils.a = 10;
console.log(utisl.a);
2.开发环境配置babel
- 安装nodejs,运行npm init -y
- npm install babel-core babel-preset-es2015 babel-preset-latest
- 项目根目录下创建.babelrc文件
- 配置该文件{ "presets":["es2015","latest"]}
- npm install babel-cli --global
- babel --version
- babel main.js可以看到编译后的结果
3.开发环境webpack
- npm install webpack babel-loader --save-dev
- 创建并配置webpack.config.js
- 配置.babelrc
- 配置package.json文件中的scripts
- 运行npm start
//webpack.config.js
const path = require("path");
module.exports = {
context:path.join(__dirname,"./src"),
entry:{
app:"main.js"
},
output:{
path:"../dist"
filename:"bundle.js"
},
module:{
rules:[
{
test:/\.js$/,
use:"babel-loader",
exclude:"../node_modules/"
}
]
}
}
//package.json
scripts:{
...
start:"webpack"
}
webpack的完整配置,包含webpack-dev-server自动打包
//webpack.config.js
const path = require("path");
const HTMLWebpackPlugin = require("html-webpack-plugin");
const webpack = require("webpack");
module.exports = {
context:path.join(__dirname,"./src"),
entry:{
app:"main.js"
},
output:{
path:"../dist"
filename:"bundle.js"
},
plugins:[
//template指定模板,将来会根据指定的页面路径,去生成内存中的页面,filename指定生成页面的名称
new HTMLWebpackPlugin({template:"index.html",filename:"index.html"}),
//new一个热更新的模块对象 启用热更新的第3步
new webpack.HotModuleReplacementPlugin()
],
devServer:{
open:true,
port:3000,
hot:true,
contentBase:"src",
},
module:{
rules:[
//配置js的解析器
{
test:/\.js$/,
use:"babel-loader",
exclude:"../node_modules/"
},
//配置css解析器
//使用import语法,导入CSS样式表 !!!webpack默认只能打包处理JS类型的文件,无法处理其他的非JS类型的文件,若要处理非JS类型的文件,需要手动安装一些合适第三方loader加载器
{
test:/\.css$/,
use:["style-loader","css-loader"]//从右到左处理
},
//配置less文件的解析器
{
test:/\.less$/,
use:["style-loader","css-loader","less-loader"]
},
//配置处理scss文件的解析器
{
test:/\.scss$/,
use:["style-loader","css-loader","scss-loader"]
},
//配置处理url解析器
//默认情况下,webpack无法处理css文件中的url地址,不管时图片,字体库还是地址,都处理不了
{
test:/\.(png|jpg|jpeg|bmp|gif)$/,
use:"url-loader?limit=7631&name=[hash:8]-[name].[ext]"
//处理图片路径的loader,使用?传参,当引用的图片大于或等于==》limit给定的值(图片大小byte位),则不会被转为Base64格式的字符串;若图片小于给定的limit值,则会被转为Base64格式的字符串
},
//处理字体文件
{
test:/\.(ttf|woff|woff2|eot|svg)$/,
use:"url-loader"
},
]
}
}
//package.json
scripts:{
...
//webpack-dev-server把打包好的文件,以一种虚拟的形式,托管到了咱们项目的根目录中,虽然我们看不到它,但,可以认为,和dist node_modules 平级,有一个看不见的文件,叫做bundle.js,引用它时应:/bundle.js====>目的:速度快,也不消耗磁盘
//start:"webpack-dev-server --open --hot -port 3000 --contentBase src "
//每次打包后自动打开浏览器,端口号为3000,以src为内容的根路径(进来就打开这个文件夹下的内容) 热更新(每次保存都来个补丁;可以实现浏览器的无刷新)
start:"webpack-dev-server"
}
4.开发环境rollup.js
react和vue都是rollup打包的
rollup功能单一,webpack功能强大
参考设计原则和《Linux/Unix设计思想》
工具与尽量单一,可集成,可扩展
- npm init -y
- npm i rollup rollup-plugin-node-resolve rollup-plugin-babel babel-plugin-external-helpers babel-preset-latest --save -dev
-
配置.babelrc
-
配置rollup.config.js
class与JS构造函数的区别
- class在语法上更加贴合面向对象的写法
- class实现继承更加易读、易理解
- 更易于写java等后端语言
- 本质还是语法糖,使用prototype
//语法糖形式
class MathHandle{
//...
}
typeof MathHandle //"function"
MathHandle.prototype.constructor = MathHandle //true
var mh = new MathHandle();
mh.__proto__ === MathHandle.prototype //true
继承:
//父类
class Animal{
constructor(name){
this.name = name;
}
eat(){
console.log(this.name+"eat.");
}
}
//子类
class Dog extends Animal{
constructor(){
super(name);
this.age = 8;
}
say(){
console.log(this.name+"say.");
}
}
const dog = new Dog();
dog.say();
dog.eat();
Promise的用法
基本语法
在cssCDN中,获取bluebrid可以在低版本浏览器中兼容Promise
异常捕获
可以捕获throw new Error(err)语法的错误,也可以捕获reject(err)的错误
多个串联
Promise.all和Promise.race
//接受一个promise'对象的数组
//等待全部Promise对象完成之后,统一执行then
Promise.all([result1,result2]).then((datas){
//接收到的是一个数组,包含了多个promise返回的内容
console.log(datas[0]);
console.log(datas[1]);
});
接受一个promise'对象的数组
//只要有一个完成,就执行success
Promise.race([result1,result2]).then(function(data){
//最先执行完成的promise的返回值
console.log(data)
});
Promise标准-状态变化
- 三种状态:pending、fulfilled、rejected
- 初始状态:pending
- pending变为fulfilled,或者pending变为rejected
- 状态变化不可您
promise目的是解决callback hell即回调地狱
其他常用功能
- let/const
- 多行字符串/模板变量
- 解构赋值
- 块级作用域
- 函数默认参数
- 箭头函数
2.异步
当前异步的解决方案
- jQuery Deferred
- Promise
- Async/Await
- Generator
什么是单线程,和异步的关系
单线程:只有一个线程,只能做一件事情
原因:
- 浏览器需要渲染DOM
- JS可以修改DOM结构
- JS执行的时候,浏览器DOM渲染会暂停
- 两段JS也不能同时执行(都修改DOM就冲突了)
- webworker支持多线程,但是不能访问DOM
解决方案:异步
异步是一种无奈的解决方案,虽然有很多问题
问题:
没按照书写方式执行,可读性差
callback中不容易模块化
实现方式:event Loop
event loop事件轮询,JS实现异步的具体解决方案
- 同步代码,直接执行
- 异步代码先放在异步队列中
- 待同步函数执行完毕,轮询 执行异步队列的函数
setTimeout(function(){
console.log(100);
},0);
console.log(200);
//主进程 console.log(200);
//异步队列: function (){console.log(100);}
$.ajax({
url:"xxxxxx",
success:function(){
console.log("a");
}
})
setTimeout(function(){
console.log(100);
},100);
setTimeout(function(){
console.log(300);
},0);
console.log(200);
//主进程:
console.log(200);
//异步队列:
console.log(100);
console.log(300);//可能,看异步ajax请求成功的时机
console.log("a");//可能,看异步ajax请求成功的时机
jQuery-deferred
- 无法改变JS异步和单线程的本质
- 只能从写法上杜绝callback这种形式
- 它是一种语法糖,但是解耦了代码
- 很好的体现:开放封闭原则
$.Deferred对象的API可分成两类,用意不同:
- dtd.resolve()\dtd.reject()
- dtd.then\dtd.fail()\dtd.done(0
- 这两类应该分开,后果很严重,可以试着在最后执行did.reject()
var waitHandle = function(data){
//创建一个deferred对象
var dtd = $.Deferred();
var wait = function(data){
if(data){
dtd.resolve();
console.log(""success.)
}else{
dtd.reject();
console.log("reject.")
}
//返回deferred对象
return dtd;
}
//返回deferred对象
return wait(data);
}
//使用
var w = waitHandle();
w.then(function(){
console.log("ok1.");
},function(){
console.log("err1.");
}).then(function(){
console.log("ok2.");
},function(){
console.log("err2.");
})
使用dtd.promise()方法
var waitHandle = function(data){
//创建一个deferred对象
var dtd = $.Deferred();
var wait = function(data){
if(data){
dtd.resolve();
console.log(""success.)
}else{
dtd.reject();
console.log("reject.")
}
//返回deferred对象的promise()方法
return dtd.promise();
}
//返回deferred对象
return wait(data);
}
//使用
var w = waitHandle();
$.when(w)
.then(function(){
console.log("ok1.");
},function(){
console.log("err1.");
}).then(function(){
console.log("ok2.");
},function(){
console.log("err2.");
})
w.reject();//执行这句话会直接报错
async-await
- 使用await,函数必须是async标识
- await后面跟的是一个promise实例
- 需要babel-polyfill
使用了Promise,并没有和Promise冲突
完全是同步的写法,再也没有回调函数
但是:改变不了JS单线程、异步的本质
//使用await,函数必须是async标识
const load = async function (){
//await后面跟的是一个promise实例
const result1 = await loadImg(src1);
console.log(result1);
const result2 = await loadImg(src2);
console.log(result2);
}
load();
//需要babel-polyfill
3.原型
说一个原型的实际应用
jQuery中的每一个元素都有css、html方法,都是原型的体现
jQuery
Zepto
原型如何体现它的扩展性
总结zepto和jquery原型的使用
插件机制
为何要把原型方法放在$.fn?
因为要扩展插件,只有$暴露在window全局变量,将插件扩展统一到$.fn.xxx这一个接口,方便使用
//扩展插件
$.fn.getNodeName = function(){
return this[0].nodeName
}