1、如何正确判断一个数据的基本类型?javascript
一、typeof css
typeof 对于原始类型(null undefined string number boolean symbol),除了null 都能显示正确的类型html
typeof null === 'object'
复制代码
typeof 对于对象来讲,除了函数外其余都是object 类型前端
typeof [] === 'object'
typeof console.log === 'function'
复制代码
因此typeof 没法正确区分对象和null(数组和null)vue
二、instanceof 判断已知对象类型的方法java
MDN 的解释: instanceof
运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype
属性node
判断一个对象是不是数据类型的实例
webpack
于是能够衍生出 用constructor 来判断类型({}).constructor == Object,可是constructor 是能够修改的ios
function Fn(){};
Fn.prototype=new Array();
var f=new Fn()
console.log(f.constructor===Fn); // false复制代码
,于是不许确。css3
三、通用型,借用Object.prototype.toString.call 来实现
var gettype=Object.prototype.toString
gettype.call('aaaa') 输出 [object String]
gettype.call(2222) 输出 [object Number]
gettype.call(true) 输出 [object Boolean]
gettype.call(undefined) 输出 [object Undefined]
复制代码
// 进行一层封装
let Type = (function(){
let type = {};
let typeArr = ['String', 'Object', 'Number', 'Array', 'Undefined', 'Null', 'Symbol'];
for(let i = 0; i < typeArr.length; i++){
type['Is'+ typeArr[i]] = function(obj){
return Object.prototype.toString.call(obj) === '[object '+ typeArr[i] +']'
}
}
return type
})()
复制代码
eg:(第一个字母小写,第二个字母大写)
Type.IsFunction(function() {}) Type.IsObject({}) 这样使用。复制代码
2、对象的深浅拷贝
什么是浅拷贝?如何实现浅拷贝?什么是深拷贝?如何实现深拷贝?
浅拷贝
利用Object.assign({}, obj) or 展开运算符 ... 来实现浅拷贝
let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(a.age) // 1
console.log(b.age) // 2复制代码
let a = {
age: 1
}
let b = { ...a }
a.age = 2复制代码
深拷贝
利用JSON.parse(JSON.stringify(object)) 来解决,(基本够用了)但这个有局限性,
自个封装 lodash 深拷贝函数
function deepClone(obj){
function isObject(o){
return (typeof o === 'object' || typeof o === 'function') && o !== null
}
if(!isObject(obj)){
throw new Error('not object')
}
let isArray = Array.isArray(obj)
let newObj = isArray? [...obj] : { ...obj }
Reflect.ownKeys(newObj).forEach((key)=>{
newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
})
return newObj
}
// eg
let obj = {
a: [1,2,3],
b:{
c:2,
d:3
}
}
let newObj = deepClone(obj)
newObj.b.c = 33
console.log(obj.b.c) // 2复制代码
3、call、apply 和 组合继承
function Product(name, price){
this.name = name;
this.price = price;
}
function Food(name, price){
Product.call(this, name, price)
this.category = 'food'
}
let foot1 = new Food('chees', 5);
foot1 // 复制代码
经过Food 构造方法里的call()
,成功使Food 扩展了name 以及price .(借用)
apply()
和 call()
都是为了改变某个函数运行时的上下文而存在的(就是为了改变函数内部的 this
指向)。而后,由于这两个方法会当即调用,因此为了弥补它们的缺失,还有个方法 bind()
。
/*apply()方法 参数是已数组的形式 add.apply(sub, [4,2]) */
function.apply(thisObj[, argArray])
/*call()方法 参数*/
function.call(thisObj[, arg1[, arg2[, [,...argN]]]]);复制代码
4、寄生组合继承(经典例子):
function Parent(value){
this.val = value
}
Parent.prototype.getValue = function(){
console.log(this.val)
}
function Child(value){
Parent.call(this, name)
}
// Child.prototype = new Parent() 组合继承
// 缺点就是在继承父类函数的时候调用了父类构造函数,致使子类的原型上多了不须要的父类属性,存在内存上的浪费
Child.prototype = Object.assign(Parent.prototype, {
constructor:{
value: Child,
enumerable: false,
writable: true,
configurable: true
}
})
const child = new Child(1)
child.getValue() // 1
child instanceof Parent // true
复制代码
继承实现的核心就是将父类的原型赋值给了子类,而且将构造函数设置为子类,这样既解决了无用的父类属性问题,还能正确的找到子类的构造函数。
es6 class 继承
class Parent{
constructor(value){
this.val = value
}
getValue(){
console.log(this.val)
}
}
class Child extends Parent{
constructor(value){
super(value)
this.val = value
}
}
let child = new Child(1)
child.getValue() // 1
child instanceof Parent //true复制代码
js 原型与原型链能够参考这个: https://juejin.im/post/5c72a1766fb9a049ea3993e6
5、防抖与节流
防抖即延时执行,指触发事件后在规定时间内回调函数只能执行一次,若是在规定时间内又触发该事件,则会从新开始算规定时间。
应用场景: 输入联想功能,用户不断输入时,用防抖来节约资源。
function callFn(content){
console.log('这是防抖回调函数')
}
// 利用回调函数 保存定时器标识
function debounce(func ,delay = 500){
let timer = null
return function(args){
let that = this
let _args = args
if(timer) clearTimeout(timer)
timer = setTimeout(function(){
func.call(that, _args)
}, delay)
}
}
let currDebounce = debounce(callFn, 500) // 返回延时函数
// 使用
let evtFn= document.querySelector('body')
evtFn.addEventListener('click', function(e){
currDebounce (e.target.value)
})复制代码
节流
当持续触发事件时,在规定时间段内只能调用一次,如再规定时间内又触发该事件,则return
,什么也不作。
应用场景,频繁触发事件,如滚动、resize 等。
// 定时器版
function throttle(func, delay = 500){
let timer = null;
return function(args){
let that = this;
let _args = args;
if(!timer){
timer = setTimeout(function(){
timer = null;
func.apply(that, _args)
}, delay)
}
}
}
// 时间戳版
function throttle(fun, delay = 500){
let previous = 0;
return function(args){
let now = Date.now();
let that = this;
let _args = args;
if(now - previous > delay){ // 若是时间差大于规定时间,则触发
fun.apply(that, _args)
previous = now
}
}
}复制代码
垃圾回收主要分为:标记清除算法(主流都是这个)与引用计数算法。
将cookie设置成HttpOnly是为了防止XSS攻击,窃取cookie内容,这样就增长了cookie的安全性。
把cookie设置为secure,只保证 cookie 与服务器之间的数据传输过程加密复制代码
6、渲染机制及重绘和回流
浏览器的渲染机制通常分为如下几个步骤:
回流一定会发生重绘,重绘不必定会引起回流。
浏览器优化:
现代浏览器大多都是经过队列机制来批量更新布局,浏览器会把修改操做放在队列中,至少一个浏览器刷新(即16.6ms)才会清空队列,但当你获取布局信息的时候,队列中可能有会影响这些属性或方法返回值的操做,即便没有,浏览器也会强制清空队列,触发回流与重绘来确保返回正确的值。
主要包括如下属性或方法:
offsetTop
、offsetLeft
、offsetWidth
、offsetHeight
scrollTop
、scrollLeft
、scrollWidth
、scrollHeight
clientTop
、clientLeft
、clientWidth
、clientHeight
width
、height
getComputedStyle()
getBoundingClientRect()
因此,咱们应该避免频繁的使用上述的属性,他们都会强制渲染刷新队列。
减小重绘与回流:
一、CSS
table
的从新布局。transform
、opacity
、filters
这些动画不会引发回流重绘 。可是对于动画的其它属性,好比background-color
这些,仍是会引发回流重绘的,不过它仍是能够提高这些动画的性能。
避免频繁操做样式,最好一次性重写style
属性,或者将样式列表定义为class
并一次性更改class
属性。
避免频繁操做DOM,建立一个documentFragment
,在它上面应用全部DOM操做
,最后再把它添加到文档中。
避免频繁读取会引起回流/重绘的属性,若是确实须要屡次使用,就用一个变量缓存起来。
<script type="text/javascript">
var pNode,fragment = document.createDocumentFragment();
for(var i=0; i<20; i++){
pNode = document.createElement('p');
pNode.innerHTML = i;
fragment.appendChild(pNode);
}
document.body.appendChild(fragment);
</script>复制代码
documentFragment
节点不属于文档树,所以当把建立的节点添加到该对象时,并不会致使页面的回流。
7、前端安全性XSS 攻击与CSRF攻击
Cross-Site Scripting (跨站脚本攻击)简称XSS,是一种代码注入攻击。攻击者经过在目标网站上注入恶意脚本,使之在用户的浏览器上运行,进而实现攻击。
XSS 常见的注入方法:
javascript:
(伪协议)等可执行代码。background-image:url("javascript:...");
的代码(新版本浏览器已经能够防范)。expression(...)
的 CSS 表达式代码(新版本浏览器已经能够防范)。经常使用防范方法:
对输入(和url参数)进行过滤,对输出进行编码,cookie 设置成 http-only
用户输入、url参数、post 请求参数、ajax
function escape(str) {
str = str.replace(/&/g, '&')
str = str.replace(/</g, '<')
str = str.replace(/>/g, '>')
str = str.replace(/"/g, '&quto;') str = str.replace(/'/g, ''') str = str.replace(/`/g, '`') str = str.replace(/\//g, '/') return str }复制代码
一、验证码;强制用户必须与应用进行交互,才能完成最终请求。此种方式能很好的遏制 csrf,可是用户体验比较差。
二、Referer check;请求来源限制,此种方法成本最低,可是并不能保证 100% 有效,由于服务器并非何时都能取到 Referer,并且低版本的浏览器存在伪造 Referer 的风险。
8、Object.assign 模拟实现
if( typeof Object.assign2 !== 'function' ){
Object.defineProperty(Object, 'assign2', {
value: function(target){
if(!target){
throw new Error('cannot convert undefined or null to object')
}
var to = Object(target)
for(var index = 1; index < arguments.length;index++){
var nextSource = arguments[index]
if(nextSource){
for( var nextKey in nextSource ){
if(Object.prototype.hasOwnProperty.call(nextSource, nextKey)){
to[nextKey] = nextSource[nextKey]
}
}
}
}
return to;
},
writable: true,
configurable: true
})
}复制代码
// 测试用例
let a = {
name: "advanced",
age: 18
}
let b = {
name: "muyiy",
book: {
title: "You Don't Know JS",
price: "45"
}
}
let c = Object.assign2(a, b);
console.log(c);
// {
// name: "muyiy",
// age: 18,
// book: {title: "You Don't Know JS", price: "45"}
// }
console.log(a === c);
// true复制代码
9、vue 记录
通常来讲,vue 组件分红三类:
一、 由vue-router 产生的每一个页面,它本质上也是一个组件(.vue),主要承载当前页面的html 结构,会包含数据获取、数据整理、数据展现等业务操做,在实际项目开发中,咱们写的大部分代码都是这类组件,在协同开发时,每人维护本身的路由页面,不多有交集。这类相对也是最好写的,能完成需求就行。
二、 不包含业务,是个独立、具体的功能基础组件,好比模态框、日期选择器。独立组件的开发难度要高于第一类组件,它侧重点是API的设计、兼容性、性能、以及复杂的功能,也会包含很是多的技巧,好比在不依赖vuex 的状况下,各组件间的通讯。一个具备数据校验功能的输入框。
三、 业务组件,在业务中被多个页面复用,会包含页面元素,通用性要差一些,(依托于项目,可使用项目中的技术栈,如vuex、axios等)。通用弹层
一个再复杂的组件,都是由三部分组成:prop、event、slot 。 Props 最好用对象的写法,这样能够针对每一个属性设置类型、默认值或自定义校验属性值。
10、JavaScript模块化方案
在es6以前,js 并无原生的模块。模块化方案的三个阶段过程:
一、全局变量+命名空间 (window.XX ,以及自执行函数等操做)
二、AMD&commonjs 各种规范带到前端
AMD模块相似:
define(function(require){
const bar = require('./bar')
return function(){}
})复制代码
commonJs 规范,它本不适合浏览器环境,但依赖现代打包工具进行转换以后就能够在浏览器中执行。commonjs 规范格式更加简洁,(nodejs 模块正在使用的就是commonjs 规范)
const bar = require('./bar')
module.exports = function(){
// ....
}复制代码
三、es6模块
模块化方案
import bar from './bar'
export default function(){
// ...
}复制代码
11、webpack 与gulp 有什么本质区别
gulp 是工具链,构建工具,能够配合各类插件作js 压缩,css 压缩,less 压缩,替代手工实现自动化工做。 一、 构建工具 二、自动化、三、提升效率
webpack 是文件打包工具,把项目的各类js ,css 打包合并成一个或多个文件,主要用于模块化打包。一、打包工具 二、模块化识别 三、编译模块代码 四、代码拆分五、模块热更新。
12、经常使用es6 以及es6 规范
到时候移到掘金
https://blog.csdn.net/u010427666/article/details/54944986
十3、seo 相关知识以及如何优化
文档&文章连接
十4、内部原型继承原理
需从新整理
https://blog.csdn.net/u010427666/article/details/53244698
十5、你须要知道的css
css 动画、flex 布局等
https://juejin.im/post/5c7646e2f265da2d8e70f681
十5、性能优化点
代码层面、网络层面、打包依赖等
https://segmentfault.com/a/1190000008273435
十6、浏览器缓存机制(强缓存&协商缓存)
是否过时根据header中的Cache-Control和Expires来判断,(缓存过时后Etag 与last-modify 是由服务器来判断)
nginx 开启强缓存
location ~ ^/static/.*(jpg|jpeg|png|gif|ico|js|css|ttf)$ {
root /home/service/www/web;
expires 12h;
add_header Cache-Control "public";
}
复制代码
nginx 开启gizp 压缩(压缩效率特高)
gzip on; #开启gzip压缩输出
gzip_min_length 1k; #最小压缩文件大小
gzip_buffers 4 16k; #压缩缓冲区
# gzip_http_version 1.0; #压缩版本(默认1.1,前端若是是squid2.5请使用1.0)
gzip_comp_level 3; #压缩等级
gzip_types text/plain application/javascript application/x-javascript text/css application/xml;
gzip_vary on;
gzip_disable "MSIE [1-7]\.";
复制代码
十7、数组乱序
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
arr.sort(function () {
return Math.random() - 0.5;
});
复制代码
洗牌算法:
function shuffle (arr) { var len = arr.length for (var i = 0;i < len - 1;i++) { var idx = Math.floor(Math.random() * (len - i)) var temp = arr[idx] arr[idx] = arr[len - i - 1] arr[len - i - 1] = temp } return arr}复制代码
十8、BFC(块级格式化上下文)
产生BFC:
BFC 做用:
一、 清除浮动,即在容器中建立BFC
二、致使外边距折叠塌陷
咱们必须记住的是外边距折叠(Margin collapsing)只会发生在属于同一BFC的块级元素之间。若是它们属于不一样的 BFC,它们之间的外边距则不会折叠。因此经过建立一个不一样的 BFC ,就能够避免外边距折叠。
https://segmentfault.com/a/1190000013647777
十9、单线程的JavaScript引擎是怎么配合浏览器内核处理这些定时器和响应浏览器事件的呢?
一、单线程,多进程
答案:promise 、console、setTimeout
答案:1,7,6,8,2,4,3,5,9,11,10,12
https://www.cnblogs.com/joyco773/p/6038022.html
http://www.xuanfengge.com/js-realizes-precise-countdown.html
https://segmentfault.com/a/1190000014940904
二10、websocket 实时推送
相关连接: https://juejin.im/post/5c20e5766fb9a049b13e387b
二11、http2.0的新特性有哪些?(选项是多路复用、头部压缩、设置优先级、服务端推送、二进制传输)
相关连接: https://juejin.im/post/5c8f30606fb9a070ef60996d
http2.0 /http1.0 302 与304 的区别 206
二12、讲解一下https 的工做原理(握手过程)
HTTPS在传输数据以前须要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程当中将确立双方加密传输数据的密码信息。TLS/SSL协议不只仅是一套加密传输的协议,更是一件通过艺术家精心设计的艺术品,TLS/SSL中使用了非对称加密,对称加密以及HASH算法。握手过程的简单描述以下:
[copy连接](github.com/airuikun/We…)
[热更新原理](zhuanlan.zhihu.com/p/30669007)
vue 3.0 新特性
目前,Vue 的反应系统是使用 Object.defineProperty
的 getter 和 setter。 Vue 3 将使用 ES2015 Proxy 做为其观察者机制。 这消除了之前存在的警告,使速度加倍,并节省了一半的内存开销。
为了继续支持 IE11,Vue 3 将发布一个支持旧观察者机制和新 Proxy 版本的构建。
二十3、前端代码日志收集
思路:
参照:
别人优质汇总:
https://juejin.im/post/5c64d15d6fb9a049d37f9c20
**3-5年内部岗位(平安、乐信、500万、vivo、oppo)推荐机会,欢迎发简历到: zgxie@126.com**