目录
盒子模型
什么是盒子模型?盒子模型分为哪几种?它们分别有什么特点?
1.内容content+内边距padding+边框border+外边距margin
2.IE盒模型border-box和普通盒模型content-box
3.content-box 的width=content;border-box的width=content+padding+border
样式优先级
1.内联式 > 嵌入式 > 外部式
2.内联样式 > id选择器样式 > 类选择器样式 > 元素选择器样式
3.!important与以上的选择器相遇时,强制使用此样式
深拷贝和浅拷贝
【参考文章:https://www.cnblogs.com/echolun/p/7889848.html】
function deepClone(obj){
let _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone
}
let a=[0,1,[2,3],4],
b=deepClone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
利用JSON对象的parse和stringify可以代替下面的深度克隆函数里的代码
JS深度克隆
定义一个函数,让对象深度克隆。
需要实现一个对象类型判断函数
const isType = (obj, type) => {
if (typeof obj !== 'object') return false;
// 判断数据类型的经典方法:
const typeString = Object.prototype.toString.call(obj);
let flag;
switch (type) {
case 'Array':
flag = typeString === '[object Array]';
break;
case 'Date':
flag = typeString === '[object Date]';
break;
case 'RegExp':
flag = typeString === '[object RegExp]';
break;
default:
flag = false;
}
return flag;
};
深度克隆函数
const clone = parent => {
// 维护两个储存循环引用的数组
const parents = [];
const children = [];
const _clone = parent => {
if (parent === null) return null;
if (typeof parent !== 'object') return parent;
let child, proto;
if (isType(parent, 'Array')) {
// 对数组做特殊处理
child = [];
} else if (isType(parent, 'RegExp')) {
// 对正则对象做特殊处理
child = new RegExp(parent.source, getRegExp(parent));
if (parent.lastIndex) child.lastIndex = parent.lastIndex;
} else if (isType(parent, 'Date')) {
// 对Date对象做特殊处理
child = new Date(parent.getTime());
} else {
// 处理对象原型
proto = Object.getPrototypeOf(parent);
// 利用Object.create切断原型链
child = Object.create(proto);
}
// 处理循环引用
const index = parents.indexOf(parent);
if (index != -1) {
// 如果父数组存在本对象,说明之前已经被引用过,直接返回此对象
return children[index];
}
parents.push(parent);
children.push(child);
for (let i in parent) {
// 递归
child[i] = _clone(parent[i]);
}
return child;
};
return _clone(parent);
};
前端性能优化
前端性能优化的方案有哪些?
减少HTTP请求、使用CDN、添加Expires头、压缩组件、将样式表放在头部、将脚本放在底部、避免CSS表达式、使用外部的JavaScript和CSS、减少DNS查找、精简JavaScript、避免重定向、删除重复脚本、配置ETag、使Ajax可缓存。
水平垂直居中
使未知宽高的child子元素在father父元素中水平垂直居中的方法有哪些?
1.显示设置父元素为:table,子元素为:table-cell,这样就可以使用vertical-align: middle,text-align: center
2.使用一个空标签span设置他的vertical-align基准线为中间,并且让它为inline-block,宽度为0
3.父元素position非static,子元素绝对定位,top 50%,left50%,然后使用css3 transform:translate(-50%; -50%)
4.使用css3 flex布局:父元素display:flex; 子元素margin:auto;
<li>标签
li与li之间有看不见的空白间隔是什么原因引起的?有什么解决办法?
当<li>
标签设置为display:inline-block时,会出现看不见的空白间隔。
引起这种空白间隔的原因:
浏览器的默认行为是把inline元素间的空白字符(空格换行tab)渲染成一个空格,也就是我们上面的代码<li>
换行后会产生换行字符,而它会变成一个空格,当然空格就占用一个字符的宽度。
解决方案:
1.既然是因为<li>
换行导致的,那就可以将<li>
代码全部写在一排;
2.<ul>
内的字符尺寸直接设为0
3.在Safari浏览器方法2依然出现间隔空白,所以设置.wrap ul{letter-spacing: -5px;},然后设置li内字符间隔.wrap ul li{letter-spacing: normal;}
经典的Foo和getName
【参考文章:https://www.cnblogs.com/laojun/p/8287399.html】
JS中的this
function a(xx){
this.x=xx;
return this
};
var x=a(5);
var y=a(6);
//写出以下代码的输出结果
console.log(x.x);
console.log(y.x);
答案是undefined 6
原因:【参考文章:https://segmentfault.com/q/1010000018487598】
1.在全局环境中使用var x,相当于给window添加x属性
2.执行var x = a(5),在function中给x赋值为5,但是将this返回给它本身,则导致它又等于window,此时x === x.x === x.x.x === ... === window,按照理论来说只要你能输出所有的x.x,那应该能有机会看到5,但这本身是一个无限循环
3.至于y为何没有undefined,原因是它没有和x变量同名
清除浮动的方法
【参考文章:https://www.cnblogs.com/nxl0908/p/7245460.html 】
跨域
1、什么是同域?是指域名相同,端口相同,协议相同。
2、什么是同源策略?
同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以a.com下的js脚本采用ajax读取b.com里面的文件数据是会报错的。
不受同源策略限制的:
1、页面中的链接,重定向以及表单提交是不会受到同源策略限制的。
2、跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的<script src="..."></script>,<img>,<link>,<iframe>等。
3、什么是跨域?是指一个域下的文档或脚本试图去请求另一个域下的资源。
4、跨域方法?
1、 通过jsonp跨域
2、 document.domain + iframe跨域
3、 location.hash + iframe
4、 window.name + iframe跨域
5、 postMessage跨域
6、 跨域资源共享(CORS)
7、 nginx代理跨域
8、 nodejs中间件代理跨域
9、 WebSocket协议跨域
TCP与UDP
tcp和udp的区别?
1.tcp面向连接;udp无连接。
2.tcp提供可靠的服务;udp尽最大努力交付,不保证可靠交付。
3.udp具有较好的实时性,工作效率比tcp高。
4.tcp连接是点对点;udp可支持一对一、一对多、多对一的交互通信。
5.tcp对系统资源要求较多,udp较少。
tcp是如何确保可靠性的?
tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
设计模式
单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
简单工厂模式:定义一个用于创建对象的接口。
工厂方法模式:是简单工厂模式的衍生,解决了许多简单工厂模式的问题。
抽象工厂模式:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
多态
定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。
多态存在的三个必要条件:1.要有继承;2.要有重写;3.父类引用指向子类对象。
重载和重写
重载:重载字面意思多次的意思,也就是同一个方法实现多个不同的逻辑,并可以在同一个类中可以实现。其实现的原理是,方法名相同,参数的个数或者类型不同即可。
重写:重写就是要重新去写(实现),一个类中不可能两个定义一样的方法。因此,重写就是子类对父类定义的方法重新实现一次。
闭包
闭包就是定义在函数中的函数。
闭包的两大作用:一个是读取函数中的变量,另外一个是将函数中的变量的值存储于内存中。
闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
JS的数据类型
【参考文章: https://www.cnblogs.com/starof/p/6368048.html】
原型链
【参考文章: https://www.jianshu.com/p/dee9f8b14771】
var o1 = {};
var o2 =new Object();
var o3 = new f1();
function f1(){};
var f2 = function(){};
var f3 = new Function('str','console.log(str)');
console.log(typeof Object); //function
console.log(typeof Function); //function
console.log(typeof f1); //function
console.log(typeof f2); //function
console.log(typeof f3); //function
console.log(typeof o1); //object
console.log(typeof o2); //object
console.log(typeof o3); //object
【参考文章: https://blog.youkuaiyun.com/u010365819/article/details/81326349】
第一题:
person1.__proto__
是什么?
因为person1.__proto__ === person1 的构造函数.prototype
因为person1的构造函数 === Person
所以person1.__proto__ === Person.prototype
第二题:
Person.__proto__
是什么?
因为Person.__proto__ === Person的构造函数.prototype
因为Person的构造函数 === Function
所以Person.__proto__ === Function.prototype
第三题:
Person.prototype.__proto__
是什么?Person.prototype
是一个普通对象,我们无需关注它有哪些属性,只要记住它是一个普通对象。
因为一个普通对象的构造函数 === Object
所以Person.prototype.__proto__ === Object.prototype
第四题:
Object.__proto__
是什么? 参照第二题,因为 Person 和 Object 一样都是构造函数第五题:
Object.prototype__proto__
是什么?Object.prototype
对象也有proto属性,但它比较特殊,为 null 。因为 null 处于原型链的顶端,这个只能记住。Object.prototype.__proto__ === null
快速排序
【参考文章:https://blog.youkuaiyun.com/adusts/article/details/80882649】
冒泡排序
xml和json的区别
【参考文章:https://www.cnblogs.com/SanMaoSpace/p/3139186.html】
时间复杂度
数据结构
数据结构有哪些?
数组、栈、队列、链表、树、图、堆、散列表。
==和===的区别
==用于一般比较,===用于严格比较,==在比较的时候可以转换数据类型,===严格比较,只要类型不匹配就返回flase。
举例说明:
"1" == true类型不同,"=="将先做类型转换,把true转换为1,即为 "1" == 1;此时,类型仍不同,继续进行类型转换,把"1"转换为1,即为 1 == 1。
1.如果比较:"1" === true 左侧为字符型,右侧为bool布尔型或int数值型,左右两侧类型不同,结果为false;2.如果比较: 1 === 1 左侧为int数值型,右侧为int数值型,左右两侧类型相同,数值大小也相同,结果为true;
3.如果比较: 1 === 2 左侧为int数值型,右侧为int数值型,左右两侧类型相同,但数值大小不同,结果为false。
typeOf和instanceOf的区别