原文出处,怎么去设计一个组件封装

作者: 前端  发布:2019-11-22

新鲜出炉的8月前端面试题

2018/08/16 · 基础技术 · 面试

原文出处: Belinda   

基础题

JS异步那些事 一 (基础知识)
JS异步那些事 二 (分布式事件)
JS异步那些事 三 (Promise)
JS异步那些事 四(HTML 5 Web Workers)
JS异步那些事 五 (异步脚本加载)

图片 1

前言

最近参加了几场面试,积累了一些高频面试题,我把面试题分为两类,一种是基础试题: 主要考察前端技基础是否扎实,是否能够将前端知识体系串联。一种是开放式问题: 考察业务积累,是否有自己的思考,思考问题的方式,这类问题没有标准答案。

题目的答案提供了一个思考的方向,答案不一定正确全面,有错误的地方欢迎大家请在评论中指出,共同进步。

异步脚本加载

我遇到的前端面试题2017

基础题

题目的答案提供了一个思考的方向,答案不一定正确全面,有错误的地方欢迎大家请在评论中指出,共同进步。

怎么去设计一个组件封装

阻塞性脚本

JavaScript在浏览器中被解析和执行时具有阻塞的特性,也就是说,当JavaScript代码执行时,页面的解析、渲染以及其他资源的下载都要停下来等待脚本执行完毕

浏览器是按照从上到下的顺序解析页面,因此正常情况下,JavaScript脚本的执行顺序也是从上到下的,即页面上先出现的代码或先被引入的代码总是被先执行,即使是允许并行下载JavaScript文件时也是如此。注意我们这里标红了"正常情况下",原因是什么呢?我们知道,在HTML中加入JavaScript代码有多种方式,概括如下(不考虑require.js或sea.js等模块加载器):

(1)正常引入:即在页面中通过<script>标签引入脚本代码或者引入外部脚本
(2)通过document.write方法向页面写入<script>标签或代码
(3)通过动态脚本技术,即利用DOM接口创建<script>元素,并设置元素的src,然后再将元素添加进DOM中。
(4)通过Ajax获取脚本内容,然后再创建<script>元素,并设置元素的text,再将元素添加进DOM中。
(5)直接把JavaScript代码写在元素的事件处理程序中或直接作为URL的主体

具体参考 http://www.jb51.net/article/77920.htm

本文首发于我的博客:http://dunizb.com

怎么去设计一个组件封装

  1. 组件封装的目的是为了重用,提高开发效率和代码质量
  2. 低耦合,单一职责,可复用性,可维护性
  3. 前端组件化设计思路

组件封装的目的是为了重用,提高开发效率和代码质量

脚本延迟运行

一般在JS页面延迟执行一些方法。可以使用以下的方法:

Window.setTimeout  

jQuery.delay

jQuery.queue和jQuery.dequeue

<script src="deferdemo.js" defer></script>

加上 defer 等于在页面完全在入后再执行,相当于 window.onload ,但应用上比 window.onload 更灵活!

<script type="text/javascript" src="demo_async.js" async="async"></script>

使用async属性,浏览器会下载js文件,同时继续对后面的内容进行渲染
通常如果js不需要改变DOM结构时可以使用async进行异步加载(比如一些统计代码可以异步加载,因为此代码与页面执行逻辑无关,不会改变DOM结构)

想知道自己什么水平就出去面试….

js 异步加载的方式

  1. 渲染引擎遇到 script 标签会停下来,等到执行完脚本,继续向下渲染
  2. defer 是“渲染完再执行”,async 是“下载完就执行”,defer 如果有多个脚本,会按照在页面中出现的顺序加载,多个async 脚本不能保证加载顺序
  3. 加载 es6模块的时候设置 type=module,异步加载不会造成阻塞浏览器,页面渲染完再执行,可以同时加上async属性,异步执行脚本(利用顶层的this等于undefined这个语法点,可以侦测当前代码是否在 ES6 模块之中)

低耦合,单一职责,可复用性,可维护性

SeaJS与RequireJS

网上写amd和cmd的文章很多,当然也有很多都是误人子弟的片面的看法,所以还是推荐自己看官方文档多加尝试去理解。

