这篇文章的主旨在于复习基础知识.涵盖了js基础,CSS,es6新特性以及关于数组方法的总结.废话不多说.总结一些面试题.方便你我他.内容尽可能涵盖高频的基础面试题
一. js基础.
1. 数据类型:
- 原始数据类型:
Number,
String,
Boolean,
Null,
Undefined,
Symbol(ES6,表示独一无二的值),
BinInt,(ES10,是一种内置对象,可以表示任意大的整数)
- 引用数据类型:
Object 其中包含Array,Function,date...
2. 数据类型的判断
-
typeof 对于原始数据类型,都用正常的显示其类型,特殊的null除外,下面举几个不同的栗子
console.log(typeof 5) // number
console.log(typeof null) // object
console.log(typeof []) {} fun() // object
-
instanceof 可以正确的判断对象的类型,主要是通过判断对象的原型链总是不是能找到类型的prototype,注意判断的是对象!!!
console.log('string' instanceof String) //返回false, 非对象实例,因此返回false
console.log(new String() instanceof String) // true
console.log({} instanceof Object) // true
console,log([] instanceof Array) // true
在此结束了吗? 好像和我们工作中有些不太一样,在工作中经常需要判断的数据不知道是什么类型又想知道.所以接下来说的就是
Object.prototype.toString.call() 使用object对象的原型方法toString,在使用call,基本上可以精准的查到数据类型,下面请看栗子
const toStr = Object.prototype.toString
log(toStr.call(new String)); // [object String]
log(toStr.call(Math)); // [object Math]
log(toStr.call([])); // [object Array]
log(toStr.call(null)); // [object Null]
3.null和undefined的区别
首先这两个都是基本数据类型,有且只有本身一个值. null可以理解为是空对象,undefined可以理解为是未定义. 一般变量声明了但还没定义的时候会返回undefined,null主要用于赋值给一些可能会是对象的变量作为初始值
其实null不是对象,虽然typeof null 会输出Object,但这只是jS历史遗留的Bug
4.js中的this
(1) 在浏览器中,在全局范围内,作为普通函数时使用
- this等价于window对象
- 用var声明的变量等价于window添加属性,this也是指向window
console.log(this === window) // true
val str = 'hello'
console.log(this.str) // hello
console.log(window.str) // hello
(2) 函数是否在new中调用,如果是的话this绑定的是新创建的对象, 即构造函数中使用
var fn = new Function()
(3) 显式绑定 (call,apply,bind执行的第一个参数)
- 函数是否通过call,apply,bind调用,如果是的话this绑定的就是指定的对象
function fn() {
console.log(this.a)
}
var obj = {
a: 'fff'
}
fn.call(obj) // fff
(4) 隐式绑定 即作为对象属性时使用(调用属性的对象)
- 对于函数中的this指向,有一句话很好用: 运行时this永远指向最后调用它的那个对象...简单理解就是看被调用的函数是否是在某个上下文的对象中调用,是的话this就指向那个上下文对象
var a = 'hello'
function fn () {
conole.log(this.a)
}
var obj = {
a: '我是obj中的a'
fn: fn
}
var b = obj.fn
fn() // hello
b() // 我是obj中的a
5.new一个对象的过程
var a = new Foo()
- 创建一个新对象
- 把这个对象的的原型指向Foo,a.proto = Foo.prototype
- 绑定this到这个对象
- 最后返回新对象
6.作用域以及闭包
理解作用域
- 自由变量
- 作用域链,及自由变量的查找,找不到逐级向上查找
- 闭包
闭包是指有权访问另一个函数的作用域内变量的函数,创建闭包最常见的方式就是在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量
-
闭包的场景
(1)函数作为变量变量传递
(2)函数作为返回值
实际开发中的闭包
function fn(){
var n = 0;
function add(){
n++;
console.log(n);
}
return add;
}
var a1 = fn(); //注意,函数名只是一个标识(指向函数的指针),而()才是执行函数;
a1(); //1
a1(); //2 第二次调用n变量还在内存中
7.原型和原型链
原型需要记住的五条规则
- 所有的应用类型都可以自定义添加属性
- 所有的引用列席都有自己的隐式原型(
__proto__
) - 函数都有自己的显式原型(prototype)
- 所有的引用类型的隐式原型都指向对应构造函数的显式原型
- 使用引用类型的某个自定义属性时,如果没有这个属性,就会去该引用类型的
__proto__
中去找
7.js的事件的三个阶段是什么
- 事件捕获阶段
当我们在DOM树的某个节点发生了一些操作(如点击,鼠标移动),就会有一个一个事件发射过去,这个事件从window发出,不断经过下级节点直到除法的目标节点.这个过程就是事件捕获阶段
document --> html --> body --> div
- 事件目标阶段
当事件不断的传递直到目标节点的时候,最终在目标上触发这个事件.就是目标阶段
- 事件冒泡阶段
事件冒泡就是从目标节点,然后逐级传播向上(我们平时用的父节点的事件绑定就是利用事件冒泡的原理)
div --> body --> html --> document
W3C: 任何事件的发生时,先从顶层开始进行事件捕获,直到事件触发到达事件源,再从事件源向上进行事件冒泡
事件传播的阻止方法:
在W3C中,使用stopPropagation()方法 在IE下使用cancelBubble = true方法
阻止默认行为:
在W3C中,使用preventDefault()方法 在iE下使用return false
8.JS中有哪些内置函数你知道吗
Object, Array, Boolean, Number, String, Function, Date, RegExp, Error, parseInt, parseFloat, Math
9.var, let, const有什么区别
var声明变量是全局变量,挂载在window上,var可以声明同名变量.同时存在变量提升,而let和const声明的变量形成局部作用域,不可以声明同名变量,同时也不会变量提升
var a = 10
log(a,window.a) // 10 10
if(true) {
var a = 20 // var变量提升
let b = 10
}
log(a) // 20 // var
log(b) // 报错, is not defined
log(c) // 报错,let不存在变量提升
let c = 200
var a = 10
log(a) // 10
var a = 100
log(a) // 100 // var可以声明同名变量
const a = 10
const a = 100
log(a) // 报错
10.浅拷贝和深拷贝
浅拷贝:就是只拷贝对象的引用,多个对象指向堆内存的同一地址,修改任意一个对象,其他的都会改变
var obj = {
a: 10,
b: 20
}
var obj1 = {...obj}
obj.a = 200
log(obj) // {a:200,b:20}
log(obj1) // {a:200,b:20}
深拷贝: 将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放,且修改后不会影响原对象
(1) JSON.parse(),显式工作中,这个也可用,但要注意会忽略undefined, symbol, 函数,同时不能解决循环引用
(2) Object.assign({},obj),无法处理多层嵌套
(3) 浅拷贝加递归
// 定义一个深拷贝函数 接收目标target参数
function deepClone(target) {
// 定义一个变量
let result;
// 如果当前需要深拷贝的是一个对象的话
if (typeof target === 'object') {
// 如果是一个数组的话
if (Array.isArray(target)) {
result = []; // 将result赋值为一个数组,并且执行遍历
for (let i in target) {
// 递归克隆数组中的每一项
result.push(deepClone(target[i]))
}
// 判断如果当前的值是null的话;直接赋值为null
} else if(target===null) {
result = null;
// 判断如果当前的值是一个RegExp对象的话,直接赋值
} else if(target.constructor===RegExp){
result = target;
}else {
// 否则是普通对象,直接for in循环,递归赋值对象的所有值
result = {};
for (let i in target) {
result[i] = deepClone(target[i]);
}
}
// 如果不是对象的话,就是基本数据类型,那么直接赋值
} else {
result = target;
}
// 返回最终结果
return result;
}
11.防抖与节流
首先想一想实际开发中在什么情况下使用到防抖和节流函数,input的监听keyup事件,监听scroll事件,频繁点击事件 防抖: 是指在频繁触发的调用动作放在最后 执行一次.事件被触发n秒后在执行回调,如果在这n秒内事件又被触发,则重新计时,只有在n秒内事件没有被触发才执行回调
function bedounce(fn,delay = 500) {
var timer = null
return function() {
var self = this, arg = arguments
if (timer) {
// 存在 即重新计时
clearTimeout(timer)
timer = null
}
timer = setTimeout(() => {
fn.apply(self, args)
}, delay)
}
}
节流:高频触发的函数事件等,在一定时间内只可以触发一次,减少函数触发的次数。
function throttle(fn, delay = 500) {
var timer = null
return function() {
var self = this, args = arguments
!timer && timer = setTimeout(() => {
fn.apply(self, args)
timer = null
}, delay)
}
}
二. CSS基础.
1.盒模型
盒模型本质就是一个盒子,包含外边距margin,边框border,内边距padding,实际内容content构成
- 标准盒模型: width 即是 content宽度
- 怪异盒模型(IE): width 即是 content+padding+border
2.css中那些属性可继承
- 字体相关属性
font-weight
font-size
font-style
...
- 文本相关属性
text-indent 文本缩进
text-align
text-shadow 文本阴影
line-height
...
- 元素可见
visibility
- 光标属性
- cursor
3.css选择器的优先级
!important > 内外联样式 > ID选择器 > 类选择器 = 伪类选择器 = 属性选择器 > 元素选择器 = 伪元素选择器 > 通配符选择器 = 后代选择器 = 兄弟选择器
还有一个权重问题
10000: !important
1000: 内/外联样式
100: ID选择器
10: 类/伪类/属性 选择器
1: 元素/伪元素 选择器
0: 通配符/后代/兄弟 选择器
继承样式,没有权重
4.CSS中隐藏元素的方法
visibility: hidden 隐藏元素,但不会改变布局,也不会触发事件
display: none 把元素隐藏起来,会改变页面布局
z-index: -1 层级置于其他元素下面
opacity: 0 透明度为0,不会改变页面布局,绑定事件依旧可以触发
5.animation属性
animation-name 规定需要绑定到选择器的keyframe名称
animation-duration 规定完成动画所花费的事件,以秒或毫秒计算
animation-timing-function 规定动画的速度曲线
animation-delay 规定在动画开始之前的延迟
animation-iteration-count 规定动画应该播放的次数
animation-direction 规定是否应该轮流反向播放动画
js实现动画的方式: setInterval,requestAnimationFrame
6.CSS实现动画
transition--设置样式的属性值是如何从一个状态平滑过度到另一种状态
transform用于元素的2D或3D转化,可以用来设置元素的形状改变, rotate(旋转), scale(缩放), skew(扭曲),translate(移动),matrix(矩形变形).通常与transition组合使用
7.让盒子垂直水平居中的方式
- absolute + 负值margin (已知盒子的宽高)
.parent {
position: relative;
}
.child {
width: 200px;
height: 200px;
position: absolute;
left: 50%;
top: 50%;
margin: -100px 0 0 -100px;
}
- absolute + margin:auto (不知盒子宽高)
.parent {
position: relative;
}
.child {
position: absolute;
left: 0%;
top: 0%;
right: 0%;
bottom: 0%;
margin: auto;
}
- absolute + transform(常用!!!)
.parent {
position: relative;
}
.child {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
- display: flex (常用!!!不知盒子宽高,不兼容IE低版本)
.parent {
display: flex;
justify-content: center;
align-items: center;
}
- display: table-cell (针对table)
.parent {
display: table-cell;
text-align: center;
vertical-align: middle;
}
- display: grid
.parent {
display: grid;
}
.child {
align-self: center;
justify-self: center;
}
8.手机端自适应rem
rem是相对HTML根元素的font-size字体大小的长度单位变化而变化辅助媒体查询
js封装rem方案
export function rem (doc, win) {
let docEl = doc.documentElement; // 考虑兼容以及屏幕旋转事件
let resizeEv = 'orientationchange' in window ? 'orientationchange' : 'resize'
let recalc = function () {
var clientWidth = docEl.elientWidth
if (!clientWidth >= 750) {
docEl.style.fontSize = '100px'
} else {
docEl.style.fontSize = 100 * (clientWidth / 750) + 'px'
}
}
if (!doc.addEventListener) return
win.addEventListener(resizeEv,recalc,false) // 屏幕大小以及旋转变化自适应
doc.addEventListener('DOMContentLoaded', recalc, false) 页面初次打开自适应
recalc()
}
9.css预处理器(lass, sass)的区别
- 定义变量 sass是以$开头定义的变量
$mainFontSize: 14px;
less是以@开头定义的变量
@mainFontSize: 14px;
- 作用域 sass没有局部变量,满足就近原则 less中{}内定义的变量为局部变量
- 混合(Mixins) sass混合: sass样式中声明Mixins时需要使用@mixin命令,在选择器调用定义好的Mixins需要使用@include
@mixin mixinFn($bg-c:red) { // 声明Mixin叫mixinFn
width: 50px;
height: 50px;
background-color: $bg-c;
}
.isA { 调用Mixins
@include mixinFn(); // 不带参数
}
.isB {
@include mixinFn(blue); // 添加参数
}
less混合: 将定义好的classA 中引入另一个已经定义的class
.mixinFn($bg-c:red) { // 声明Mixin叫mixinFn
width: 50px;
height: 50px;
background-color: $bg-c;
}
.isA { 调用Mixins
.mixinFn(); // 不带参数
}
.isB {
.mixinFn(blue); // 添加参数
}
- 继承 sass的继承: @extend
.isA {
margin:5px 20px;
padding: 10px;
}
.isB {
@extend .isA; // 继承isA的样式
color: red;
}
less的继承
.isA { // 类似less的mixins
margin:5px 20px;
padding: 10px;
}
.isB {
.isA; // 继承isA的样式
color: red;
}
三. ES6新特性
1.提出了块级作用域 let和const
let是更完美的var 不是全局变量,一般情况下不会发生变量提升
const定义常量,不能够重新赋值,如果值是一个对象,可以改变里面的属性值
相信看到这里的朋友们对let和const与var的区别都很熟悉了.在这里我就不一一赘述了,请看下一个
2.``模板字符串
模板字符串大大的提高了我们的代码的质量以及阅读,使用${}
这种形式来替代我们原始的数据拼接
- 基本的字符串格式化.
//ES5
var name = 'tt'
log(name + 'ly') // ttly
//ES6
log(`${name}ly`) // ttly
- 用``解决反斜杠()来做多行字符串拼接
//ES5
var str = "hello \
world"
// ES6
let str = `hello
world`
3.解构
- 数组解构
// ES5
var arr = [1,2,3]
var a = arr[0]/arr[1]/arr[2] // 用索引来取值
// ES6
const arr = [1,2,3]
const [a, a1, a2] = arr
还有更多玩法可以自行探索哦
- 对象解构
与数组解构时用变量对象相应元素不同,对象的解构时通过属性名来匹配的.若没有匹配成功,则会变成undefined,当然也可以在解构的时候给变量起别名
const obj = {
name: "ttly"
age:18
}
const { name1, arr, age: a } = obj
log(name1, arr, age) // ttly ,undefined, 18
4.展开运算符"..."
...不仅可以作为剩余操作符使用,还可以用来展开数组. ...可以将数组的每一项一次传入函数中
// ES5
var arr = [1, 2, 3]
console.log.apply(console,arr)
// ES6
const arr [1, 2, 3]
console.log(...arr)
5.``对象扩展方法
- Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象,返回新对象. 如果目标对象中的属性和源对象有同样的键,这目标对象会被覆盖
语法: Object.assign({},...obj)
const target = {a: 1, b: 2}
const source = {b: 5, c: 6}
const newTarget = Object.assign(target,source)
log(target) // a: 1, b: 5, c: 6
log(newTarget) // a: 1, b: 5, c: 6
- Object.is()方法判断两个值是否为同一个值,返回一个boolean值
Object.is('foo', 'foo'); // true
Object.is(window, window); // true
Object.is('foo', 'bar'); // false
Object.is([], []); // false
var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo); // true
Object.is(foo, bar); // false
Object.is(null, null); // true
// 特例
Object.is(0, -0); // false
Object.is(0, +0); // true
Object.is(-0, -0); // true
Object.is(NaN, 0/0); // true
6.Set
Set是ES6引入的一种类似Array的新的数据结构,Set实例的成员都是唯一的,不重复的.利用这个特性可以轻松的实现数组去重
const numbers = [2,2,3,3,4,5,6,7,8,8,9,9]
log([...new Set(numbers)]) // [2,3,4,5,6,7,8,9]
7.箭头函数(区别于function)★★★
ES6的核心升级项...
- 箭头函数中的没有自己的this,this指向是函数定义时所在的对象. 也就是定义时的上下文的this指向
- 箭头函数不能用作构造函数,没有自己的this,无法实例化
- 箭头函数中不存在argunments.也是因为没有自己的this
- 箭头函数可以默认赋值,在ES6之前,函数的形参不能给默认赋值,只能在函数内部通过变通方法实现.
- 必须要用定义变量的方式来声明函数
- 可以简写,当函数的形参只有一个的时候,可以省略小括号.当函数体仅有一句(return)语句时,可以省略大括号
function fn(x, y = 'ttly') {
log(x, y)
}
fn(1) // 1, ttly
// 简写
const fn1 = num => num + 1
8.``Class类与构造函数★★★
ES6的Class可以看做ES5生成实例对象的构造函数的语法糖,让对象原型写法更加清晰,Class类可以通过extends实现继承
class Student {
constructor(name) {
this.name = name
}
si() {
log('hello')
}
}
class ttly extends Student {
constructor(name,age) {
super(name)
this.age = age
}
statis study() {
log('agg')
}
sayHi() {
super.si()
}
}
在这里提一下Class类与构造函数的区别
- Class类的所有方法都是不可枚举的,构造函数中的prototype的方法是可以进行枚举的
- Class类不存在变量提升
- Class类定义的构造函数不使用new是没法调用的
- 构造函数的继承是先创建子类的实例对象this,然后再将父类的方法添加到this上面(Parent.call(this)).Class类的继承实质是先创建父类的实例对象this,通过super方法,然后在用子类的构造函数修改this
9.Promise★★★
promise的出现主要是为了解决异步编程的回调地狱问题 promise简单的说就是一个容器,里面保存着谋个未来才会结束的事件(通常一个异步操作)的结果
Promise中有三个状态
- pending(进行中)
- fulfilled(成功)
- rejected(失败)
promise一旦状态改变,就不会在变,状态的改变也只有两种可能:pending->fulfilled,和pending->rejected
缺点:首先,无法取消Promise,一旦建立就立即执行,无法中途取消.其次,如果不设置毁掉函数,Promise内部抛出的错误,不会反应到外部.再者,当处于pending状态时,无法得知目前进展到哪一个阶段(刚开始还是即将完成)
const promise = new Promise(function(resolve, reject) {
if (/*异步操作成功*/) {
resolve(val)
} else {
reject(error)
}
})
小抄一个手写promise实现
function myPromise(constructor) {
let self = this
self.status = "pending" // 定义初始状态
self.value = undefined // 定义状态为resolved的时候的状态
self.reason = undefined // 定义状态为rejected的时候的状态
function resolve(value) {
// 两个==="pending",保存状态的改变是不可逆的
if (self.status === 'pending') {
self.value = value
self.status = 'resolved'
}
}
function rejected(reason) {
if (self.status === 'pending') {
self.reason = reason
self.status = 'rejected'
}
}
// 捕获构造异常
try {
constructor(resolve, reject)
} catch(e) {
reject(e)
}
}
// 定义链式调用的.then方法
myPromise.prototype.then = function(onFulfilled, onRejected) {
let self = this
switch (self.status) {
case "resolved":
onFullfilled(self.value)
break;
case: "rejected":
onRejected(self.reason)
break;
default
}
}
- Promise.all()方法用于将多个Promise实例,包装成一个新的Promise实例
const p = Promise.all([p1, p2, p3])
// p的状态是由p1,p2,p3决定,分两种情况
// (1) 只有p1,p2,p3的状态都编程fulfilled(已成功),p的状态才会变成fulfilled,此时p1,p2,p3的返回值组成一个数组,传递给p的回调函数
// (2) 只要p1,p2,p3之中有一个被rejected,p的状态就会变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result)
.catch(e => e);
Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// ["hello", Error: 报错了]
promise还有很多方法就不一一列举例,有兴趣的可以点击
10.proxy
Proxy可以理解成,在目标对象之前架设一层拦截,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写.Proxy这个词的原意是代理,用在这里表示由他来代理某些操作,可以理解成"代理器".内置的都get和set
由于理解的不够深刻,所以大家可以自行查找,以后慢慢补充
四. 数组方法的总结(认真记就不怕被问到各种数组的方法啦)
1、会改变原数组的方法
(1).push()方法在数组的尾部添加一个或多个元素,并返回数组新的长度
(2).pop()方法删除数组的最后一个元素,会减小数组涨肚并返回它删除的值
(3).unshift()方法在数组的头部添加一个或多个元素,并返回数组新的长度
(4).shift()方法删除数组的第一个元素,然后把所有随后的元素前移一个位置来填补数组头部的空缺,并返回删除的元素
(5).splice(start)方法在数组中插入或删除元素的通用方法.
(6).sort()方法将数组中的元素排序,并返回排序后的数组.
sort(fn)接收一个函数,默认排序是将数组中的元素转换为字符串,然后比较他们UTF-16单元值序列排序.
const arr = [1, 20, 5, 32, 1000]
log(arr.sort()) // [1, 1000, 20, 32, 5]
fn用来指定按某种顺序进行排序的函数,有两个参数.a第一个用于比较的元素. b用于比较的第二个元素
如果fn(a, b) 小于 0 那么a会排在b前面.
如果fn(a, b) 等于 0 那么a和b的相对位置不变
如果fn(a, b) 大于 0 那么b会排在a前面.
[3,4,5,10,1].sort((a, b) => a - b) // [1,3,4,5,10]
(7).reverse()方法将数组中的元素颠倒顺序,并返回倒序的数组
2、不改变原数组的方法
(1).slice(start,end)方法返回一个从开始到结束(不包括结束)的数组的一部分浅拷贝到一个新数组中,并返回.不会改变原数组
(2).join()方法将一个数组中的所有元素转换为字符串并返回一个新的数组元素串联起来的字符串,参数可接收一个字符串为分隔符.默认为',' 可用于简单的数组偏平化
(3).toString()方法将数组的每个元素转换为字符串,并返回一个用','分隔的字符串.可用于简单的数组偏平化
(4).concat()方法用于合并两个或多个数组.并返回一个新数组.注意点,concat()方法只是浅拷贝.所以原始数组和新数组都引用的相同的对象,新老的对象被修改,都将发生改变
(5).isArray()方法用于判断元素是否是一个Array,返回一个Boolean
3、数组遍历,映射,过滤等方法
(1).forEach()方法是从头到尾遍历数组,为每个元素调用指定的函数.注意forEach()方法无法中途退出循环,return只能退出本地回调,进行下一次回调.如果想提前终止,可以使用try块中,并能抛出一个异常throw. 想改变原数组记得使用第三个参数
(2).map()方法创建一个新数组,并返回一个每个元素执行指定函数后的新数组,注意: map()方法会创建一个新的数组,占用内存,如果不使用指定函数后的返回值.那就应当用forEach()方法
(3).filter()方法用于筛选出符合指定函数的判断的方法.返回的数组是调用指定函数后的新数组.
(4).every()方法用于检查数组中每个元素是否符合指定函数的条件.当数组所有元素都返回true,最终返回才是true,否则返回false
(5).some()方法用于检查数组中是否有一个元素符合指定函数的条件,如果有就返回true,否则返回false
(6).reduce()方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终返回一个计算值,reduce()对于空数组不会执行指定函数,通常用于求和
(7).indexOf(某元素, startIndex)方法用于从什么地方开始查找某元素在数组中的位置,若存在,则返回第一个位置的下标,否则返回-1
[1,2,3,4,2,4,5].indexOf(2) // 1
[1,2,3,4,2,4,5].indexOf(4,4) // 5
(8).lastIndexOf()方法与indexOf()相同,区别在于从尾部向首部查询.两者都不会改变原数组
(9).find()方法用于判断数组中是否有符合指定函数的元素,如果有就返回第一个符合条件的元素值.否则就返回undefined (ES6新增)
(10).findIndex()方法用于判断数组中是否有符合指定函数的元素,如果有就返回符合条件的元素索引值,否则返回-1.(ES6新增)
(11)keys()方法用于从数组创建一个包含数组键的可迭代对象.(ES6新增)
(12)values()方法用于从数组创建一个包含数组值的可迭代对象.(ES6新增)
(13).include()方法用于查看数组中是否与存在指定的值.返回一个boolean,用于简单数组(ES7)