面试题(部分)

一、Promise,.then.catch那一块。

1、[Promise静态方法(resolve,reject,all,race)]
异步抽象处理对象

这4个方法都是静态方法,非实例方法,用Promise对象是无法调用的。

Promise.resolve将对象转为Promise对象。函数声明:Promise.resolve(value);。
Promise.reject将对象转换成一个状态为Rejected的全新的Promise对象。函数声明:Promise.reject(error);
Promise.all方法用于将多个Promise实例对象,包装成一个新的Promise实例对象。函数声明:Promise.all(iterable);
Promise.race方法和all方法类似,函数声明:Promise.race(iterable);

关于Promise.all
Promse.all在处理多个异步处理时非常有用,比如说一个页面上需要等两个或多个ajax的数据回来以后才正常显示,在此之前只显示loading图标。
关于Promise.race
顾名思义,Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

谨慎使用Promise.all
如果有一个回调执行失败,then是不会执行的,或者说,所有的promise也都失败了
即使有几个promise已经进入resolved状态,也会阻塞在那里直到所有的promise完成

2、Promise的then方法和catch方法

1、Promise.prototype.then()方法显然就是Promise的精华。函数声明:p.then(resolve, reject);
then()方法
不是静态方
法,需要经由Promise实例对象来调用。
then方法有两个参数,第一个参数是Promise实例对象为Resolved状态时的回调函数,它的参数就是上面Promise构造函数里resolve传递过来的异步操作成功的结果。

第二个参数可选,是Promise实例对象为Rejected状态时的回调函数,它的参数就是上面Promise构造函数里reject传递过来的异步操作失败的信息。

then方法最强大之处在于,它内部可以使用return或throw来实现链式调用。使用return或throw后的返回值是一个新的Promise实例对象(注意,不是原来那个Promise实例对象):

2、**Promise.prototype.catch()**同样是实例方法,需要经由Promise实例对象来调用,用于Promise实例对象状态为Rejected的后续处理,即异常处理。函数声明:p.catch(reject);

catch方法本质上等价于then(null, reject),参数reject是一个回调函数,它的参数就是Promise对象状态变为Rejected后,传递来的错误信息。

二、vuex相关知识。

Vuex是一个专为Vue.js应用程序开发的状态管理模式。然后Vuex里面有五个特别重要的属性,分别是state,mutations,actions,getters,modules。

1. state
放置状态相关的信息,vue是使用单一状态树的,也就是单一数据源,也就是说我们的state只能有一个

2. getters:从基本数据(state)派生的数据,相当于state的计算属性

3. mutations:提交更新数据的方法,必须是同步的(如果需要异步使用action)。每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。

回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。

4. actions:mutations是写同步操作的,在他里面是不能写异步操作的,那我们就需要在actions里面来写我们的异步操作。并且写异步操作的话,调用的话就不是使用commit了,而是 4使用我们的dispatch

5. modules:模块化vuex,可以让每一个模块拥有自己的state、mutations、actions、getters,使得结构非常清晰,方便管理。

三、深拷贝浅拷贝。

深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用。

浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,

深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,

使用深拷贝的情况下,释放内存的时候不会因为出现浅拷贝时释放同一个内存的错误。

四、es6新特性,新增的方法。

1. let const

let 表示申明变量。const 表示申明常量。

  • 常量定义了就不能改了。对象除外,因为对象指向的地址没变。
  • const在申明是必须被赋值。
  • 两者都为块级作用域。

块级作用域与函数作用域。任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。函数作用域就好理解了,定义在函数中的参数和变量在函数外部是不可见的。

const a = 1
a = 0 //报错
2. 模块字符串``

可以使用反引号````来进行字符拼接。${}

3. 解构

可以使用{}来对数组和对象进行解构。

image

image

4. 函数的参数默认值

函数传参可以有默认值

// ES6;
function printText(text = 'default') {
    console.log(text);
}
5. Spread / Rest 操作符...