“RequireJS 遵循的是 AMD(异步模块定义)规范,SeaJS 遵循的是 CMD (通用模块定义)规范”。

AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。

amd 规划 https://github.com/amdjs/amdjs-api/wiki/AMD-(%E4%B8%AD%E6%96%87%E7%89%88))

cmd 规范 https://github.com/seajs/seajs/issues/242

2017-10-19更新:修改22题深浅拷贝的答案

css 动画和 js 动画的差异

  1. 代码复杂度,js 动画代码相对复杂一些
  2. 动画运行时,对动画的控制程度上,js 能够让动画,暂停,取消,终止,css动画不能添加事件
  3. 动画性能看,js 动画多了一个js 解析的过程,性能不如 css 动画好

前端组件化设计思路

区别:

  1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)

  2. CMD 推崇依赖就近,AMD 推崇依赖前置。

2017-10-18更新:修正部分题目答案,答案并非十分准确,仅供参考,此文部分题目答案故意省掉了一些高精尖、新奇特的东西,比如创建对象我写了三种,《JS高程》上可不止三种,一切以常用记得住的为宗旨,所以,对于部分答案有疑问的同学,可以留言讨论或自行斟酌

XSS 与 CSRF 两种跨站攻击

  1. xss 跨站脚本攻击,主要是前端层面的,用户在输入层面插入攻击脚本,改变页面的显示,或则窃取网站 cookie,预防方法:不相信用户的所有操作,对用户输入进行一个转义,不允许 js 对 cookie 的读写
  2. csrf 跨站请求伪造,以你的名义,发送恶意请求,通过 cookie 加参数等形式过滤
  3. 我们没法彻底杜绝攻击,只能提高攻击门槛

js 异步加载的方式

ECMAScript6 Moudle

历史上,JavaScript一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。其他语言都有这项功能,比如Ruby的require、Python的import,甚至就连CSS都有@import
到了ES6,实现了模块化的功能,功能上基本可以取代 cmd和amd的规范,

模块的功能主要由两个命令构成,export和import,export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

2017-10-12更新:有部分题目属于后端范畴,或者是大前端范畴,因为我以前做Java后端的(关于我),故偶尔会遇到后端相关的一些问题,但是没有遇到问纯Java技术问题。如果你对某些后端题目不理解就直接跳过吧。部分题目来自慕课网实战课程《前端跳槽面试必备技巧》,课程里的一些题目确实被面试问到过

事件委托,目的,功能,写法

  1. 把一个或者一组元素的事件委托到它的父层或者更外层元素上
  2. 优点,减少内存消耗,动态绑定事件
  3. target 是触发事件的最具体的元素,currenttarget是绑定事件的元素(在函数中一般等于this)
  4. JavaScript 事件委托详解

渲染引擎遇到 script 标签会停下来,等到执行完脚本,继续向下渲染

export的写法,

// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export {firstName, lastName, year};

上面代码在export命令后面,使用大括号指定所要输出的一组变量。

金九银十,在九月之前把工作落实了,经历了好几个公司的面试,得到一些信息,和大家分享:

线程,进程

  1. 线程是最小的执行单元,进程是最小的资源管理单元
  2. 一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程

defer 是“渲染完再执行”,async 是“下载完就执行”,defer 如果有多个脚本,会按照在页面中出现的顺序加载,多个async 脚本不能保证加载顺序

import写法:

// main.js

import {firstName, lastName, year} from './profile';

function setName(element) {
  element.textContent = firstName + ' ' + lastName;
}
  1. 大部分公司(创业公司)都趋向于招一个牛逼的前端而不是三四个平庸的前端
  2. 性能优化、ES6必问
  3. 招聘要求上清一色的要求有一门后端语言的经验,但似乎面试的时候并没有一个公司问过我后端语言方面的东西
  4. 招聘要求写的和面试相关性并不是很高
  5. 招人的要求越来越高,不要轻易离职,特别是裸辞

负载均衡

  1. 当系统面临大量用户访问,负载过高的时候,通常会使用增加服务器数量来进行横向扩展,使用集群和负载均衡提高整个系统的处理能力
  2. 服务器集群负载均衡原理?

