Es6(es2015)常见高级面试题

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继承实现如下:

  1. 创建一个高级的抽象构造函数
  2. 创建一个低级的构造函数
  3. 把低级构造函数的显示原型复制成高级原型的实例
  4. 实例化低级构造函数,这个实例继承了高级构造函数的方法

代码:

//定义一个抽象的高级构造函数
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 实现的继承步骤如下

  1. 定义一个高级的构造函数
  2. 定义低级构造函数继承高级构造函数 extends
  3. 低级构造函数执行constructor之前先通过super执行高级构造函数的constructor
  4. 这时候实例化低级构造函数 , 低级构造函数就继承了高级构造函数的方法
//定义个高级的构造函数
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

总结

  1. class更贴合面向对象,更易读和理解
  2. 本质是语法糖,使用的是原型的继承方式

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的有哪些常用功能?

回答: 解模板变量,默箭头作用域

  1. 解: 结构赋值
  2. 模板: 多行/模板字符串
  3. 变量: let/const
  4. 默: 函数默认参数
  5. 箭头: 箭头函数
  6. 作用域: 块级作用域

变量

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})

注意: 使用箭头函数的时候,应该运用在简单的函数上。如果函数体内容复杂,还应该使用传统的函数。箭头函数是对传统函数的完善,不能代替传统的函数。

猜你喜欢

转载自blog.csdn.net/weixin_40814356/article/details/83931069