Spread / Rest 操作符指的是 …,具体是 Spread 还是 Rest 需要看上下文语境。

  • 当被用于迭代器中时,它是一个 Spread 操作符:迭代器 (Iterator)是按照一定的顺序对一个或多个容 器 中的元素行进遍历的一种机制
function foo(x,y,z) {
  console.log(x,y,z);
}
 
let arr = [1,2,3];
foo(...arr); // 1 2 3
  • 当被用于函数传参时,是一个 Rest 操作符:当被用于函数传参时,是一个 Rest 操作符:
function foo(...args) {
  console.log(args);
}
foo( 1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]
6. 箭头函数
  • 不需要 function 关键字来创建函数
  • 省略 return 关键字
  • this始终指向函数申明时所在作用域下的this值
//es5
var fun = function() {

}
//es6
var fn = () => {

}
7. for of
  • for of遍历的是键值对中的值
  • for in遍历的是键值对中的键
8. class类

ES6 中支持 class 语法,不过,ES6的class不是新的对象继承模型,它只是原型链的语法糖表现形式。

class Student {
  constructor() {
    console.log("I'm a student.");
  }
 
  study() {
    console.log('study!');
  }
 
  static read() {
    console.log("Reading Now.");
  }
}
 
console.log(typeof Student); // function
let stu = new Student(); // "I'm a student."
stu.study(); // "study!"
stu.read(); // "Reading Now."
9. 导入导出
  • 导入improt
  • 导出export default
10. promise

Promise 用于更优雅地处理异步请求。

  <script>
    new Promise((resolve,reject) => {
      setTimeout(function() {
        resolve('成功了!')
      },1000)
      // reject("失败了,wuwu")
    }).then(data => {
      console.log(data)
    }).catch(err => {
      console.log(err)
    })
  </script>
11. async/await

比promise更好的解决了回调地狱。

async function() {
  awiat fn()
}
12. Symbol

新的基本类型

13. Set集合

存储任何类型的唯一值,即集合中所保存的元素是不重复的。类数组结构。

arr = [1,2,3,1]
let arrNew = new Set(arr)
arrNew = [1,2,3]

类数组不是数组,要转化为数组Array.form(arrNew)这样arrNew才是数组了

五、flex布局实现垂直水平居中

justify-content: center

align-items:center

六、Js关于继承那一块

js继承的6种方式

想要继承,就必须要提供个父类(继承谁,提供继承的属性)
  img

一、原型链继承

img
    重点:让新实例的原型等于父类的实例。
    特点:1、实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性。(新实例不会继承父类实例的属性!)
    缺点:1、新实例无法向父类构造函数传参。
       2、继承单一。
       3、所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)

二、借用构造函数继承

img
    重点:用.call()和.apply()将父类构造函数引入子类函数(在子类函数中做了父类函数的自执行(复制))
    特点:1、只继承了父类构造函数的属性,没有继承父类原型的属性。
       2、解决了原型链继承缺点1、2、3。
       3、可以继承多个构造函数属性(call多个)。
       4、在子实例中可向父实例传参。
    缺点:1、只能继承父类构造函数的属性。
       2、无法实现构造函数的复用。(每次用每次都要重新调用)
       3、每个新实例都有父类构造函数的副本,臃肿。

三、组合继承(组合原型链继承和借用构造函数继承)(常用)

img
    重点:结合了两种模式的优点,传参和复用
    特点:1、可以继承父类原型上的属性,可以传参,可复用。
       2、每个新实例引入的构造函数属性是私有的。
    缺点:调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数。

四、原型式继承

img
    重点:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象。object.create()就是这个原理。
    特点:类似于复制一个对象,用函数来包装。
    缺点:1、所有实例都会继承原型上的属性。
       2、无法实现复用。(新实例属性都是后面添加的)

五、寄生式继承

img
    重点:就是给原型式继承外面套了个壳子。
    优点:没有创建自定义类型,因为只是套了个壳子返回对象(这个),这个函数顺理成章就成了创建的新对象。
    缺点:没用到原型,无法复用。

