又是一年金三银四,今年做了些面试的准备,收集了些面试题,有的是自己面试遇到的,有的是网上看到的,分享出来,如有错误,欢迎指出。
JavaScript 数据类型有哪些
- 空类型:null、undefined;
- 值类型(基本类型):string、number、boolean、symbol;
- 引用类型:object、function、array; 值类型存在在栈中;引用类型地址存在栈中,值存在堆中,调用的时候传的是地址值,null与之类似。
Symbol生成一个全局唯一的值。
const symbol1 = Symbol();
const symbol2 = Symbol(42);
const symbol3 = Symbol('foo');
console.log(typeof symbol1);
// expected output: "symbol"
console.log(symbol3.toString());
// expected output: "Symbol(foo)"
console.log(Symbol('foo') === Symbol('foo'));
// expected output: false
基本数据类型和引用数据类型区别
很自然地就引出这个题,基本数据类型在被创建时,在栈上给其划分一块内存,将数值直接存储在栈上;引用数据类型在被创建时,首先在栈上创建一个引用,而对象的具体内容都存储在堆内存上,然后由栈上面的引用指向堆中对象的地址。
基本数据类型和引用数据类型拷贝的时候有什么区别?
由于存储的位置不一样,直接拷贝的时候就会有两种情况:拷贝了值和拷贝了引用,也就是我们常说的深浅拷贝。
对于基本数据类型而言,没有深浅拷贝的概念,都是在栈上新开辟了一块内存给新的值。而对于引用数据类型而言,区别简单来说就是会不会共享堆内存里的值
冒泡和捕获
stopPropagation()和preventDefault()。
- js冒泡和捕获是事件的两种行为,使用event.stopPropagation()起到阻止捕获或冒泡阶段中当前事件的进一步传播先捕获再冒泡。
- element.addEventListener(event, function, useCapture)
- 第一个参数是需要绑定的事件;
- 第二个参数是触发事件后要执行的函数;
- 第三个参数默认值是false,表示在事件冒泡阶段调用事件处理函数;如果参数为true,则表示在事件捕获阶段调用处理函数。
- 首先发生的事件捕获,为截获事件提供了机会。然后是实际的目标接收了事件。最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应。 segmentfault.com/a/119000001…
- 使用event.preventDefault()可以取消默认事件。
- 元素必须有默认行为才能被取消,如果元素本身就没有默认行为,调用当然就无效了。什么元素有默认行为呢?如链接
<a>,提交按钮<input type=”submit”>等。当Event 对象的 cancelable为false时,表示没有默认行为,这时即使有默认行为,调用preventDefault也是不会起作用的。
slice、splice、split区别
- slice
- slice(切片):截取数组,返回截取到的新数组,不改变原有数组
arr.slice(start,end);- start:必需,从原数组的start位置开始截取(包括下标为start的元素)。start为负数,表示从尾部开始截取。如-1表示最后一个元素,-2表示倒数第二个元素
- end:可选,截取到的指定位置(不包括下标为end的元素)。没有指定,则截取到最后一个元素。end要大于start,否则截取不到元素 blog.csdn.net/tangxiujian…
- splice
- splice(拼接):从数组中添加、删除元素,改变原有数组,返回被删除的元素
arr.splice(index,howmany,item1...itemx);- index:必需,整数,添加/删除数据的位置
- howmany:必需,整数,添加/删除数据的数量。设置为0则不会删除
- item1...itemx:向数组添加的新数据
- split
- split(分离):用于把一个字符串切割为字符串数组,返回新的字符串数组,每个变量用”,“分隔,源字符串不改变
stringObject.split(seperator,howmany);- seperator:必需,
var str = ''how are?;
console.log(str.split('')); //h,o,w,a,r,e,? ( seperator = '',则把每个字符都分割)
console.log(str.split(' '));//how,are?
console.log(str.split(' ',1));//how
说下 JS 中的事件循环
- JavaScript是单线程,非阻塞的
- 非阻塞:通过 event loop 实现
- 执行栈: 同步代码的执行,按照顺序添加到执行栈中
- 事件队列: 异步代码的执行,遇到异步事件不会等待它返回结果,而是将这个事件挂起,继续执行执行栈中的其他任务。当异步事件返回结果,将它放到事件队列中,被放入事件队列不会立刻执行起回调,而是等待当前执行栈中所有任务都执行完毕,主线程空闲状态,主线程会去查找事件队列中是否有任务,如果有,则取出排在第一位的事件,并把这个事件对应的回调放到执行栈中,然后执行其中的同步代码。
- 异步任务的返回结果会被放到一个任务队列中,根据异步事件的类型,这个事件实际上会被放到对应的宏任务和微任务队列中去。
- 在当前执行栈为空时,主线程会查看微任务队列是否有事件存在
- 存在,依次执行队列中的事件对应的回调,直到微任务队列为空,然后去宏任务队列中取出最前面的事件,把当前的回调加到当前执行栈。
- 如果不存在,那么再去宏任务队列中取出一个事件并把对应的回到加入当前执行栈;
- 当前执行栈执行完毕后时会立刻处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。
宏任务/微任务
- 在当前的微任务没有执行完成时,是不会执行下一个宏任务的。
- 微任务列表是先进先出,先进入的,就先执行。
Promise.all和Promise.race
-
Promise.all可以将多个Promise实例包装成一个新的Promise实例。 -
成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。
-
Promse.all在处理多个异步处理时非常有用,比如说一个页面上需要等两个或多个ajax的数据回来以后才正常显示,在此之前只显示loading图标。
-
Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。 -
Promise.race可以用来在有最大请求数量限制时,用来实现大量请求的队列发起
-
用于和定时器绑定,可以测试一些接口的响应速度,分析用户的网络状况之类的,比如将一个请求,和三秒后执行定时器 包装成promise 实例,然后加入 promise.race队列中, 当请求三秒还未响应时候,可以给用户一些提示, 或者是一些其他操作
实现debounce
call、apply、bind使用和区别
call ,aply , bind的区别,都是改变函数内部this的指向, call接受参数列表,apply接受一个参数数组,bind返回的是一个函数,必须再调用bind(s)()
输入url后发生了什么
- 缓存解析(浏览器缓存-系统缓存-路由器缓存)
- 域名解析(又称DNS解析:域名到IP地址的转换过程)
- TCP连接,三次握手
- 客户端向服务器发送连接请求报文;
- 服务器端接受客户端发送的连接请求后后回复ACK报文,并为这次连接分配资源。
- 客户端接收到ACK报文后也向服务器端发生ACK报文,并分配资源。 这样TCP连接就建立了。 在此之后,浏览器开始向服务器发送http请求,请求数据包。请求信息包含一个头部和一个请求体。
- 服务器收到请求
- 服务器收到浏览器发送的请求信息,返回一个响应头和一个响应体。
- 页面渲染
- 浏览器收到服务器发送的响应头和响应体,进行客户端渲染,生成Dom树、解析css样式、js交互。
用户访问网站的过程(缓存,DNS查询,建立链接,请求,响应,收到页面,解析DOM树,显示内容,首屏加载完成,可交互)
css预处理器特性
嵌套、变量、函数、混合(Mixins)、模块化
ES6
- 新特性:let、const、箭头函数、symbols、接口、枚举、范型T
- ES6 声明变量的六种方法:var、let、const、import、function、class
- const
- const定义的:基本类型常量不可变,引用类型常量可以变;
- const 不变的是变量地址,不是值;const 一个 object 依然可以改变里面的属性值;
箭头函数
developer.mozilla.org/zh-CN/docs/…
- 箭头函数不能用作构造器,和 new一起用会抛出错误。
- 箭头函数没有prototype属性。
- this指向
- 写法更简洁
this指向
www.ruanyifeng.com/blog/2018/0…
- 被谁调用就指向谁
- this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象
- this就是函数运行时所在的环境对象
解释一下同步、异步
同步:连续的执行;异步:不连续的执行
怎么实现异步编程
promise\async,await的用法
平时关注过前端的内存处理么
1、内存的生命周期 内存的分配:声明变量、函数、对象的时候,js会自动分配内存; 内存的使用:调用的时候使用; 内存的回收:js的垃圾回收机制 2、js的垃圾回收机制 1、引用计数垃圾回收 2、标记清除算法 3、js中,有哪些常见的内存泄漏: 1、全局变量 2、未被清除的定时器和回调 3、闭包 4、dom的引用 4、如何避免内存泄漏 1、减少不必要的全局变量 2、使用完数据后,及时解除引用
说说浅拷贝、深拷贝以及它们的实现
浅拷贝:Object.assign()
深拷贝:
不能拷贝函数:
let obj2=JSON.parse(JSON.stringify(obj1));
递归赋值;
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
//判断是否为自身属性
if(obj.hasOwnProperty(key)){
//判断ojb子元素是否为对象,如果是,递归复制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
赋值、浅拷贝、深拷贝的区别
- 针对引用类型:基本类型的赋值的两个变量是两个独立相互不影响的变量。引用类型的赋值是传址。
- 赋值,重新在栈内存创建对象,赋的其实是该对象在栈中的地址,也就是两个对象指向同一个存储空间,无论哪个对象发送改变,改的都是存储空间的值,所以两个对象是联动的
- 浅拷贝:重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响。
- 深拷贝:从堆内存中开辟一个新的区域存放新对象,对对象中的子对象进行递归拷贝,拷贝前后的两个对象互不影响。
什么是闭包,闭包的应用场景
- 定义在函数内部的函数
- 闭包优点:读取函数内部的变量,让这些变量一直在内存中;
- 缺点:内存泄漏;解决方式:变量用完不再使用时设为null; 应用场景:
- 设计单例模式(单例模式:创建一次不再创建)
- 设置私有变量
- 设置属性私有化
- 取正确值
实现图片懒加载
<img data-src='img.png' src=''/>
图片出现在可视区域时(图片离可视区域顶部的距离小于可视区域)把data-src的值赋给src
document.documentElement.clientHeight//获取屏幕可视区域的高度
element.offsetTop//获取元素相对于文档顶部的高度
getBoundingClientRect()//获取元素的大小及位置
http状态码
- 1xx: 表示目前是协议处理的中间状态,还需要后续操作。
- 2xx: 表示成功状态。
- 3xx: 重定向状态,资源位置发生变动,需要重新请求。 301永久重定向;302临时重定向
- 4xx: 请求报文有误。
- 5xx: 服务器端发生错误。
浏览器缓存
sessionStorage与localStorage的区别
共同点
都是保存在浏览器端,且同源的,一样都是用来存储客户端临时信息的对象。他们均只能存储字符串类型的对象(虽然规范中可以存储其他原生类型的对象,但是目前为止没有浏览器对其进行实现)。
区别
cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。存储大小限制也不同,cookie数据不能超过4k,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。Web Storage 支持事件通知机制,可以将数据更新的通知发送给监听者。Web Storage 的 api 接口使用更方便。
localStorage生命周期是永久,这意味着除非用户显示在浏览器提供的UI上清除localStorage信息,否则这些信息将永远存在。
sessionStorage生命周期为当前窗口或标签页,一旦窗口或标签页被永久关闭了,那么所有通过sessionStorage存储的数据也就被清空了。
不同浏览器无法共享localStorage或sessionStorage中的信息。相同浏览器的不同页面间可以共享相同的 localStorage(页面属于相同域名和端口),但是不同页面或标签页间无法共享sessionStorage的信息。这里需要注意的是,页面及标 签页仅指顶级窗口,如果一个标签页包含多个iframe标签且他们属于同源页面,那么他们之间是可以共享sessionStorage的。
react\angular\vue组件之间如何通信
- 父组件向子组件通信: props
- 子组件向父组件通信: 回调函数/自定义事件
- 跨级组件通信: 层层组件传递props/context
- 没有嵌套关系组件之间的通信: 自定义事件
redux设计思想及使用场景
一个状态管理工具
mapStateToProps 建立一个 state对象到UI组件的props对象的映射关系
- mapStateToProps函数返回的是一个对象;
- 返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
- mapStateToProps用于传递状态 mapDispatchToProps
- mapDispatchToProps函数返回的是一个对象;
- 返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
- mapDispatchToProps用于传递操作状态的方法 返回一个对象,该对象的每个键值对都是一个映射,定义了 UI 组件的参数怎样发出 Action。
react\angular技术选型www.cnblogs.com/dadifeihong…
解释一下react的虚拟dom和diff算法juejin.im/post/684490…
重绘和回流
回流也叫重排,回流开销大,回流必定引起重绘,重绘不一定回流
前端性能如何优化
- 减少 HTTP 请求;
- 将 CSS 放在文件头部,JavaScript 文件放在底部(eg现在的小程序项目);
- 善用缓存,不重复加载相同的资源;
- 压缩文件;
- 图片延迟加载;
- 减少重绘重排;
- 使用服务端渲染;
- 静态资源使用 CDN
git提交代码的流程
git add .—>git commit -m 'xxx' —>git pull—>git push
interface、type区别
相同点:
- 两者都可以用来描述对象或函数的类型
- 两者都可以实现继承 不同点:
- 扩展语法
// interface使用extends,type使用‘&’
type PartialPointX = { x: number; };
type Point = PartialPointX & { y: number; };
- 同名合并
// interface 支持,type 不支持。
interface Point { x: number; }
interface Point { y: number; }
const point: Point = { x: 1, y: 2 };
- 描述类型:对象、函数两者都适用,但是 type 可以用于基础类型、联合类型、元祖。
- 计算属性:type 支持计算属性,生成映射类型,;interface 不支持。
type DudeType = {
[key in Keys]: string
}
webpack
webpack.wuhaolin.cn/4%E4%BC%98%…
- entry:配置模块的入口
- module:模块
- chunk:代码块
- loader:模块转换器。解析和转换文件,style-loader,css-loader,sacc-loader
- rules:
[
{
// 增加对 SCSS 文件的支持
test: /\.scss$/,
// SCSS 文件的处理顺序为先 sass-loader 再 css-loader 再 style-loader
use: ['style-loader', 'css-loader', 'sass-loader'],
},
]
- plugin:扩展插件
plugins: [
['ice-plugin-fusion', {
themePackage: '@icedesign/theme',
}],
['ice-plugin-moment-locales', {
locales: ['zh-cn'],
}],
],
- output:输出结果。输出文件的名称和位置 filename: '[name].js'
path: path.resolve(_dirname, 'dist[hash]')
- resolve:配置模块对应的文件(告诉webpack怎么去搜索文件)
- resolve:
{
//resolve.alias 配置项通过别名来把原导入路径映射成一个新的导入路径
//把导入语句里的 components 关键字替换成 ./src/components/
alias:{
components: './src/components/'
},
// 使用 alias 把导入 react 的语句换成直接使用单独完整的 react.min.js 文件,
// 减少耗时的递归解析操作
alias: {
'react': path.resolve(__dirname, './node_modules/react/dist/react.min.js'), // react15
// 'react': path.resolve(__dirname, './node_modules/react/umd/react.production.min.js'), // react16
}
//resolve.mainFields 用于配置第三方模块使用哪个入口文件。
//mainFields 的配置去决定优先采用那份代码
mainFields: ['jsnext:main', 'browser', 'main'],
//在导入语句没带文件后缀时,Webpack 会自动带上后缀后去尝试访问文件是否存在。 resolve.extensions 用于配置在尝试过程中用到的后缀列表,
//列表值尽量少
//频率高的文件类型的后缀写在前面
//源码中的导入语句尽可能的写上文件后缀,如require(./data)要写成require(./data.json)
extensions: ['.js', '.json'] ,
// 使用绝对路径指明第三方模块存放的位置,以减少搜索步骤
// 其中 __dirname 表示当前工作目录,也就是项目根目录
modules: [path.resolve(__dirname, 'node_modules')]
//module.noParse字段告诉Webpack不必解析哪些文件,可以用来排除对非模块化库文件的解析
// 独完整的 `react.min.js` 文件就没有采用模块化,忽略对 `react.min.js` 文件的递归解析处理
noParse: [/react\.min\.js$/],
}
webpack优化
juejin.cn/post/684490… juejin.cn/post/684490…
- 优化构建速度 缩小文件的搜索范围 (重视resolve字段的配置;配置loader时,通过test、exclude、include缩小搜索范围)
- 使用DllPlugin减少基础模块编译次数
- 使用HappyPack开启多进程Loader转换
- 使用ParallelUglifyPlugin开启多进程压缩JS文件
-
优化开发体验 使用自动刷新(Webpack监听文件、DevServer刷新浏览器) 开启模块热替换HMR
-
优化输出质量-压缩文件体积 区分环境--减小生产环境代码体积(分为开发环境、生产环境) 压缩代码-JS、ES、CSS
- 压缩JS:Webpack内置UglifyJS插件、ParallelUglifyPlugin
- 压缩ES6:第三方UglifyJS插件
- 压缩CSS:css-loader?minimize、PurifyCSSPlugin
const UglifyJSPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
//...
plugins: [
new UglifyJSPlugin({
compress: {
warnings: false, //删除无用代码时不输出警告
drop_console: true, //删除所有console语句,可以兼容IE
collapse_vars: true, //内嵌已定义但只使用一次的变量
reduce_vars: true, //提取使用多次但没定义的静态值到变量
},
output: {
beautify: false, //最紧凑的输出,不保留空格和制表符
comments: false, //删除所有注释
}
})
]
使用Tree Shaking剔除JS死代码
- 优化输出质量--加速网络请求
- 使用CDN加速静态资源加载
- 多页面应用提取页面间公共代码,以利用缓存
- 分割代码以按需加载
跨域问题
-
CORS
-
JSONP:JSONP主要就是利用了script标签没有跨域限制的这个特性来完成的
-
nginx反向代理
-
Websocket 客户端和服务器之间存在持久的连接,而且双方都可以随时开始发送数据;本质没有使用了 HTTP 的响应头, 因此也没有跨域的限制
-
Nginx 反向代理
-
document.domain + Iframe
-
window.location.hash + Iframe
-
window.postMessage
hooks和class的区别
Hooks的优势
- Hook 使你在无需修改组件结构的情况下复用状态逻辑(自定义hook)
- Hook 将组件中相互关联的部分拆分成更小的函数(比如设置订阅或请求数据),而并非强制按照生命周期划分。
- 类组件难以理解,影响组件预编译,Hook 使你在非 class 的情况下可以使用更多的 React 特性
- getSnapshotBeforeUpdate,componentDidCatch 、 getDerivedStateFromError:只能用class来实现
ts中class和interface的区别
interface -- 接口只声明成员方法,不做实现。 class -- 类声明并实现方法。
伪元素和伪类的区别
伪类和伪元素分别用单冒号 : 和双冒号 :: 来表示。 伪类和伪元素的区别,最关键的点在于如果没有伪元素(或伪类),是否需要添加元素才能达到目的,如果是则是伪元素,反之则是伪类
常见的页面性能优化
HTTP 上有哪些优化手段
移动端有哪些兼容的场景
- 在写手机端时必要需要加入meta
// (width=device-width),
// 初始缩放比例(initial-scale=1)为1.0,即网页初始大小占屏幕面积的100%。
// minimum-scale=1, maximum-scale=1 最大(最小)缩放比例
// user-scalable 是否允许用户缩放。
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
// 删除默认的ios工具栏和菜单栏
<meta name="apple-mobile-web-app-capable" content="yes">
// 在web app应用下状态条(屏幕顶部条)的颜色
<meta name="apple-mobile-web-app-status-bar-style" content="black">
// 禁止了把数字转化为拨号链接
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
- new Date()在IOS上出现值为NAN的问题
原因:因为IOS下的new Date()不支持"-“这个字符
解决方法:把”-“改成‘”/"就可以了。例如
new Date("2017-08-11 12:00:00".replace(/-/g, "/"));
CommonJS、ES6模块requireJs区别
commonJs:
- 对于基本数据类型,属于复制。即会被模块缓存。同时,在另一个模块可以对该模块输出的变量重新赋值。
- 对于复杂数据类型,属于浅拷贝。由于两个模块引用的对象指向同一个内存空间,因此对该模块的值做修改时会影响另一个模块。
- 当使用require命令加载某个模块时,就会运行整个模块的代码。
- 当使用require命令加载同一个模块时,不会再执行该模块,而是取到缓存之中的值。也就是说,CommonJS模块无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非手动清除系统缓存。
- 动态编译,运行时加载 es6模块:
- ES6模块中的值属于【动态只读引用】。
- 对于只读来说,即不允许修改引入变量的值,import的变量是只读的,不论是基本数据类型还是复杂数据类型。当模块遇到import命令时,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
- 对于动态来说,原始值发生变化,import加载的值也会发生变化。不论是基本数据类型还是复杂数据类型。
- 循环加载时,ES6模块是动态引用。只要两个模块之间存在某个引用,代码就能够执行。
- 静态编译,编译时加载 require.js:
- 实现js文件的异步加载,避免网页失去响应;
- 管理模块之间的依赖性,便于代码的编写和维护。
加载外部js文件,可能造成网页失去响应。解决办法有两个,一个是把它放在网页底部加载,另一个是写成下面这样:
<script src="js/require.js" defer async="true" ></script>
async属性表明这个文件需要异步加载,避免网页失去响应。IE不支持这个属性,只支持defer,所以把defer也写上。
编译:将源代码翻译成机器能识别的语言(二进制)
运行:所谓运行时就是代码跑起来了。被装载到内存中去了 www.cnblogs.com/unclekeith/…
怎样理解阻塞非阻塞与同步异步的区别
- 同步和异步关注的是消息通信机制
- 同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。
- 换句话说,就是由调用者主动等待这个调用的结果。
- 异步,则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。
- 阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
- 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
- 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
脏数据检测
双向数据绑定:通过属性绑定与事件绑定实现
history与hash路由的区别
Dom 创建,查找, 删除, 插入,复制
blog.csdn.net/Maci_yera/a… 创建:
document.createElement(“div”);//创建一个div元素,参数需要是标签名;
document.createTextNode(“233”);//创建一个文本节点内容是“233”;
查找
var ul = document.getElementByTagName("ul");
console.log(ul.children);//返回ul子节点li的集合
删除
dom.removeChild(myli); //删除子节点myli
插入
document.body.insertBefore(oDiv,oDiv1);//在oDiv1节点前插入新创建元素节点 末尾
ul.appendChild(ul.firstChild); //把ul的第一个元素节点移到ul子节点的
复制
node.cloneNode(deep);
// 可选。默认是 false。
// 设置为 true,如果您需要克隆节点及其属性,以及后代
// 设置为 false,如果您只需要克隆节点及其后代
// 一般cloneNode(true);
var ul = document.getElementByTagName("ul");
var newul = ul.cloneNode(true);
// 替换
var replaceChild = document.body.replaceChild(div1,div2); //将div1替换div2
js换肤
www.zhangxinxu.com/wordpress/2…
- 一个全局class控制样式切换;
- 改变皮肤link元素的href地址。例如:
<link id="skinLink" href="skin-default.css" rel="stylesheet" type="text/css">
换皮肤的时候JS改变href属性值:
skinLink.href = 'skin-red.css';
- 原生HTML特性下的网站换肤 此方法借助HTML rel属性的alternate属性值实现。
<link href="reset.css" rel="stylesheet" type="text/css">
<link href="default.css" rel="stylesheet" type="text/css" title="默认">
<link href="red.css" rel="alternate stylesheet" type="text/css" title="红色">
<link href="green.css" rel="alternate stylesheet" type="text/css" title="绿色">
上面4个元素,共出现了3中不同性质的CSS样式文件加载:
没有title属性,rel属性值仅仅是stylesheet的无论如何都会加载并渲染,如reset.css;
有title属性,rel属性值仅仅是stylesheet的作为默认样式CSS文件加载并渲染,如default.css;
有title属性,rel属性值同时包含alternate stylesheet的作为备选样式CSS文件加载,默认不渲染,如red.css和green.css; 使用JavaScript代码修改元素DOM对象的disabled值为false,可以让默认不渲染的CSS开始渲染。注意,必须是DOM元素对象的disabled属性,而不是HTML元素的disabled属性,元素是没有disabled属性的。 // 渲染red.css这个皮肤
document.querySelector('link[href="red.css"]').disabled = false;
要实现换肤功能,只要在页面上方几个换肤按钮,点击的时候改变对应元素DOM对象的disabled值就可以了。
弹性盒子中 flex: 0 1 auto 表示什么意思
三个参数分别对应的是 flex-grow, flex-shrink 和 flex-basis,默认值为0 1 auto。
- flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
- flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
- flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。
- flex-grow: 扩张比率,只有当子集宽度合计小于父级宽度(需要子集扩张)时才看这个值,默认为0,即如果存在剩余空间,也不放大。
- flex-shrink:收缩比率,只有当子集宽度合计大于父级宽度(需要子集收缩)时才看这个值,默认为1,即如果空间不足,该项目将缩小。
- flex-base:项目长度,可以自动计算,继承,和设置具体的长度值; github.com/Advanced-Fr…
useMemo和useCallback
useMemo(() => computeExpensiveValue(a, b), [a, b])
- 返回一个 memoized 值。
- 仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。
- 如果没有提供依赖项数组,useMemo 在每次渲染时都会计算新的值。
useCallback(fn, deps)相当于useMemo(() => fn, deps)- useCallback用来缓存函数,useMemo用来缓存计算结果
- 在 React 组件中执行过数据获取、订阅或者手动修改过 DOM。我们统一把这些操作称为“副作用”,或者简称为“作用”。
工作中遇到最大的难题最后是怎么解决的
项目优化
项目亮点、难点
说说自己最擅长的东西(技术点、方向,看看面试者有什么亮点)
上家离职原因
想找什么样的公司
你有什么想问的么
本次面试的表现;团队项目的工作内容、项目招人的背景、对于后续面试该做什么准备;我在团队中的作用,我能为团队做什么;我今后在团队的发展
目前薪资
面试题
单向绑定的优点和缺点
- 优点是相应的可以带来单向数据流,这样做的好处是所有状态变化都可以被记录、跟踪,状态变化通过手动调用通知,源头易追溯,没有“暗箱操作”。同时组件数据只有唯一的入口和出口,使得程序更直观更容易理解,有利于应用的可维护性。
- 缺点则是代码量会相应的上升,数据的流转过程变长,从而出现很多类似的样板代码。同时由于对应用状态独立管理的严格要求(单一的全局store),在处理局部状态较多的场景时(如用户输入交互较多的“富表单型”应用),会显得啰嗦及繁琐。
双向绑定的优缺点
基本上双向绑定的优缺点就是单向绑定的镜像了。
- 优点是在表单交互较多的场景下,会简化大量业务无关的代码。
- 缺点就是由于都是“暗箱操作”,我们无法追踪局部状态的变化(虽然大部分情况下我们并不关心),潜在的行为太多也增加了出错时 debug 的难度。同时由于组件数据变化来源入口变得可能不止一个,新手玩家很容易将数据流转方向弄得紊乱,如果再缺乏一些“管制”手段,最后就很容易因为一处错误操作造成应用雪崩。
cordova优缺点
优点:
- 跨平台,安卓、iOS自然不在话下。
- 开发效率高,Web经过这么多年的发展,API丰富,各种轮子异常丰富,随用随找。
- 因为安卓、iOS都已经自带webview,所以Cordova app不需要带webview,所以开发出来的app可以很小,基本可以和原生媲美。
缺点:
- UI执行效率比较低,所以出现了ReactNative等使用原生控件的库,但低到什么程度需要你自己去感受一下,是否可以接受。
- Web组件本身一些天生的设计缺陷,比如页面来回切换导致的重新加载,长列表的位置保持,这些需要开发人员想一些办法去规避。
- 不同平台自带的浏览器版本有差异导致的兼容性问题。
- 非web接口,比如和摄像头、蓝牙等交互的功能,需要通过插件来解决,插件没有的话,还是需要自己用原生代码写插件。
移动Web应用可分为三种:
- 原生应用:通过各种应用市场安装,采用平台特定语言开发。
- Web应用:通过浏览器访问,采用Web技术开发。
- 混合型应用:通过各种应用市场安装,但采用Web技术开发。它虽然看上去是一个原生应用,但里面访问的实际上是一个Web应用。 原生应用的优势:
- 提供最佳的用户体验、最优质的用户界面和最华丽的交互;
- 针对不同平台提供不同体验;
- 可节省带宽成本;
- 可访问本地资源;
- 盈利模式明朗。 原生应用的劣势:
- 移植到不同平台上比较麻烦;
- 维护多个版本的成本比较高;
- 需要通过store或market确认;
- 盈利需要与第三方分成。 Web应用的优势如下:
- 开发成本低;
- 适配多种移动设备的成本低;
- 跨平台和终端;
- 迭代更新容易;
- 无需安装成本。 Web应用的劣势如下:
- 浏览体验短期内还无法超越原生应用;
- 不支持离线模式(HTML5将会解决这个问题);
- 消息推送不够及时;
- 调用本地文件系统的能力弱。
- 混合型应用可以说是为了弥补上面两种应用开发模式的缺陷而生,它是两者混合的产物,并且尽可能继承了双方的优势:
什么是JSBridge
js桥梁,连接JavaScript和原生之间的桥梁
JSBridge通信原理
JS 调用 Native
- JS 调用 Native 的实现方式较多,主要有拦截 URL Scheme 、重写 prompt 、注入 API 等方法。 Native 调用 JS
- Native 调用 JS 比较简单,只要 H5 将 JS 方法暴露在 Window 上给 Native 调用即可。
HTTP与HTTPS有什么区别?
- HTTP 明文传输,数据都是未加密的,安全性较差,HTTPS(SSL+HTTP) 数据传输过程是加密的,安全性较好。
- 使用 HTTPS 协议需要到 CA(Certificate Authority,数字证书认证机构) 申请证书,一般免费证书较少,因而需要一定费用。证书颁发机构如:Symantec、Comodo、GoDaddy 和 GlobalSign 等。
- HTTP 页面响应速度比 HTTPS 快,主要是因为 HTTP 使用 TCP 三次握手建立连接,客户端和服务器需要交换 3 个包,而 HTTPS除了 TCP 的三个包,还要加上 ssl 握手需要的 9 个包,所以一共是 12 个包。
- http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
- HTTPS 其实就是建构在 SSL/TLS 之上的 HTTP 协议,所以,要比较 HTTPS 比 HTTP 要更耗费服务器资源。 SSL协议工作在(应用层与传输层之间)。 www.cnblogs.com/aspirant/p/…
get、post区别
- GET - 从指定的资源请求数据。
- POST - 向指定的资源提交要被处理的数据
对称加密和非对称加密
- 加密和解密用同一个秘钥的加密方式叫做对称加密。
- 非对称加密,比如RSA。 非对称加密会有一对秘钥:公钥和私钥。 公钥加密的内容,只有私钥可以解开,私钥加密的内容,所有的公钥都可以解开(当然是指和秘钥是一对的公钥)。公钥放在服务器上。
- 假如中间人拦截后把服务器的公钥替换为自己的公钥,因为数字签名的存在,会导致客户端验证签名不匹配,这样就防止了中间人替换公钥的问题。
- HTTPS就是使用SSL/TLS协议进行加密传输,让客户端拿到服务器的公钥,然后客户端随机生成一个对称加密的秘钥,使用公钥加密,传输给服务端,后续的所有信息都通过该对称秘钥进行加密解密,完成整个HTTPS的流程。 segmentfault.com/a/119000002…
二叉树的四种遍历方式
- 先序(先根)遍历:即先访问根节点,再访问左孩子和右孩子
- 中序遍历:左根右
- 后序遍历:左右根
- 层序遍历:上至下一层层遍历