加载 es6模块的时候设置 type=module,异步加载不会造成阻塞浏览器,页面渲染完再执行,可以同时加上async属性,异步执行脚本(利用顶层的this等于undefined这个语法点,可以侦测当前代码是否在 ES6 模块之中)

ES6模块加载的实质

ES6模块加载的机制,与CommonJS模块完全不同。CommonJS模块输出的是一个值的拷贝,而ES6模块输出的是值的引用。CommonJS模块输出的是被输出值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。

ES6模块的运行机制与CommonJS不一样,它遇到模块加载命令import时,不会去执行模块,而是只生成一个动态的只读引用。等到真的需要用到时,再到模块里面去取值,换句话说,ES6的输入有点像Unix系统的”符号连接“,原始值变了,import输入的值也会跟着变。因此,ES6模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。

// mod.js
function C() {
  this.sum = 0;
  this.add = function () {
    this.sum = 1;
  };
  this.show = function () {
    console.log(this.sum);
  }
}

export let c = new C();

上面的脚本mod.js,输出的是一个C的实例。不同的脚本加载这个模块,得到的都是同一个实例。

// x.js
import {c} from './mod';
c.add();

// y.js
import {c} from './mod';
c.show();

// main.js
import './x';
import './y';

现在执行main.js,输出的是1。
证明加载的是同一个实例
参考 http://es6.ruanyifeng.com/#docs/module

以下是我整理我面试遇到的一些我觉得具有代表性的题目,刚好30题,吐血献上!

什么是CDN缓存

  1. CDN 是一种部署策略,根据不同的地区部署类似nginx 这种服务服务,会缓存静态资源。前端在项目优化的时候,习惯在讲台资源上加上一个 hash 值,每次更新的时候去改变这个 hash,hash 值变化的时候,服务会去重新取资源
  2. (CDN)是一个经策略性部署的整体系统,包括分布式存储、负载均衡、网络请求的重定向和内容管理4个要件
  3. CDN_百度百科

css 动画和 js 动画的差异

总结

写这篇博客参考了很多网上的文章和一些书籍,因为太多就没有一一列举,这也算是我学习js异步知识的一个记录吧。

毕竟马上就要去以一个前端工程师的身份去鹅厂实习了,所以还是要多学点东西,拿点干货出来。

关于JS异步那些事就写到这里了,很多地方理解的不够深刻希望大家多多指教。

0.谈谈对前端安全的理解,有什么,怎么防范

前端安全问题主要有XSS、CSRF攻击
XSS:跨站脚本攻击
它允许用户将恶意代码植入到提供给其他用户使用的页面中,可以简单的理解为一种javascript代码注入。
XSS的防御措施:

  1. 过滤转义输入输出
  2. 避免使用evalnew Function等执行字符串的方法,除非确定字符串和用户输入无关
  3. 使用cookie的httpOnly属性,加上了这个属性的cookie字段,js是无法进行读写的
  4. 使用innerHTML、document.write的时候,如果数据是用户输入的,那么需要对象关键字符进行过滤与转义

CRSF:跨站请求伪造
其实就是网站中的一些提交行为,被黑客利用,在你访问黑客的网站的时候进行操作,会被操作到其他网站上
CRSF防御措施:

  1. 检测http referer是否是同域名
  2. 避免登录的session长时间存储在客户端中
  3. 关键请求使用验证码或者token机制

其他的一些攻击方法还有HTTP劫持、界面操作劫持

闭包的写法,闭包的作用,闭包的缺点

  1. 使用闭包的目的——隐藏变量,间接访问一个变量,在定义函数的词法作用域外,调用函数
  2. 闭包的内存泄露,是IE的一个 bug,闭包使用完成之后,收回不了闭包的引用,导致内存泄露
  3. 「每日一题」JS 中的闭包是什么?
  4. 闭包造成内存泄露的实验

代码复杂度,js 动画代码相对复杂一些

1.使用箭头函数需要注意的地方

当要求动态上下文的时候,你就不能使用箭头函数,比如:定义方法,用构造器创建对象,处理时间时用 this 获取目标。