六、寄生组合式继承(常用)

寄生:在函数内返回对象然后调用
    组合:1、函数的原型等于另一个实例。2、在函数中用apply或者call引入另一个构造函数,可传参 
     img
    重点:修复了组合继承的问题

七、This指向问题

八、Es6各种循环数组的方法,foreach,map,filter,reduce,some,every都是数组的操作

1.arr.forEach():用来代替普通for循环,接收两个参数(循环的回调函数,this的指向(可选,用的比较少))无返回值
2.arr.map():
#‘映射’ 用法同forEach(),经常用来做数据交互
#正常情况下,需要配合return,返回的是一个新的数组
#若是没有return ,相当于firEach();
#注意,平时只要用map,filter,some,every,就要配合return使用,
#可以重新整理数据
3.arr.filter():过滤,过滤掉不合格的元素,如果回调函数为true,则留下来
4.arr.some():类似查找,只要有一个符合条件的元素就返回true,反之返回false
5.arr.every():只有数组中所有元素符合条件就返回true,反之返回false
6.arr.reduce():
类似递归,传的参数(pre(当前值得前一个值),cur(当前值),index(当前值得索引),arr(数组本身)),从左向右计算
7.arr.reduceRight():从右向左计算
8.for…of 循环

九、节流和防抖

  • 节流是触发事件后,立即执行回调,一段时间过后才能再次触发,在这期间内无论触发多少次事件都不会执行回调(类似英雄技能冷却)。
  • 防抖是触发事件后,过一段时间再执行回调,在这期间再次触发事件,会重新计算时间(类似英雄回城)。
  • 节流和防抖的作用都是防止函数多次调用。

十、js十大算法

img

冒泡泡排序:

function bubbleSort(arr) {
    var len = arr.length;
    for (var i = 0; i < len; i++) {
        for (var j = 0; j < len - 1 - i; j++) {
            if (arr[j] > arr[j+1]) {        //相邻元素两两对比
                var temp = arr[j+1];        //元素交换
                arr[j+1] = arr[j];
                arr[j] = temp;
            }
        }
    }
    return arr;
}

十一、Vue的生命周期

  1. beforeCreate(创建前) 在数据观测和初始化事件还未开始
  2. created(创建后) 完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来
  3. beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。
  4. mounted(载入后) 在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。
  5. beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
  6. updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
  7. beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。
  8. destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
1.什么是vue生命周期?

答: Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。

2.vue生命周期的作用是什么?

答:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。

3.vue生命周期总共有几个阶段?

答:它可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后。

4.第一次页面加载会触发哪几个钩子?

答:会触发 下面这几个beforeCreate, created, beforeMount, mounted 。

5.DOM 渲染在 哪个周期中就已经完成?

答:DOM 渲染在 mounted 中就已经完成了。

十二、 Vue实现数据双向绑定的原理:Object.defineProperty()

vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过**Object.defineProperty()**来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。

十三、Vue的路由实现:hash模式 和 history模式

**hash模式:**在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。

**history模式:**history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”

十四、Vue与React的区别?

2.与React的区别
相同点:
React采用特殊的JSX语法,Vue.js在组件开发中也推崇编写.vue特殊文件格式,对文件内容都有一些约定,两者都需要编译后使用;中心思想相同:一切都是组件,组件实例之间可以嵌套;都提供合理的钩子函数,可以让开发者定制化地去处理需求;都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载;在组件开发中都支持mixins的特性。
不同点:
React采用的Virtual DOM会对渲染出来的结果做脏检查;Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作Virtual DOM。

十五、一句话就能回答的面试题

1.css只在当前组件起作用
答:在style标签中写入scoped即可 例如:

2.v-if 和 v-show 区别
答:v-if按照条件是否渲染,v-show是display的block或none;

