前端面试之ES6篇
1、箭头函数需要注意的地方
2、ES6 let、const
3、set数据结构
4、promise对象的用法,手写一个promise
5、class的理解
6、模版语法的理解
7、rest参数
8、 module体系
箭头函数需要注意的地方
*当要求动态上下文的时候,就不能够使用箭头函数。也就是this的固定化
1、在使用=>定义函数的时候,this的指向是定义时所在的对象,而不是使用时所在的对象
2、不能够用作构造函数,这就是说,不能够使用new命令,否则就会抛出一个错误
3、不能够使用arguments对象
4、不能使用yield命令
这是一道当年很困惑我的一道题不知道你在第一眼能不能看出其结果,this的指向总是让人困扰,但是有了=>以后妈妈再也不用担心你使用this了
class Animal {
constructor(){
this.type = 'animal'
}
says(say) {
setTimeout(function () {
console.log(this.type + 'says' + say)
},1000)
}
}
var animal = new Animal()
animal.says('hi') // undefined says hi
我们再来看看=>的情况
class Animal() {
constructor() {
this.type = 'animal'
}
says(say) {
setTimeout(() => {
console.log(this.type + ' says ' + say)
}, 1000)
}
}
var animal = new Animal()
animal.says('hi') // animal says hi
ES6 let、const
*let是更完美的var,不是全局变量,具有块级函数作用域,大多数情况不会发生变量提升。const定义常量值,不能够重新赋值,如果值是一个对象,可以改变对象里边的属性值
let
1、let声明的变量具有块级作用域
2、let声明的变量不能通过window.变量名进行访问
3、形如for(let x..)的循环是每次迭代都为x创建新的绑定
下面是var带来的不合理场景
var a = []
for (var i = 0; i < i; i++) {
a[i] = function () {
console.log(i)
}
}
a[5]() // 10
在上述代码中,变量i是var声明的,在全局范围类都有效。所以每一次循环,新的i值都会覆盖旧值,导致最后输出都是10
而如果对循环使用let语句的情况,那么每次迭代都是为x创建新的绑定代码如下
var a = []
for (let i = 0; i < i; i++) {
a[i] = function () {
console.log(i)
}
}
a[5]() // 5
当然除了这种方式让数组中的各个元素分别是不同的函数,我们还可以采用闭包和立即函数两种方法
这是闭包的方法
function showNum(i) {
return function () {
console.log(i)
}
}
var a = []
for (var i = 0; i < 5; i++) {
a[i] = showNum(i)
}
这是立即函数的方法
var a = []
for (var i = 0; i < 5; i++) {
a[i] = (function (i) {
return function () {
console.log(i)
}
})(i)
}
a[2]()
Set数据结构
*es6方法,Set本身是一个构造函数,它类似于数组,但是成员值都是唯一的
const set = new Set([1,2,3,4,4])
[...set] // [1,2,3,4]
Array.from(new Set())是将set进行去重
promise对象的用法,手写一个promise
promise是一个构造函数,下面是一个简单实例
var promise = new Promise((resolve,reject) => {
if (操作成功) {
resolve(value)
} else {
reject(error)
}
})
promise.then(function (value) {
// success
},function (value) {
// failure
})
Class的讲解
*class语法相对原型、构造函数、继承更接近传统语法,它的写法能够让对象原型的写法更加清晰、面向对象编程的语法更加通俗
这是class的具体用法
class Animal {
constructor () {
this.type = 'animal'
}
says(say) {
console.log(this.type + 'says' + say)
}
}
let animal = new Animal()
animal.says('hello') // animal says hello
class Cat extends Animal {
constructor() {
super()
this.type = 'cat'
}
}
let cat = new Cat()
cat.says('hello') // cat says hello
可以看出在使用extend的时候结构输出是cat says hello 而不是animal says hello。说明contructor内部定义的方法和属性是实例对象自己的,不能通过extends 进行继承。在class cat中出现了super(),这是什么呢
在ES6中,子类的构造函数必须含有super函数,super表示的是调用父类的构造函数,虽然是父类的构造函数,但是this指向的却是cat
Object.assign 方法
var n = Object.assign(a,b,c)向n中添加a,b,c的属性
模版语法
*就是这种形式${varible}
,在以往的时候我们在连接字符串和变量的时候需要使用这种方式'string' + varible + 'string'但是有了模版语言后我们可以使用string${varible}string
这种进行连接
rest参数
*es6引入rest参数,用于获取函数的多余参数,这样就不需要使用arguments对象了
ex:
function add(...values) {
let sum = 0
for(var val of values) {
sum += val
}
return sum
}
module体系
*历史上js是没有module体系,无法将一个大程序拆分成一些小的程序。在es6之前,有commonJs,AMD两种
CommonJS是如何书写的呢
const animal = require('./content.js')
// content.js
module.exports = 'a cat'
require.js是这样做的
// content.js
define('content.js', function () {
return 'A cat'
})
require(['./content.js'], function (animal) {
console.log(animal) // a cat
})
ES6的语法(在我用的vue中,就使用的是这个)
import animal from './content'
// content.js
export default 'a cat'
es6 import的其他用法
在vue中可以 import animal from './content'
animal这个值可以根据你的喜欢而改变,但是有一个问题就是如果一旦引入的是函数或者变量时,你就必须和content中的名字保持一致,可以参照
import { say, type } from './content'
常用的还有一种写法
import * as content from './content'
这种写法就是表示所有的输出值都在这个对象上