跨域问题,谁限制的跨域,怎么解决

  1. 浏览器的同源策略导致了跨域
  2. 用于隔离潜在恶意文件的重要安全机制
  3. [jsonp ,允许 script 加载第三方资源]https://segmentfault.com/a/11…
  4. nginx 反向代理(nginx 服务内部配置 Access-Control-Allow-Origin *)
  5. cors 前后端协作设置请求头部,Access-Control-Allow-Origin 等头部信息
  6. iframe 嵌套通讯,postmessage

动画运行时,对动画的控制程度上,js 能够让动画,暂停,取消,终止,css动画不能添加事件

2.webpack.load的原理

loaders是你用在app源码上的转换元件。他们是用node.js运行的,把源文件作为参数,返回新的资源的函数。

javascript 中常见的内存泄露陷阱

  1. 内存泄露会导致一系列问题,比如:运行缓慢,崩溃,高延迟
  2. 内存泄露是指你用不到(访问不到)的变量,依然占居着内存空间,不能被再次利用起来
  3. 意外的全局变量,这些都是不会被回收的变量(除非设置 null 或者被重新赋值),特别是那些用来临时存储大量信息的变量
  4. 周期函数一直在运行,处理函数并不会被回收,jq 在移除节点前都会,将事件监听移除
  5. js 代码中有对 DOM 节点的引用,dom 节点被移除的时候,引用还维持
  6. JavaScript 中 4 种常见的内存泄露陷阱

动画性能看,js 动画多了一个js 解析的过程,性能不如 css 动画好

3.ES6 let、const

let
let是更完美的var

  1. let声明的变量拥有块级作用域,let声明仍然保留了提升的特性,但不会盲目提升。
  2. let声明的全局变量不是全局对象的属性。不可以通过window.变量名的方式访问
  3. 形如for (let x…)的循环在每次迭代时都为x创建新的绑定
  4. let声明的变量直到控制流到达该变量被定义的代码行时才会被装载,所以在到达之前使用该变量会触发错误。

const
定义常量值,不可以重新赋值,但是如果值是一个对象,可以改变对象里的属性值

const OBJ = {"a":1, "b":2};
OBJ.a = 3;
OBJ = {};// 重新赋值,报错!
console.log(OBJ.a); // 3

babel把ES6转成ES5或者ES3之类的原理是什么

  1. 它就是个编译器,输入语言是ES6+,编译目标语言是ES5
  2. babel 官方工作原理
  3. 解析:将代码字符串解析成抽象语法树
  4. 变换:对抽象语法树进行变换操作
  5. 再建:根据变换后的抽象语法树再生成代码字符串

XSS 与 CSRF 两种跨站攻击

4.CSS3 box-sizing的作用

设置CSS盒模型为标准模型或IE模型。标准模型的宽度只包括content,二IE模型包括border和padding

box-sizing属性可以为三个值之一:

  1. content-box,默认值,border和padding不计算入width之内
  2. padding-box,padding计算入width内
  3. border-box,border和padding计算入width之内

Promise 模拟终止

  1. 当新对象保持“pending”状态时,原Promise链将会中止执行。
  2. return new Promise(()=>{}); // 返回“pending”状态的Promise对象
  3. 从如何停掉 Promise 链说起(promise内存泄漏问题)

xss 跨站脚本攻击,主要是前端层面的,用户在输入层面插入攻击脚本,改变页面的显示,或则窃取网站 cookie,预防方法:不相信用户的所有操作,对用户输入进行一个转义,不允许 js 对 cookie 的读写

5.说说HTML5中有趣的标签(新标签及语义化)

如果代码写的语义化,有利于SEO。搜索引擎就会很容易的读懂该网页要表达的意思。例如文本模块要有大标题,合理利用h1-h6,列表形式的代码使用ul或ol,重要的文字使用strong等等。总之就是要充分利用各种HTML标签完成他们本职的工作

promise 放在try catch里面有什么结果

  1. Promise 对象的错误具有冒泡性质,会一直向后传递,直到被捕获为止,也即是说,错误总会被下一个catch语句捕获
  2. 当Promise链中抛出一个错误时,错误信息沿着链路向后传递,直至被捕获