3. r o u t e 和 route和 routerouter的区别
答: r o u t e 是 “ 路 由 信 息 对 象 ” , 包 括 p a t h , p a r a m s , h a s h , q u e r y , f u l l P a t h , m a t c h e d , n a m e 等 路 由 信 息 参 数 。 而 route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。而 routepathparamshashqueryfullPathmatchednamerouter是“路由实例”对象包括了路由的跳转方法,钩子函数等。

4.vue.js的两个核心是什么?
答:数据驱动、组件系统

5.vue几种常用的指令
答:v-for 、 v-if 、v-bind、v-on、v-show、v-else

6.vue常用的修饰符?
答:.prevent: 提交事件不再重载页面;.stop: 阻止单击事件冒泡;.self: 当事件发生在该元素本身而不是子元素的时候会触发;.capture: 事件侦听,事件发生的时候会调用

7.v-on 可以绑定多个方法吗?
答:可以

8.vue中 key 值的作用?
答:当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM。

9.什么是vue的计算属性?
答:在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。好处:①使得数据处理结构清晰;②依赖于数据,数据更新,处理结果自动更新;③计算属性内部this指向vm实例;④在template调用时,直接写计算属性名即可;⑤常用的是getter方法,获取数据,也可以使用set方法改变数据;⑥相较于methods,不管依赖的数据变不变,methods都会重新计算,但是依赖数据不变的时候computed从缓存中获取,不会重新计算。

10.vue等单页面应用及其优缺点
答:优点:Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。
缺点:不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。

十、vue如何自定义一个过滤器?

html代码:

<div id="app">
     <input type="text" v-model="msg" />
     {{msg| capitalize }}
</div>

JS代码:

var vm=new Vue({
    el:"#app",
    data:{
        msg:''
    },
    filters: {
      capitalize: function (value) {
        if (!value) return ''
        value = value.toString()
        return value.charAt(0).toUpperCase() + value.slice(1)
      }
    }
})

全局定义过滤器

Vue.filter('capitalize', function (value) {  if (!value) return ''  value = value.toString()  return value.charAt(0).toUpperCase() + value.slice(1)})

过滤器接收表达式的值 (msg) 作为第一个参数。capitalize 过滤器将会收到 msg的值作为第一个参数。

十一、对keep-alive 的了解?

keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
在vue 2.1.0 版本之后,keep-alive新加入了两个属性: include(包含的组件缓存) 与 exclude(排除的组件不缓存,优先级大于include) 。

使用方法

<keep-alive include='include_components' exclude='exclude_components'>  <component>    <!-- 该组件是否缓存取决于include和exclude属性 -->  </component></keep-alive>

参数解释
include - 字符串或正则表达式,只有名称匹配的组件会被缓存
exclude - 字符串或正则表达式,任何名称匹配的组件都不会被缓存
include 和 exclude 的属性允许组件有条件地缓存。二者都可以用“,”分隔字符串、正则表达式、数组。当使用正则或者是数组时,要记得使用v-bind 。

使用示例

<!-- 逗号分隔字符串,只有组件a与b被缓存。 -->
<keep-alive include="a,b">
  <component></component>
</keep-alive>

<!-- 正则表达式 (需要使用 v-bind,符合匹配规则的都会被缓存) -->
<keep-alive :include="/a|b/">
  <component></component>
</keep-alive>

<!-- Array (需要使用 v-bind,被包含的都会被缓存) -->
<keep-alive :include="['a', 'b']">
  <component></component>
</keep-alive>

JS数组方法

JavaScript中创建数组有两种方式

(一)使用 Array 构造函数:

var arr1 = new Array(); //创建一个空数组
var arr2 = new Array(20); // 创建一个包含20项的数组
var arr3 = new Array("lily","lucy","Tom"); // 创建一个包含3个字符串的数组

(二)使用数组字面量表示法:

var arr4 = []; //创建一个空数组var arr5 = [20]; // 创建一个包含1项的数组var arr6 = ["lily","lucy","Tom"]; // 创建一个包含3个字符串的数组

