2. 盒模型有几种?有什么特点
content-box
:这是默认样式指定CSS标准。测量width和height属性只包括的内容,但不是border, margin, 或者 padding。
border-box
:width和height属性包括padding和border,但不是margin。这是盒模
3.undefined与null的区别
undefined
和null
在if语句中,都会被自动转为false,相等运算符甚至直接报告两者相等。
if (!undefined)
console.log('undefined is false');
// undefined is false
if (!null)
console.log('null is false');
// null is false
undefined == null
// true
4. 宏任务和微任务
答: js作为单线程的运行机制,必定有自己的运行顺序,在听了一次分享后,也好奇这种运行的机制到底是什么?
js可分为同步任务和异步任务,对于同步的任务,我们当然知道按照顺序进行执行,但是对于异步的操作,会有一个优先级的执行顺序,分别为宏任务和微任务
宏任务(macrotasks)和微任务(microtasks)??包含什么?
宏任务一般是:包括整体代码script
,setTimeout
,setInterval
、I/O
、UI render
。
微任务主要是:Promise
、Object.observe
、MutationObserver
。
-
宏任务和微任务之间的关系
1.Promise在前,setTimeout在后
new Promise((resolve) => {
console.log('外层宏事件2');
resolve()
}).then(() => {
console.log('微事件1');
}).then(()=>{
console.log('微事件2')
})
console.log('外层宏事件1');
setTimeout(() => {
//执行后 回调一个宏事件
console.log('内层宏事件3')
}, 0)
结果:
外层宏事件2
外层宏事件1
微事件1
微事件2
内层宏事件3
2.setTimeout在前,Promise在后
setTimeout(() => {
//执行后 回调一个宏事件
console.log('内层宏事件3')
}, 0)
console.log('外层宏事件1');
new Promise((resolve) => {
console.log('外层宏事件2');
resolve()
}).then(() => {
console.log('微事件1');
}).then(()=>{
console.log('微事件2')
})
结果:
外层宏事件1
外层宏事件2
微事件1
微事件2
内层宏事件3
-
事件循环
上图解释:
- 同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数
- 当指定的事情完成时,Event Table会将这个函数移入Event Queue
- 当栈中的代码执行完毕,执行栈(call stack)中的任务为空时,就会读取任务队列(Event quene)中的事件,去执行对应的回调
- 如此循环,形成js的事件循环机制(Event Loop)
5. 浏览器输入网址到显示经历了哪些过程
- 输入网址
- 域名解析(浏览器解析URL获取协议,主机,端口,path)
- 浏览器自身缓存(chrome://net-internals/#dns)
- 操作系统自身的dns缓存
- 读取本地的host文件
- 浏览器发起一个DNS的系统调用(本地主控DNS服务器:宽带运营商服务器查看本身缓存)
- 运营商服务器发起一个迭代DNS解析的请求(->根域.com服务器->imooc.com域服务器->运营商服务器得到(结果)->操作系统内核并缓存->浏览器)
- 浏览器与服务器的web程序tcp链接->三次握手
- 发送http请求
- 服务器处理请求,并将结果返回
- 浏览器根据返回结果进行处理或页面渲染
6. webpack热更新原理
核心就是客户端从服务端拉取更新后的文件,进行一个替换;
实际上 WDS 与浏览器之间维护了一个 Websocket,当本地资源发生变化时,WDS 会向浏览器推送更新,并带上构建时的 hash,让客户端与上一次资源进行对比。客户端对比出差异后会向 WDS 发起 Ajax 请求来获取更改内容(文件列表、hash),这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该chunk的增量更新。
8.event对象中 target和currentTarget 属性的区别。
- event.target返回触发事件的元素
- event.currentTarget返回绑定事件的元素
<ul id="ul">ul
<li>li<a href="">a</a></li>
<li>li<a href="">b</a></li>
<li>li<a href="">c</a></li>
</ul>
var ul = document.getElementById("ul");
ul.onclick = function(event){
var tar = event.target;
console.log(tar);
var tagName = tar.innerText;
console.log("你点击了:"+tagName);
var currentTarget = event.currentTarget;
console.log(currentTarget);
var currentName = currentTarget.innerText;
console.log("你点击了:"+currentName);
// js中的preventDefault()
// 该方法将通知 Web 浏览器不要执行与事件关联的默认动作(如果存在这样的动作),比如阻止表单提交,阻止链接跳转。
event.preventDefault();
}
9.跨域jsonp优缺点
10.vue中data为什么不是一个对象而是一个函数
为什么组件的 data 是一个回调函数
组件就是一个 vue 实例。在 js 中,实例是通过构造函数 new 出来的,每个实例都会继承原型上的方法和属性。
- 组件的 data 若使用对象:对象是内存地址的引用,直接使用对象的话组件之间的 data 都会指向同一个内存地址,会造成组件之间数据的相互影响。
- 组件的 data 使用函数:在 vue 源码中可以看到,若 typeof data === 'function' 则使用的是 getData() 函数,该函数内部通过 call 方法把 this 指向 vm 实例本身。
11. vue双向绑定
Vue是采用数据劫持结合发布/订阅模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
个人理解:在new Vue的时候,在Observer中通过Object.defineProperty()达到数据劫持,代理所有数据的getter和setter属性,在每次触发setter的时候,都会通过(订阅器)Dep来通知Watcher,Watcher作为Observer数据监听器与Compile模板解析器之间的桥梁,当Observer监听到数据发生改变的时候,通过Updater来通知Compile更新视图
而Compile通过Watcher订阅对应数据,绑定更新函数,通过Dep来添加订阅者,达到双向绑定
12. vue的created和mounted的区别
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
13.JS中数据类型分为两类: 基本数据类型 + 引用数据类型
1.基本数据类型 ----- 直接在栈内存中保存数据值,按值访问。
有5种:String字符串、Number数字、 Boolean布尔值、Undefined、Null
当copy数据时,copy到的是数据值本身。基本数据类型的变量与变量之间是独立存在,修改其中一个变量,不会影响其他变量
例:var A = ‘abc’;
B = A;
A = ‘abcd’
则修改变量A的值后,变量B的值不会被修改,仍为'abc'。
2.引用数据类型 ----- 变量保存的是内存地址(对象的引用),访问时访问的也是内存地址(相当于指针,在各自的内存地址里存储了数据)
Object对象
当copy数据时,copy到的是保存数据的内存地址而不是数据值本身。当两个变量保存的是同一个引用数据对象,则其中一个变量的属性发生改变,另一个变量也会随之变化。
例:var A = {name: 'wangxiaoming', age: 19};
B = A;
则变量B其实copy到的是变量A的内存地址;此时修改A的属性为:A.name = 'Tom',其实修改的是变量A保存的内存地址中的内容,所以变量B也被影响---{name: 'Tom', age: 19}。
14.HTTP与HTTPS有什么区别?
HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
15. export和export default区别
export的使用
1.直接输出
export let words = 'hello world!!!'
export function output() {
// ...
}
2.先定义再输出
let firstWords = 'hello'
let secondWords = 'world'
let thirdWords = '!!!'
function output() {
// ...
}
export {firstWords, secondWords, thirdWords, output}
export default的使用
1.export default 用于规定模块的默认对外接口
2.很显然默认对外接口只能有一个,所以 export default 在同一个模块中只能出现一次
3.export default只能直接输出,不能先定义再输出。
4.其在 import 方式上也和 export 存在一定区别
(1)export的输出与import输入
export function output() {
// ...
}
import {output} from './example'
(2)export default的输出与import输入
export default function output() {
// ...
}
import output from './example'
从以上两种 import 方式即可看出,export default 的 import 方式不需要使用大括号包裹。因为对于 export default 其输出的本来就只有一个接口,提供的是模块的默认接口,自然不需要使用大括号包裹。
1. 必考:受控组件 V.S. 非受控组件
```
<FInput value={x} onChange={fn}/> 受控组件
<FInput defaultValue={x} ref={input}/> 非受控组件
```
区别受控组件的状态由开发者维护,非受控组件的状态由组件自身维护(不受开发者控制)
2. 必考:React 有哪些生命周期函数?分别有什么用?(Ajax 请求放在哪个阶段?)
答题思路跟 Vue 的一样
1. 钩子在[文档](https://react.docschina.org/docs/state-and-lifecycle.html "null")里,蓝色框框里面的都是生命周期钩子
2. 把名字翻译一遍就是满分
3. 要特别说明哪个钩子里请求数据,[答案是 componentDidMount](https://segmentfault.com/q/1010000008133309 "null")
3. 必考:React 如何实现组件间通信?
1. 父子靠 props 传函数
2. 爷孙可以穿两次 props
3. 任意组件用 Redux(也可以自己写一个 eventBus)
4. 必考:shouldComponentUpdate 有什么用?
1. 要点:用于在没有必要更新 UI 的时候返回 false,以提高渲染性能
2. 参考:[http://taobaofed.org/blog/2016/08/12/optimized-react-components/](http://taobaofed.org/blog/2016/08/12/optimized-react-components/ "null")
- 必考:虚拟 DOM 是什么?
- 要点:虚拟 DOM 就是用来模拟 DOM 的一个对象,这个对象拥有一些重要属性,并且更新 UI 主要就是通过对比(DIFF)旧的虚拟 DOM 树 和新的虚拟 DOM 树的区别完成的。
- 参考:http://www.alloyteam.com/2015/10/react-virtual-analysis-of-the-dom/
6. 必考:什么是高阶组件?
1. 要点:[文档原话](https://react.docschina.org/docs/higher-order-components.html "null")——高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件。
2. 举例:React-Redux 里 [connect 就是一个高阶组件](https://react-redux.js.org/api/connect "null"),比如 `connect(mapState)(MyComponent)` 接受组件 MyComponent,返回一个具有状态的新 MyComponent 组件。
7. React diff 的原理是什么?
看你记忆力了:[https://imweb.io/topic/579e33d693d9938132cc8d94](https://imweb.io/topic/579e33d693d9938132cc8d94 "null")
8. 必考 Redux 是什么?
1. 背下文档第一句:Redux 是 JavaScript 状态容器,提供可预测化的状态管理。重点是『状态管理』。
2. 说出核心概念的名字和作用:Action/Reducer/Store/单向数据流
3. 说出常用 API:store.dispatch(action)/store.getState()
9. connect 的原理是什么?
react-redux 库提供的一个 API,connect 的作用是让你把组件和store连接起来,产生一个新的组件(connect 是高阶组件)
参考:[https://segmentfault.com/a/1190000017064759](https://segmentfault.com/a/1190000017064759 "null")
10. React/Vue 项目时为什么要在组件中写 key,其作用是什么?
key 的作用是为了在 diff 算法执行时更快的找到对应的节点,提高 diff 速度。
key值:用于 管理可复用的元素,标识数据的唯一性。因为Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染
key的作用主要是为了高效的更新虚拟DOM
11.new一个对象的过程
- 创建一个空对象
- 将所创建对象的
__proto__
属性值设为构造函数的prototype
的属性值 - 执行构造函数中的代码,构造函数中的this指向该对象
- 返回对象
12. useEffect第二个参数不能是引用类型
useEffect接受两个参数:
- 第一个参数是函数(这里叫effect函数),它的作用是,在页面渲染后执行这个函数。因此你可以把ajax请求等放在这里执行;
- 第二个参数是一个数组,这里注意:
参数情况 | 效果 | 注意 |
---|---|---|
不传 | 每次渲染后都执行清理或者执行effect | 这可能会导致性能问题,比如两次渲染的数据完全一样 |
传空数组 | 只运行一次的 effect(仅在组件挂载和卸载时执行) | 这就告诉 React 你的 effect 不依赖于 props 或 state 中的任何值,所以它永远都不需要重复执行 |
传[count] | React 将对前一次渲染的count和后一次渲染的count进行比较。若相等React 会跳过这个 effect, | 实现了性能的优化 |
上面例子中之所以造成页面的死循环,是因为在JavaScript中,{} === {}结果是false,{a:1} === {a:1}同样,由此造成了react以为两个值不同,就一直的渲染最终页面死循环。
13. setState同步和异步
- setState只是在合成事件和生命周期函数中是异步更新
- 在settimeout、原生事件、async函数中是同步更新。
14.Taro 设计思想及架构
在 Taro 中采用的是编译原理的思想,所谓编译原理,就是一个对输入的源代码进行语法分析,语法树构建,随后对语法树进行转换操作再解析生成目标代码的过程。
15.typescript中interface和type的区别
interface 可以而 type 不行
interface 能够声明合并
interface User {
name: string
age: number
}
interface User {
sex: string
}
/*
User 接口为 {
name: string
age: number
sex: string
}
*/
type 可以而 interface 不行
type 可以声明基本类型别名,联合类型,元组等类型
// 基本类型别名
type Name = string
// 联合类型
interface Dog {
wong();
}
interface Cat {
miao();
}
type Pet = Dog | Cat
// 具体定义数组每个位置的类型
type PetList = [Dog, Pet]
16.html5有哪些新特性
一、绘画 canvas
二、用于媒介回放的video和audio元素
三、本地离线存储localStorage长期存储数据,浏览器关闭后数据不丢失
四、sessionStorage的数据在浏览器关闭后自动删除
五、语意化更好的内容元素,比如 article、footer、header、nav、section
六、表单控件,calendar、date、time、email、url、search
七、新的技术webworker, websocket, Geolocation
17.前端模块化的理解
将原本一个复杂的程序按功能模块等形式进行代码拆分,在不同部分的内部仅暴露接口(方法),在主程序中进行调用和组合,称为前端模块化,其优势是减少代码耦合度,提高运行效率,降低维护难度,减少代码和提高复用性
模块化规范
- CommonJS
- AMD
- UMD
- CMD
- Module(es6)
19.手写Promise
class Commitment {
static pending = '待定';
static fulfilled = '成功';
static rejected = '失败'
constructor(func) {
this.status = Commitment.pending;
this.result = null;
this.resolveCallbacks = []
this.rejectCallbacks = []
try {
func(this.resolve.bind(this), this.resolve.bind(this))
} catch (error) {
this.reject(error)
}
}
resolve(result) {
setTimeout(()=> { // 先等 setTimeout 里面的异步操作完后再 resolve
if (this.status === Commitment.pending) {
this.status = Commitment.fulfilled;
this.result = result;
this.resolveCallbacks.forEach((callback) => {
callback(result);
})
}
})
}
reject(result) {
setTimeout(()=> {
if (this.status === Commitment.pending) {
this.status = Commitment.rejected;
this.result = result;
this.rejectCallbacks.forEach((callback) => {
callback(result);
})
}
})
}
then(onFulfilled, onRejected) {
return new Commitment((resolve, reject) => {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
onRejected = typeof onRejected === 'function' ? onRejected : () => {};
if (this.status === Commitment.pending) { // 保存异步操作后,then的回调
this.resolveCallbacks.push(onFulfilled)
this.rejectCallbacks.push(onRejected)
}
if (this.status === Commitment.fulfilled) {
setTimeout(()=> {
onFulfilled(this.result)
})
}
if (this.status === Commitment.rejected) {
setTimeout(()=> {
onRejected(this.result)
})
}
})
}
}
// 使用
let com = new Commitment((resolve, reject)=> {
setTimeout(()=> {
resolve('这次一定')
reject('下次一定')
})
})
com.then((res)=> {
console.log(res)
}, (err)=> {
console.log(err)
})
20.react的生命周期
挂载
componentWillMount,render,componentDidMount
更新
shouldComponentUpdate,componentWillUpdate,render,componentDidUpdate
21. # js判断数据类型
1: typeof
2:toString 这个是最完美的
oString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。
对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
22.Vuex刷新页面数据丢失问题解决思路
因为vuex里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,vuex里面的数据就会被重新赋值。
23.react hooks的闭包陷阱
react hooks在渲染的时候维护了一个链表, 来记录useState和useEffect的位置和值。(这也是state不能使用if else的原因, 因为可能会导致链表中state useEffect的顺序错乱, 从而不能获取到正确的数值)
24. require和import的区别
- 原生浏览器不支持 require/exports,可使用支持 CommonJS 模块规范的 Browsersify、webpack 等打包工具,它们会将 require/exports 转换成能在浏览器使用的代码。
- import/export 在浏览器中无法直接使用,我们需要在引入模块的 <script> 元素上添加type="module" 属性。
- require/exports 是运行时动态加载,import/export 是静态编译
CommonJS 加载的是一个对象(即 module.exports 属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
-
require/exports
输出的是一个值的拷贝,import/export
模块输出的是值的引用
26. js设计模式
一. 单例模式
定义:保证一个类仅有一个实例,并且提供一个可以访问它的访问点
实现:用一个变量来标识实例是否已经存在,如果存在,则直接返回已经创建好的实例,反之就创建一个对象
三. 工厂模式
定义:不暴露创建对象的具体逻辑,而是将将逻辑封装在一个函数中,这个函数被视为一个工厂
分类:简单工厂,工厂方法,抽象工厂
区别:简单工厂是将创建对象的步骤放在父类进行,工厂方法是延迟到子类中进行,它们两者都可以总结为:“根据传入的字符串来选择对应的类”,而抽象工厂则是:“用第一个字符串选择父类,再用第二个字符串选择子类”