csrf 跨站请求伪造,以你的名义,发送恶意请求,通过 cookie 加参数等形式过滤

6.git命令,如何批量删除分支

git branch |grep 'branchName' |xargs git branch -D,从分支列表中匹配到指定分支,然后一个一个(分成小块)传递给删除分支的命令,最后进行删除。(参考这里)

网站性能优化

  1. http 请求方面,减少请求数量,请求体积,对应的做法是,对项目资源进行压缩,控制项目资源的 dns 解析在2到4个域名,提取公告的样式,公共的组件,雪碧图,缓存资源,
  2. 压缩资源,提取公共资源压缩,提取 css ,js 公共方法
  3. 不要缩放图片,使用雪碧图,使用字体图表(阿里矢量图库)
  4. 使用 CDN,抛开无用的 cookie
  5. 减少重绘重排,CSS属性读写分离,最好不要用js 修改样式,dom 离线更新,渲染前指定图片的大小
  6. js 代码层面的优化,减少对字符串的计算,合理使用闭包,首屏的js 资源加载放在最底部

我们没法彻底杜绝攻击,只能提高攻击门槛

7.创建对象的三种方法

第一种方式,字面量

var o1 = {name: "o1"}

第二种方式,通过构造函数

var o2 = new Object({name: "o2"})
var M = function(name){ this.name = name }
var o3 = new M("o3")

第三种方式,Object.create

var  p = {name: "p"}
var o4 = Object.create(p)

新创建的对o4的原型就是p,同时o4也拥有了属性name

js 自定义事件实现

  1. 原生提供了3个方法实现自定义事件
  2. createEvent,设置事件类型,是 html 事件还是 鼠标事件
  3. initEvent 初始化事件,事件名称,是否允许冒泡,是否阻止自定义事件
  4. dispatchEvent 触发事件

事件委托,目的,功能,写法

8.JS实现继承的几种方式

借用构造函数实现继承

function Parent1(){
    this.name = "parent1"
}
function Child1(){
    Parent1.call(this);
    this.type = "child1";
}

缺点:Child1无法继承Parent1的原型对象,并没有真正的实现继承(部分继承)

借用原型链实现继承

function Parent2(){
    this.name = "parent2";
    this.play = [1,2,3];
}
function Child2(){
    this.type = "child2";
}
Child2.prototype = new Parent2();

缺点:原型对象的属性是共享的

组合式继承

function Parent3(){
    this.name = "parent3";
    this.play = [1,2,3];
}
function Child3(){
    Parent3.call(this);
    this.type = "child3";
}
Child3.prototype = Object.create(Parent3.prototype);
Child3.prototype.constructor = Child3;

angular 双向数据绑定与vue数据的双向数据绑定

  1. 二者都是 MVVM 模式开发的典型代表
  2. angular 是通过脏检测实现,angular 会将 UI 事件,请求事件,settimeout 这类延迟,的对象放入到事件监测的脏队列,当数据变化的时候,触发 $diget 方法进行数据的更新,视图的渲染
  3. vue 通过数据属性的数据劫持和发布订阅的模式实现,大致可以理解成由3个模块组成,observer 完成对数据的劫持,compile 完成对模板片段的渲染,watcher 作为桥梁连接二者,订阅数据变化及更新视图

把一个或者一组元素的事件委托到它的父层或者更外层元素上

9.当new Foo()时发生了什么

1.创建了一个新对象
2.将this指向这个新对象
3.执行构造函数里面的代码
4.返回新对象(this)
参考《JS高程》6.6.2

get与post 通讯的区别

  1. Get 请求能缓存,Post 不能
  2. Post 相对 Get 安全一点点,因为Get 请求都包含在 URL 里,且会被浏览器保存历史纪录,Post 不会,但是在抓包的情况下都是一样的。
  3. Post 可以通过 request body来传输比 Get 更多的数据,Get 没有这个技术
  4. URL有长度限制,会影响 Get 请求,但是这个长度限制是浏览器规定的,不是 RFC 规定的
  5. Post 支持更多的编码类型且不对数据类型限制