数组的方法有数组原型方法,也有从object对象继承来的方法,这里我们只介绍数组的原型方法,数组原型方法主要有以下这些:

join()
push()和pop()
shift() 和 unshift()
sort()
reverse()
concat()
slice()
splice()
indexOf()和 lastIndexOf() (ES5新增)
forEach() (ES5新增)
map() (ES5新增)
filter() (ES5新增)
every() (ES5新增)
some() (ES5新增)
reduce()和 reduceRight() (ES5新增)


下面详细介绍一下各个方法的基本功能。

1、join()

join(separator): 将数组的元素组起一个字符串,以separator为分隔符,省略的话则用默认用逗号为分隔符,该方法只接收一个参数:即分隔符。

var` `arr = [1,2,3];``console.log(arr.join()); ``// 1,2,3``console.log(arr.join(``"-"``)); ``// 1-2-3``console.log(arr); ``// [1, 2, 3](原数组不变)

通过join()方法可以实现重复字符串,只需传入字符串以及重复的次数,就能返回重复后的字符串,函数如下:

function` `repeatString(str, n) {``return` `new` `Array(n + 1).join(str);``}``console.log(repeatString(``"abc"``, 3)); ``// abcabcabc``console.log(repeatString(``"Hi"``, 5)); ``// HiHiHiHiHi

2、push()和pop()

push(): 可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。
pop():数组末尾移除最后一项,减少数组的 length 值,然后返回移除的项。

var` `arr = [``"Lily"``,``"lucy"``,``"Tom"``];``var` `count = arr.push(``"Jack"``,``"Sean"``);``console.log(count); ``// 5``console.log(arr); ``// ["Lily", "lucy", "Tom", "Jack", "Sean"]``var` `item = arr.pop();``console.log(item); ``// Sean``console.log(arr); ``// ["Lily", "lucy", "Tom", "Jack"]

3、shift() 和 unshift()

shift():删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined 。
unshift:将参数添加到原数组开头,并返回数组的长度 。

这组方法和上面的push()和pop()方法正好对应,一个是操作数组的开头,一个是操作数组的结尾。

var` `arr = [``"Lily"``,``"lucy"``,``"Tom"``];``var` `count = arr.unshift(``"Jack"``,``"Sean"``);``console.log(count); ``// 5``console.log(arr); ``//["Jack", "Sean", "Lily", "lucy", "Tom"]``var` `item = arr.shift();``console.log(item); ``// Jack``console.log(arr); ``// ["Sean", "Lily", "lucy", "Tom"]

4、sort()

sort():按升序排列数组项——即最小的值位于最前面,最大的值排在最后面。

在排序时,sort()方法会调用每个数组项的 toString()转型方法,然后比较得到的字符串,以确定如何排序。即使数组中的每一项都是数值, sort()方法比较的也是字符串,因此会出现以下的这种情况:

var` `arr1 = [``"a"``, ``"d"``, ``"c"``, ``"b"``];``console.log(arr1.sort()); ``// ["a", "b", "c", "d"]``arr2 = [13, 24, 51, 3];``console.log(arr2.sort()); ``// [13, 24, 3, 51]``console.log(arr2); ``// [13, 24, 3, 51](元数组被改变)

为了解决上述问题,sort()方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。比较函数接收两个参数,如果第一个参数应该位于第二个之前则返回一个负数,如果两个参数相等则返回 0,如果第一个参数应该位于第二个之后则返回一个正数。以下就是一个简单的比较函数:

function` `compare(value1, value2) {``if` `(value1 < value2) {``return` `-1;``} ``else` `if` `(value1 > value2) {``return` `1;``} ``else` `{``return` `0;``}``}``arr2 = [13, 24, 51, 3];``console.log(arr2.sort(compare)); ``// [3, 13, 24, 51]

如果需要通过比较函数产生降序排序的结果,只要交换比较函数返回的值即可:

function` `compare(value1, value2) {``if` `(value1 < value2) {``return` `1;``} ``else` `if` `(value1 > value2) {``return` `-1;``} ``else` `{``return` `0;``}``}``arr2 = [13, 24, 51, 3];``console.log(arr2.sort(compare)); ``// [51, 24, 13, 3]

5、reverse()

reverse():反转数组项的顺序。

var` `arr = [13, 24, 51, 3];``console.log(arr.reverse()); ``//[3, 51, 24, 13]``console.log(arr); ``//[3, 51, 24, 13](原数组改变)

6、concat()

concat() :将参数添加到原数组中。这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。在没有给 concat()方法传递参数的情况下,它只是复制当前数组并返回副本。

var` `arr = [1,3,5,7];``var` `arrCopy = arr.concat(9,[11,13]);``console.log(arrCopy); ``//[1, 3, 5, 7, 9, 11, 13]``console.log(arr); ``// [1, 3, 5, 7](原数组未被修改)

从上面测试结果可以发现:传入的不是数组,则直接把参数添加到数组后面,如果传入的是数组,则将数组中的各个项添加到数组中。但是如果传入的是一个二维数组呢?

var` `arrCopy2 = arr.concat([9,[11,13]]);``console.log(arrCopy2); ``//[1, 3, 5, 7, 9, Array[2]]``console.log(arrCopy2[5]); ``//[11, 13]

上述代码中,arrCopy2数组的第五项是一个包含两项的数组,也就是说concat方法只能将传入数组中的每一项添加到数组中,如果传入数组中有些项是数组,那么也会把这一数组项当作一项添加到arrCopy2中。

7、slice()

slice():返回从原数组中指定开始下标到结束下标之间的项组成的新数组。slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下, slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。

var` `arr = [1,3,5,7,9,11];``var` `arrCopy = arr.slice(1);``var` `arrCopy2 = arr.slice(1,4);``var` `arrCopy3 = arr.slice(1,-2);``var` `arrCopy4 = arr.slice(-4,-1);``console.log(arr); ``//[1, 3, 5, 7, 9, 11](原数组没变)``console.log(arrCopy); ``//[3, 5, 7, 9, 11]``console.log(arrCopy2); ``//[3, 5, 7]``console.log(arrCopy3); ``//[3, 5, 7]``console.log(arrCopy4); ``//[5, 7, 9]

arrCopy只设置了一个参数,也就是起始下标为1,所以返回的数组为下标1(包括下标1)开始到数组最后。
arrCopy2设置了两个参数,返回起始下标(包括1)开始到终止下标(不包括4)的子数组。
arrCopy3设置了两个参数,终止下标为负数,当出现负数时,将负数加上数组长度的值(6)来替换该位置的数,因此就是从1开始到4(不包括)的子数组。
arrCopy4中两个参数都是负数,所以都加上数组长度6转换成正数,因此相当于slice(2,5)。

8、splice()

splice():很强大的数组方法,它有很多种用法,可以实现删除、插入和替换。

删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。例如, splice(0,2)会删除数组中的前两项。

插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、 0(要删除的项数)和要插入的项。例如,splice(2,0,4,6)会从当前数组的位置 2 开始插入4和6。
替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例如,splice (2,1,4,6)会删除当前数组位置 2 的项,然后再从位置 2 开始插入4和6。

splice()方法始终都会返回一个数组,该数组中包含从原始数组中删除的项,如果没有删除任何项,则返回一个空数组。

var` `arr = [1,3,5,7,9,11];``var` `arrRemoved = arr.splice(0,2);``console.log(arr); ``//[5, 7, 9, 11]``console.log(arrRemoved); ``//[1, 3]``var` `arrRemoved2 = arr.splice(2,0,4,6);``console.log(arr); ``// [5, 7, 4, 6, 9, 11]``console.log(arrRemoved2); ``// []``var` `arrRemoved3 = arr.splice(1,1,2,4);``console.log(arr); ``// [5, 2, 4, 4, 6, 9, 11]``console.log(arrRemoved3); ``//[7]

