React 组件动态加载
React 的 setState 怎么实现的异步操作
React 官网对 setState 的说明:
将 setState() 认为是一次请求而不是一次立即执行更新组件的命令。为了更为客观的性能,React 可能会推迟它,稍后一次性更新这些组件。React 不会保证在 setState 之后,能够立刻拿到改变的结果。
- setState 只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的;
- setState 的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形成了所谓的“异步”,当然可以通过 setState 的第二个参数中的 callback 拿到更新后的结果;
- setState 的批量更新优化也是建立在“异步”之上的,在原生事件和 setTimeout 中不会批量更新,在“异步”中如果对同一个值进行多次 setState,setState 的批量更新策略就会对其进行覆盖,取最后一次的执行,如果同时 setState 多个不同的值,在更新时会对其进行批量更新。
如果想让 setState 立即执行怎么实现
讲一讲 React 的高阶组件
高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。
高阶组件是参数为组件,返回值为新组件的函数。
const EnhancedComponent = higherOrderComponent(WrappedComponent);
HOC 不会修改传入的组件,也不会使用继承来复制其行为。相反,HOC 通过将组件包装在容器中来组成新组件。HOC 是纯函数,没有副作用。
被包装组件
React 怎么做到将 JSX 转换为 DOM 树的
React 怎么减少 DOM 变动次数的
一个页面中多个 tab, 不用 Redux,怎么实现数据共享?
Localstorage 有过期时间吗?怎么实现?
JS 怎么捕获路由变化
如果是哈希路由变化的话,直接给 window 绑定 'hashchange' 事件;
普通路由 'popstate' 事件在调用 history.back()、history.forward()、history.go() 方法后会触发,而 history.pushState() 和 history.replaceState() 并不会触发 popState 事件,怎么办呢?
网路上有一篇 JS 监听 history 路由变化的文章
// 订阅-发布模式
JS 怎么捕获脚本运行错误
CSRF、XSS 攻击的原理以及怎么防范
简述浏览器输入 URL 到浏览器出现页面的过程
为什么 JS 的脚本时,会停止 DOM 树的解析
JS 怎么异步编程的方法?
- 回调函数
回调函数是异步编程最基础的方法。举例一个最简单的回调:在 f1 执行完之后再执行 f2
var func1 = function(){ console.log(1); if(callback && typeof(callback) === 'function'){ callback(); } } var func2 = function(){ console.log(2); } func1(func2); // 输出 1,2
异步回调最常见的就是 Ajax
$.ajax({ url: "/getmsg", type: "get", dataType: 'json', success: function(ret){ if(ret && ret.status){ // } }, error: function(xhr){ // } })
- 事件监听
- 发布/订阅
- promise
- generator (ES6)
- async/await (ES7)
微任务与宏任务有什么区别
JS 有哪些设计模式
设计模式
设计模式:在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方法。
例
- 观察者模式:观察者模式定义了对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新。
- 订阅-发布模式:在现在的订阅-发布模式中,发布者的消息不会直接发送给订阅者,这意味着发布者和订阅者都不知道彼此的存在。在发布者和订阅者之间存在第三个组件,称为消息代理或调度中心或中间件,它维持着发布者和订阅者之间的联系,过滤所有的发布者传入的消息,并相应的分发给他们的订阅者。
观察者模式和订阅发布最大的区别是订阅-发布模式有事件调度中心。
观察者模式有具体目标调度,每个被订阅的目标里面都需要对观察者的处理,这种处理方式可能造成代码的冗余;
订阅-发布模式中,统一由调度中心进行处理,订阅者和发布者互不干扰,消除了发布者和订阅者之间的依赖。这样一方面实现了解耦,另一方面可以实现更加细粒度的控制。比如发布者发布了很多消息,但不是所有的订阅者都希望收到,就可以在调度中心做一些处理,类似权限控制之类的。还可以做一些节流操作。
为什么选择的是 React,而不是 Vue
讲一下 js 的基础类型 symbol
symbol 是一种基本数据类型。每个从 Symbol() 返回的 symbol 值都是唯一的。一个 symbol 值能作为对象属性的标识符;这是该数据类型仅有的目的。
Symbol('foo') !== Symbol('foo') // true var sym = new Symbol() // TypeError // 在对象中查找 Symbol 属性 Object.getOwnPropertySymbols() // 方法 // Symbol.for() Symbol.for('bar') === Symbol.for('bar') // true // Symbol.keyFor() // 创建一个 symbol,并放入 Symbol 注册表,key 为 "foo" var globalSym = Symbol.for("foo"); Symbol.keyFor(globalSym) // "foo" // 创建一个 symbol,但是并不放入注册表里,key 为 "song" Symbol.keyFor("song") // undefined
同源策略
scheme、host、port 都相同则为同源;
非同源站点有这样的限制:
- 不能读取和修改对方的 DOM;
- 不能访问对方的 Cookie、IndexDB和LocalStorage等;
- 限制 XMLHttpRequest 请求;
有哪些跨域请求的方法
CORS、Jsonp、Nginx反向代理
讲一下 Nginx 反向代理
Nginx 是一种高性能的反向代理服务器,,可以轻松用来解决跨域问题;
正向代理帮助客户端访问客户端访问不到的服务器,然后将结果返回客户端;
反向代理拿到客户端的请求,将请求转发给其他的服务器,主要的场景是维持服务器集群的负载均衡,换句话说,反向代理帮其他的服务器拿到请求,然后选择一个合适的服务器,将请求转交给它。
也就是说,正向代理服务器是帮客户端做事情,而反向代理服务器是帮其他的服务器做事情。
现在客户端的域名是 client.com,服务器的域名是 server.com,客户端向服务器发送 Ajax 请求,属于跨域。
// server 代表一个服务 server { listen 80; server_name client.com; location /api { proxy_pass server.com; }
Nginx 相当于一个跳板机,这个跳板机的域名是 client.com,让客户端首先访问 client.com/api,这当然没有跨域,然后 Nginx 服务器作为反向代理,将请求转发给 server.com,当响应返回时,又将响应给到客户端,这就完成了整个跨域请求的过程。
块级元素和 inline 元素的区别
怎么让两个块级元素在同一行
浮动会造成什么后果,怎么解决
一个 a.cn 的服务器请求一个 b.cn 的服务器,会触发同源策略吗?
用户怎么实时的获取服务器更新信息
讲一下 Webpack 的作用
字符串去重怎么做
了解 Web Workers 吗
讲一下 CSS 的动画实现
讲一下 rem
怎么实现响应式布局
复盘
二面完全崩了,几乎一题都没回答上来,React 框架的原理完全不懂,要尽快补上。。。。。。