优点,减少内存消耗,动态绑定事件

10.你做过哪些性能优化

雪碧图,移动端响应式图片,静态资源CDN,减少Dom操作(事件代理、fragment),压缩JS和CSS、HTML等,DNS预解析

有没有去研究webpack的一些原理和机制,怎么实现的

  1. 解析webpack配置参数,合并从shell传入和webpack.config.js文件里配置的参数,生产最后的配置结果。
  2. 注册所有配置的插件,好让插件监听webpack构建生命周期的事件节点,以做出对应的反应。
  3. 从配置的entry入口文件开始解析文件构建AST语法树,找出每个文件所依赖的文件,递归下去。
  4. 在解析文件递归的过程中根据文件类型和loader配置找出合适的loader用来对文件进行转换。
  5. 递归完后得到每个文件的最终结果,根据entry配置生成代码块chunk。
  6. 输出所有chunk到文件系统。

target 是触发事件的最具体的元素,currenttarget是绑定事件的元素(在函数中一般等于this)

11.浏览器渲染原理

首先来看一张图:

图片 2

  1. HTML被解析成DOM Tree,CSS被解析成CSS Rule Tree
  2. 把DOM Tree和CSS Rule Tree经过整合生成Render Tree(布局阶段)
  3. 元素按照算出来的规则,把元素放到它该出现的位置,通过显卡画到屏幕上

更多详情看这里

ES6模块与CommonJS模块的差异

  1. CommonJs 模块输出的是一个值的拷贝,ES6模块输出的是一个值的引用
  2. CommonJS 模块是运行时加载,ES6模块是编译时输出接口
  3. ES6输入的模块变量,只是一个符号链接,所以这个变量是只读的,对它进行重新赋值就会报错

JavaScript 事件委托详解

12.前端路由的原理

什么是路由?简单的说,路由是根据不同的 url 地址展示不同的内容或页面

使用场景?前端路由更多用在单页应用上, 也就是SPA, 因为单页应用, 基本上都是前后端分离的, 后端自然也就不会给前端提供路由。

前端的路由和后端的路由在实现技术上不一样,但是原理都是一样的。在 HTML5 的 history API 出现之前,前端的路由都是通过 hash 来实现的,hash 能兼容低版本的浏览器。

两种实现前端路由的方式
HTML5 History两个新增的API:history.pushStatehistory.replaceState,两个 API 都会操作浏览器的历史记录,而不会引起页面的刷新。

Hash就是url 中看到 # ,我们需要一个根据监听哈希变化触发的事件( hashchange) 事件。我们用 window.location 处理哈希的改变时不会重新渲染页面,而是当作新页面加到历史记录中,这样我们跳转页面就可以在 hashchange 事件中注册 ajax 从而改变页面内容。

优点
从性能和用户体验的层面来比较的话,后端路由每次访问一个新页面的时候都要向服务器发送请求,然后服务器再响应请求,这个过程肯定会有延迟。而前端路由在访问一个新页面的时候仅仅是变换了一下路径而已,没有了网络延迟,对于用户体验来说会有相当大的提升。

更多内容请看这里

缺点
使用浏览器的前进,后退键的时候会重新发送请求,没有合理地利用缓存。

模块加载AMD,CMD,CommonJS Modules/2.0 规范

  1. 这些规范的目的都是为了 JavaScript 的模块化开发,特别是在浏览器端的
  2. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行
  3. CMD 推崇依赖就近,AMD 推崇依赖前置

线程,进程

13.Restful API是什么

  1. Restful的意思就是表现层状态转化。
  2. "表现层"其实指的是"资源"(Resources)的"表现层",把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)。
  3. 所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在,每一个URI代表一种资源。
  4. 如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。
  5. Restful就是客户端和服务器之间,传递这种资源的某种表现层
  6. 客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"

Restful API就是符合Restful架构的API设计。

Restful API一些具体实践:

  1. 应该尽量将API部署在专用域名之下。如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下。
  2. 应该将API的版本号放入URL。
  3. 对于资源的具体操作类型,由HTTP动词表示
  4. 如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果
  5. 如果状态码是4xx,就应该向用户返回出错信息。一般来说,返回的信息中将error作为键名
    .....