9、indexOf()和 lastIndexOf()

indexOf():接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的开头(位置 0)开始向后查找。
lastIndexOf:接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的末尾开始向前查找。

这两个方法都返回要查找的项在数组中的位置,或者在没找到的情况下返回1。在比较第一个参数与数组中的每一项时,会使用全等操作符。

var` `arr = [1,3,5,7,7,5,3,1];``console.log(arr.indexOf(5)); ``//2``console.log(arr.lastIndexOf(5)); ``//5``console.log(arr.indexOf(5,2)); ``//2``console.log(arr.lastIndexOf(5,4)); ``//2``console.log(arr.indexOf(``"5"``)); ``//-1

10、forEach()

forEach():对数组进行遍历循环,对数组中的每一项运行给定函数。这个方法没有返回值。参数都是function类型,默认有传参,参数分别为:遍历的数组内容;第对应的数组索引,数组本身。

var` `arr = [1, 2, 3, 4, 5];``arr.forEach(``function``(x, index, a){``console.log(x + ``'|'` `+ index + ``'|'` `+ (a === arr));``});``// 输出为:``// 1|0|true``// 2|1|true``// 3|2|true``// 4|3|true``// 5|4|true

11、map()

map():指“映射”,对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。

下面代码利用map方法实现数组中每个数求平方。

var` `arr = [1, 2, 3, 4, 5];``var` `arr2 = arr.map(``function``(item){``return` `item*item;``});``console.log(arr2); ``//[1, 4, 9, 16, 25]

12、filter()

filter():“过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。

var` `arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];``var` `arr2 = arr.filter(``function``(x, index) {``return` `index % 3 === 0 || x >= 8;``}); ``console.log(arr2); ``//[1, 4, 7, 8, 9, 10]

13、every()

every():判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回true。

var` `arr = [1, 2, 3, 4, 5];``var` `arr2 = arr.every(``function``(x) {``return` `x < 10;``}); ``console.log(arr2); ``//true``var` `arr3 = arr.every(``function``(x) {``return` `x < 3;``}); ``console.log(arr3); ``// false

14、some()

some():判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true。

var` `arr = [1, 2, 3, 4, 5];``var` `arr2 = arr.some(``function``(x) {``return` `x < 3;``}); ``console.log(arr2); ``//true``var` `arr3 = arr.some(``function``(x) {``return` `x < 1;``}); ``console.log(arr3); ``// false

15、reduce()和 reduceRight()

这两个方法都会实现迭代数组的所有项,然后构建一个最终返回的值。reduce()方法从数组的第一项开始,逐个遍历到最后。而 reduceRight()则从数组的最后一项开始,向前遍历到第一项。

这两个方法都接收两个参数:一个在每一项上调用的函数和(可选的)作为归并基础的初始值。

传给 reduce()和 reduceRight()的函数接收 4 个参数:前一个值、当前值、项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数就是数组的第二项。

下面代码用reduce()实现数组求和,数组一开始加了一个初始值10。

var` `values = [1,2,3,4,5];``var` `sum = values.reduceRight(``function``(prev, cur, index, array){``return` `prev + cur;``},10);``console.log(sum); ``//25

18 arr.indexOf() 查找某个元素的索引值,若有重复的,则返回第一个查到的索引值若不存在,则返回 -1

let arr = [1,2,3,4,5,2]
let arr1 = arr.indexOf(2)
console.log(arr1)  // 1
let arr2 = arr.indexOf(9)
console.log(arr2)  // -1

19 arr.lastIndexOf() 和arr.indexOf()的功能一样,不同的是从后往前查找

let arr = [1,2,3,4,5,2]let arr1 = arr.lastIndexOf(2)console.log(arr1)  // 5let arr2 = arr.lastIndexOf(9)console.log(arr2)  // -1

