前端面试题三
ES6新特性有哪些?
- 变量声明:由var变为let和const;
- 模板字符串:使用反引号 `` ;在模板字符串里面支持换行,并可以在里面使用${}来包裹一个变量或表达式;
- 解构赋值:有数组解构和对象解构,可以快速获取数组和对象的值;
- 扩展运算符:在ES6中用...来表示展开运算符,它可以将数组或者对象进行展开;
- 箭头函数:函数的快捷写法,不需要通过function关键字创建函数,并且可以省略return关键字,但函数体内的this对象指的是定义时所在的对象,而不是使用时所在的对象; 化简规则: Function 变成 =>; 只有1个参数可以省略小括号; 没有参数或者有多个参数不能省略小括号; 函数体内只有一行可以省略大括号,如果有返回值return,则return也要省略; 函数体内有多行,不能省略大括号;
- 对象的简化赋值:对象赋值时如果属性名和变量名一致可以简写
- 类的支持:ES6中添加了对类的支持,引入了class关键字。JS本身就是面向对象,ES6中提供的类实际上只是JS原型模式包装。现在有了class,对象的创建,继承更直观,父类方法的调用,实例化,静态方法和构造函数更加形象化。
JavaScript 中,如何判断两个对象是否相等?
两个Object类型对象,即使拥有相同属性、相同值,当使用 == 或 === 进行比较时,也不认为他们相等。这就是因为他们是通过引用(内存里的位置)比较的,不像基本类型是通过值比较的。
```js //浅拷贝指向同一内存的时候,此时两个对象相等。 var obj1 = { name: "xiaoming", age: "18" };
var obj2 = { name: "xiaoming", age: "18" };
var obj3 = obj1;
console.log(obj1 === obj3); // true
console.log(obj2 === obj3); // false ```
说说你对promise的理解
Promise的含义:
promise是异步编程的一种解决方法。 所谓promise,简单说是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果,从语法上说,promise是一个对象,从它可以获取异步操作的消息,promise提供了统一的API,各种异步操作都可以用同样的方法进行处理。
Promise对象的特点:
(1)对象的状态不受外界影响,promise对象代表一个异步操作,有三种状态,pending(进行中)、fulfilled(已成功)、rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,这也是promise这个名字的由来“承若”; (2)一旦状态改变就不会再变,任何时候都可以得到这个结果,promise对象的状态改变,只有两种可能:从pending变为fulfilled,从pending变为rejected。这时就称为resolved(已定型)。如果改变已经发生了,你再对promise对象添加回调函数,也会立即得到这个结果,这与事件(event)完全不同,事件的特点是:如果你错过了它,再去监听是得不到结果的。
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。
Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
Promise的用法:
是一个构造函数,这个构造函数里有两个参数,分别是:resolve(成功之后的回调函数)、reject(失败之后的回调函数)。
因为promise表示的是一个异步操作,每当我们new一个promise实例,就表示一个具体的异步操作,那么这个异步操作的结果就只能有两种状态:成功/失败,两者都需要回调函数resolve/reject返回。所以内部拿到操作的结果后,无法使用return把操作结果返回给调用者,这时候只能用回调函数的形式来把成功或失败的结果返回给调用者。
vue中watch和computed区别
监听属性watch - 不支持缓存,数据变,会直接触发相应的操作; - watch支持异步; - 监听数据必须是data中声明过或者父组件传递过来的props中的数据。
计算属性computed - 支持缓存,只有依赖数据发生改变,才会重新进行计算; - 不支持异步,当computed内有异步操作时无效,无法监听数据的变化; - computed属性值会默认走缓存,计算属性是基于他们的相应依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值。
Vue-router 中hash模式和history模式的区别
外观:
hash模式url带#号,history模式不带#号。
功能: hash模式url里面永远带着#号,开发当中默认使用这个模式。如果用户考虑url的规范那么就需要使用history模式,因为history模式没有#号,是个正常的url,适合推广宣传; 比如我们在开发app的时候有分享页面,那么这个分享出去的页面就是用vue或是react做的,咱们把这个页面分享到第三方的app里,有的app里面url是不允许带有#号的,所以要将#号去除那么就要使用history模式,但是使用history模式还有一个问题就是,在访问二级页面的时候,做刷新操作,会出现404错误,那么就需要和后端人配合,让他配置一下apache或是nginx的url重定向,重定向到你的首页路由上就ok了。
Vuex的相关知识
Vue生命周期
beforeCreate
实例初始化之后,this指向创建的实例,不能访问到data、computed、watch、methods上的方法和数据,常用于初始化非响应式变量。
created
实例创建完成,可访问data、computed、watch、methods上的方法和数据,未挂载到DOM,不能访问到$el属性,$ref属性内容为空数组,常用于简单的ajax请求,页面的初始化。
beforeMount
在挂载开始之前被调用,beforeMount之前,会找到对应的template,并编译成render函数。
mounted
实例挂载到DOM上,此时可以通过DOM API获取到DOM节点,$ref属性可以访问 常用于获取VNode信息和操作,ajax请求。
beforeupdate
响应式数据更新时调用,发生在虚拟DOM打补丁之前,适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器。
updated
虚拟 DOM 重新渲染和打补丁之后调用,组件DOM已经更新,可执行依赖于DOM的操作,避免在这个钩子函数中操作数据,可能陷入死循环。 beforeDestroy
实例销毁之前调用。这一步,实例仍然完全可用,this仍能获取到实例,常用于销毁定时器、解绑全局事件、销毁插件对象等操作。
destroyed
实例销毁后调用,调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
理解vue的单向数据流
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
这里有两种常见的试图改变一个 prop 的情形:
这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:
js props: ['initialCounter'], data: function () { return { counter: this.initialCounter } }
这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:
js props: ['size'], computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } }
注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。
js props: { list: { type: Array, default: (() => []) } }, methods: { addFn () { this.list.push('newValue') } }
单向数据流:父级 prop 的更新会向下流动到子组件中,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。