Node 事件循环,js 事件循环差异

  1. Node.js 的事件循环分为6个阶段
  2. 浏览器和Node 环境下,microtask 任务队列的执行时机不同
    • Node.js中,microtask 在事件循环的各个阶段之间执行
    • 浏览器端,microtask 在事件循环的 macrotask 执行完之后执行
  3. 递归的调用process.nextTick()会导致I/O starving,官方推荐使用setImmediate()

线程是最小的执行单元,进程是最小的资源管理单元

14.script标签的defer、async的区别

defer是在HTML解析完之后才会执行,如果是多个,按照加载的顺序依次执行
async是在加载完成后立即执行,如果是多个,执行顺序和加载顺序无关

浅拷贝和深拷贝的问题

  1. 深拷贝和浅拷贝是只针对Object和Array这样的复杂类型的
  2. 也就是说a和b指向了同一块内存,所以修改其中任意的值,另一个值都会随之变化,这就是浅拷贝
  3. 浅拷贝, ”Object.assign() 方法用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象。它将返回目标对象
  4. 深拷贝,JSON.parse()和JSON.stringify()给了我们一个基本的解决办法。但是函数不能被正确处理

一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程

15.同源与跨域

什么是同源策略?
限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。
一个源指的是主机名、协议和端口号的组合,必须相同

跨域通信的几种方式

  • JSONP
  • Hash
  • postMessage
  • WebSocket
  • CORS

JSONP原理
基本原理:利用script标签的异步加载特性实现
给服务端传一个回调函数,服务器返回一个传递过去的回调函数名称的JS代码

更多请查看:《前后端通信类知识》

开放性问题

开放性问题主要是考察候选人业务积累,是否有自己的思考,思考问题的方式,没有标准答案。不过有些问题挺刁的,哈哈哈哈,比如:” 你见过的最好的代码是什么? “总之提前准备下没错。

  1. 先自我介绍一下,说一下项目的技术栈,以及项目中遇到的一些问题
  2. 从整体中,看你对项目的认识,框架的认识和自己思考
  3. 项目中有没有遇到什么难点,怎么解决
  4. 如果你在创业公司你怎么从0开始做(选择什么框架,选择什么构建工具)
  5. 说一下你项目中用到的技术栈,以及觉得得意和出色的点,以及让你头疼的点,怎么解决的
  6. 一个业务场景,面对产品不断迭代,以及需求的变动该怎么应对,具体技术方案实现
  7. 你的学习来源是什么
  8. 你觉得哪个框架比较好,好在哪里
  9. 你觉得最难得技术难点是什么
  10. 你见过的最好的代码是什么

负载均衡

16.原型与闭包相关问题

原型是什么
原型就是一个普通的对象,每个对象都有一个原型(Object除外),原型能存储我们的方法,构造函数创建出来的实例对象能够引用原型中的方法。
查看原型
以前一般使用对象的__proto__属性,ES6推出后,推荐用Object.getPrototypeOf()方法来获取对象的原型

闭包是什么?
专业说法:当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包。

还可以这么理解:
闭包就是一个具有封闭功能与包裹功能的结构,是为了实现具有私有访问空间的函数的,函数可以构成闭包,因为函数内部定义的数据函数外部无法访问,即函数具有封闭性;函数可以封装代码即具有包裹性,所以函数可以构成闭包。
创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量
闭包的特性
闭包有三个特性:

  1. 函数嵌套函数
  2. 函数内部可以引用外部的参数和变量
  3. 参数和变量不会被垃圾回收机制回收

闭包有什么用,使用场景
当我们需要在模块中定义一些变量,并希望这些变量一直保存在内存中但又不会“污染”全局的变量时,就可以用闭包来定义这个模块。

闭包的缺点
闭包的缺点就是常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。

函数套函数就是闭包吗?不是!,当一个内部函数被其外部函数之外的变量引用时,才会形成了一个闭包。

更多内容请看这里

本文由9159.com发布于前端,转载请注明出处:原文出处,怎么去设计一个组件封装

关键词: