Es6 模块化如何使用,开发环境如何打包?
回答: es6的模块化是import 和export 的语法。
代码如下:
//util1.js: 输出一个默认的对象
export default {
a: 1
}
//util2.js: 输出两个函数
export function fn1() {
console.log('fn1')
}
export function fn1() {
console.log('fn1')
}
//index.js 引入使用
import util from './util1'
import { fn1, fn2 } from './util2'
console.log(util)
fn1()
fn2()
这里很简单的语法使用,不多赘述。
转换es的方法如下:
第一步: npm init, 得到package.json
第二步: 安装依赖,核心、preset2015、preset-latest(最新)
npm install babel-core babel-preset-es2015 babel-preset-latest
第三步: 配置.babelrc文件
{
"presets": ["es2015", "latest"],
"plugins": {}
}
第四步: 全局安装babel
npm install babel-cli -g
第五步:使用
babel src/index.js(要解析的文件)
开发环境的打包
rollup
Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码.
和webpack对比: 职责单一,就是用来解析es6的模块化的,且编译出来的代码比webpack编译的代码更少。
如何使用?
- 安装文件: rollup, plugin-node-resolve,babel,external-helpers,latest
- 配置.babelrc文件
- 配置rollup.config.js
- 修改webpack文件的启动方式
.bablerc配置如下
{
"presets": [
"latest", {
"es2015": {
"modules": false
}
}
],
"plugins": ["external-helpers"]
}
rollup.config.js配置如下:
import babel from "rollup-plugin-babel"
import resolve from "rollup-plugin-node-resolve"
export default {
"entry": "src/index.js",
"format": "umd",
"plugins": [
resolve(),
babel({
exclude: "node_modules/*"
})
],
"dest": "build/bundle.js"
}
这里遇到一个小坑。
Error: Cannot find module '@babel/core'
最后发现是: rollup-plugin-babel @4.X 和 [email protected]不兼容、后来把rollup-plugin-babel降级 到3.X就可以了。
Class 和普通构造函数的区别是什么, 优缺点是什么?
回答:
传统的constructor是这样的:
//构造函数
function MathHandle(x, y) {
this.x = x;
this.y = y;
}
//添加add方法
MathHandle.prototype.add = function() {
return this.x + this.y
}
//实例化这个构造函数
var m = new MathHandle(10, 20)
console.log(m.add())
Class是这样的:
class MathHandle {
constructor(x, y) {
this.x = x;
this.y = y;
}
add() {
return this.x + this.y
}
}
let m = new MathHandle(10, 20)
console.log(m.add())
实际上在javascript中是没有class类的,class就是一个语法糖
typeof MathHandle === function
MathHandle.prototype.constructor === MathHandle
重点知识: 继承
传统的js继承实现如下:
- 创建一个高级的抽象构造函数
- 创建一个低级的构造函数
- 把低级构造函数的显示原型复制成高级原型的实例
- 实例化低级构造函数,这个实例继承了高级构造函数的方法
代码:
//定义一个抽象的高级构造函数
function Animal() {
this.eat = function() {
console.log("animal need eat")
}
}
//定义一个低级的构造函数
function Dog() {
this.dark = function() {
console.log("dog offen dark")
}
}
//把低级构造函数的显示原型赋值成高级构造函数的实例, 实现继承高级构造函数的方法
Dog.prototype = new Animal();
// 实例化低级函数, 此时低级函数具有自己的方法,同时拥有高级函数的方法
var dog = new Dog()
dog.eat() //animal need eat
dog.dark() //dog offen dark
class 实现的继承步骤如下
- 定义一个高级的构造函数
- 定义低级构造函数继承高级构造函数 extends
- 低级构造函数执行constructor之前先通过super执行高级构造函数的constructor
- 这时候实例化低级构造函数 , 低级构造函数就继承了高级构造函数的方法
//定义个高级的构造函数
class Animal {
constructor(name) {
this.name = name
}
eat() {
console.log(`${this.name}eat`)
}
}
//定义个低级的构造函数继承高级构造函数
class Dog {
constructor(name) {
// 通过super先执行高级构造函数的consructor, 让高级构造函数也具有name
super(name)
this.name = name
}
dark() {
console.log(`${this.name} dark`)
}
}
//实例化dog
let dog = new Dog("哈士奇")
dog.eat() //哈士奇eat
dog.dark() //哈士奇dark
总结
- class更贴合面向对象,更易读和理解
- 本质是语法糖,使用的是原型的继承方式
Promise的使用和原理
回答:
promise 是为了解决传统js中处理异步的callbackHell
传统的js中回调一般是这样的:
function loadImg(src, callabck, faild) {
var img = document.createElement('img')
img.onload = function(img) {
callback(img)
}
img.onerror = function() {
faild()
}
}
//调用这个回调函数
var src = "xxxx"
loadImg(src, function(img) {
//这里通常做很多动作, 如果还有回调,就会出现回调地狱
console.log(img.width)
}, function() {
console.log("faild")
}
)
如果使用Promise就是把异步代码同步化写法,本质上还是异步的。
具体代码如下:
function loadImg(src) {
const promise = new Promise((resolve, reject) => {
var img = document.createElement('img')
img.onload = function(img) {
resolve(img)
}
img.onerror = function() {
reject()
}
img.src = src
})
return promise
}
var src = "xxx"
var result = loadImg(src)
result.then(function(img) {
console.log(img.width)
}, function() {
console.log("faild")
})
result.then(function(img) {
console.log("height")
})
总结: Promise让异步代码同步化,并且可以链式的.then操作。更易读。解决了回调地狱的问题
总结Es6的有哪些常用功能?
回答: 解模板变量,默箭头作用域
- 解: 结构赋值
- 模板: 多行/模板字符串
- 变量: let/const
- 默: 函数默认参数
- 箭头: 箭头函数
- 作用域: 块级作用域
变量
let j = 20;
const i = 10;
j = 30;
i = 40; //Assignment to constant variable.
模板字符串
let name = "zhangsan", age = "18", html="";
html = `<p>${name}${age}</p>`
解构赋值
obj={a:10, b:20, c: 30}
let {x, y, z} = obj
---------------------------
function fn({commit, aaa}) {
console.log(commit, aaa)
}
fn({commit: 'commit', aaa: 'aaa'})
---------------------------
let {, x, y} = [1, 2, 3]
解构赋值的好文链接:
https://blog.csdn.net/c_kite/article/details/72587929
默认参数
function(a, b = 0) {
console.log(b)
}
块级作用域
for(let i = 0; i < 10; i++) {
.....
}
console.log(i) //result: undefined
箭头函数
arr.map((item, index) => {
console.log(item)
return item + 1
})
关于箭头函数的this指向
function fn() {
console.log('real', this) //real {a: 100}
var arr = [1, 2, 3]
arr.map(function(item) {
console.log(this) // 改变指向window
})
arr.map(item => console.log(this)) //不改变指向 {a: 100}
}
//通过call把this的指向变成「a: 100」
fn.call({a: 100})
注意: 使用箭头函数的时候,应该运用在简单的函数上。如果函数体内容复杂,还应该使用传统的函数。箭头函数是对传统函数的完善,不能代替传统的函数。