*20 Array.from() 将伪数组变成数组,就是只要有length的就可以转成数组。 —es6*

let str = '12345'console.log(Array.from(str))    // ["1", "2", "3", "4", "5"]let obj = {0:'a',1:'b',length:2}console.log(Array.from(obj))   // ["a", "b"]

21 Array.of() 将一组值转换成数组,类似于声明数组 —es6

let str = '11'console.log(Array.of(str))   // ['11']

等价于

console.log(new Array('11'))  // ['11]

ps:

但是new Array()有缺点,就是参数问题引起的重载

console.log(new Array(2))   //[empty × 2]  是个空数组console.log(Array.of(2))    // [2]

22 arr.copyWithin() 在当前数组内部,将制定位置的数组复制到其他位置,会覆盖原数组项,返回当前数组

参数: target --必选 索引从该位置开始替换数组项

start --可选 索引从该位置开始读取数组项,默认为0.如果为负值,则从右往左读。

end --可选 索引到该位置停止读取的数组项,默认是Array.length,如果是负值,表示倒数

[复制代码](javascript:void(0)😉

复制代码

let arr = [1,2,3,4,5,6,7]
let arr1 = arr.copyWithin(1)
console.log(arr1)   // [1, 1, 2, 3, 4, 5, 6]
let arr2 = arr.copyWithin(1,2)
console.log(arr2)   // [1, 3, 4, 5, 6, 7, 7]
let arr3 = arr.copyWithin(1,2,4)
console.log(arr3)   // [1, 3, 4, 4, 5, 6, 7]

复制代码

[复制代码](javascript:void(0)😉

23 arr.find(callback) 找到第一个符合条件的数组成员

let arr = [1,2,3,4,5,2,4]
let arr1 = arr.find((value, index, array) =>value > 2)
console.log(arr1)   // 3

24 arr.findIndex(callback) 找到第一个符合条件的数组成员的索引值

let arr = [1,2,3,4,5]
let arr1 = arr.findIndex((value, index, array) => value > 3)
console.log(arr1)  // 3

25 arr.fill(target, start, end) 使用给定的值,填充一个数组,ps:填充完后会改变原数组

参数: target – 待填充的元素

start – 开始填充的位置-索引

end – 终止填充的位置-索引(不包括该位置)

[复制代码](javascript:void(0)😉

复制代码

let arr = [1,2,3,4,5]
let arr1 = arr.fill(5)
console.log(arr1)  // [5, 5, 5, 5, 5]
console.log(arr)   // [5, 5, 5, 5, 5]
let arr2 = arr.fill(5,2)
console.log(arr2)
let arr3 = arr.fill(5,1,3)
console.log(arr3)

复制代码

[复制代码](javascript:void(0)😉

26 arr.includes() 判断数中是否包含给定的值

[复制代码](javascript:void(0)😉

复制代码

let arr = [1,2,3,4,5]
let arr1 = arr.includes(2)  
console.log(arr1)   // ture
let arr2 = arr.includes(9) 
console.log(arr2)    // false
let arr3 = [1,2,3,NaN].includes(NaN)
console.log(arr3)  // true

复制代码

[复制代码](javascript:void(0)😉

ps:与indexOf()的区别:

1 indexOf()返回的是数值,而includes()返回的是布尔值

2 indexOf() 不能判断NaN,返回为-1 ,includes()则可以判断

27 arr.keys() 遍历数组的键名

let arr = [1,2,3,4]
let arr2 = arr.keys()
for (let key of arr2) {
    console.log(key);   // 0,1,2,3
}

28 arr.values() 遍历数组键值

let arr = [1,2,3,4]
let arr1 = arr.values()
for (let val of arr1) {
     console.log(val);   // 1,2,3,4
}

29 arr.entries() 遍历数组的键名和键值

let arr = [1,2,3,4]
let arr1 = arr.entries()
for (let e of arr1) {
    console.log(e);   // 1,2,3,4
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值