CSS
【】css盒模型
html元素都可以看成是一个盒子,盒模型就是用来设计和布局时使用。
**盒模型主要包括:**外边距(margin)、边框(border)、内边距(padding)、内容(content)
**盒模型又分为两种:**标准盒模型(content-box)、怪异盒模型(border-box)
**标准盒模型(默认):**width就是content的内容,所以计算标准盒模型的总长/宽=margin+border+padding+width
**怪异盒模型/IE盒模型:**width就是content+border+padding的宽度,所以计算怪异盒模型的总长/宽=margin+width
【】em、rem、px的区别
【】display:none和visibility:hidden、opcaity
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5bDVqNMw-1636353995044)(面试回答总结.assets/1626676642190.png)]
HTML
【】DOCTYPE是什么,作用是什么
DOCTYPE文档类型,作用是告知浏览器以哪种方式解析html
DOCTYPE有3种类型:Strict、transitional、Frameset
如果不制定DOCTYPE,浏览器默认使用混杂模式
其中的DTD(例如上例中的xhtml1-transitional.dtd)叫文档类型定义,里面包含了文档的规则,浏览器就根据你定义的DTD来解释你页面的标识,并展现出来。
过渡的(Transitional):要求非常宽松的DTD,它允许你继续使用HTML4.01的标识(但是要符合xhtml的写法)
严格的(Strict):要求严格的DTD,你不能使用任何表现层的标识和属性,例如
框架的(Frameset):专门针对框架页面设计使用的DTD,如果你的页面中包含有框架,需要采用这种DTD
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
// 可简写如下
<!DOCTYPE html>
【】link和@import的区别
- link是html标签,@import是css提供的一种方式
- @import有兼容性要求(IE5+)
- link引入的资源在解析html时到了这个位置就会加载,而@import引入的资源是在html解析完成后才下载
- link引入的资源种类可以是css文件,还有rel连接属性等,而@import只能引入css文件
【】如何禁止页面的缩放
在meta中添加content="user-scalable=no"即可防止浏览器被放大
maximum-scale、minimum-scale控制允许用户以怎样的方式放大或缩小页面
【】如何防止浏览器的js或css缓存
引入js或css时生成唯一版本号
引入的路径后面加上?time='xxxx'
【】css兼容各版本浏览器的前缀
浏览器 | 前缀 | 内核 |
---|---|---|
IE | -ms- | Trident |
Chrome、Safari | -webkit- | webkit |
firefox | -moz- | Gecko |
Opera | -o- | Blink |
JS
【】js的事件处理机制
js的事件处理机制可以分为3个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段
- 事件捕获阶段:document发出事件流从document节点开始往下一层层查找(IE没有这个阶段)
- 处于目标阶段:事件流到达响应事件所在节点,并执行同名函数
- 事件冒泡阶段:事件流从目标节点往document节点一层层冒泡,如果遇到与目标函数同名函数则会被触发
捕获:html->body->TARGE
冒泡:TARGE->body->html
【】es6的了解,有哪些新内容
- 新增let\const 声明方式
- 箭头函数
- 解构(数组解构和对象解构)
- Promise
- Class,继承的显示化
- 新增Symbol数据类型
- Set和Map集合
- 字符串模板
- Generator生成器
- 函数参数默认值
- 11.函数参数简写即字面量提升
【】promise的用法
promise 是一个异步构造函数,是一种异步编程的解决方案。
使用方式:将异步方法封装成promise对象,借助promise的回调函数提高编程可读性,以及promise的一些原型函数简化了我们的编程。
使用场景:
1.有2个函数,要同时比较这两个函数的结果再执行后面的操作,可以使用promise.all();
promise.all()可以并行执行多个异步函数,then()中获取所有异步函数执行完成的结果
2.可以使用promise. Ace()可以阻塞多个接口的回调,只返回最快执行的接口的结果。
【】js原型链的理解
原型:任何javascript对象都有一个prototype或_proto_属性指向它的构造函数的prototype
**我理解的原型链:**其实就是javascript的继承机制,是指获取JavaScript对象的属性会顺着其_proto_的指向寻找,直至找到Object.prototype上
【-】this的作用域
this指向调用该函数的对象。如果是箭头函数,this指向外层的对象,全局环境下this指向window
【】cookie、session和localStorage的区别
感觉解释的不好
- cookie:服务端生成放在客户端存储,HTTP请求时会明文携带,有长度限制,4k左右,需手动清除,操作需开发人员手动封装。支持跨域名访问
- session:服务端存储,生命周期为一个会话,不支持跨域访问安全性高。
- localStorage:是为了解决cookie的弊端生成的,长度限制为5M,具体根据浏览器不同,长期有效,需手动清除,有封装好的API使用,setItem,getItem等
闭包的理解
手写一个Array.map的实现
/**
* 手写实现map
* @param fn
* @returns {[]}
*/
export function myMap(fn) {
let newArr = [];
for (let i = 0; i < this.length; i++) {
fn(this[i], i, this);
newArr.push(this[i]);
}
return newArr;
}
//使用方式
Array.prototype.myMap = myMap;
let arr = [];
arr.myMap(item => {});
js的事件循环机制
防抖和节流的区别及实现
/**
* 防抖
* @param fn
* @param timer
* @returns {function(...[*]=)}
*/
export const debounce = (fn, timer = 500) => {
let timeout = null;
return function() {
if (timeout) {
clearTimeout(timeout);
timeout = setTimeout(() => {
let args = arguments;
fn.apply(this, args);
}, timer);
}
};
};
/**
* 节流
* @param fn
* @param timer
* @returns {function(...[*]=)}
*/
export const throttle = (fn, timer = 500) => {
let timeout = null;
let prev = null;
return function() {
if (prev) {
return;
}
prev = true;
timeout = setTimeout(() => {
let args = arguments;
fn.apply(this, args);
prev = null;
clearTimeout(timeout);
}, timer);
};
};
手写实现深克隆
/**
* 深拷贝
* @param obj
* @returns {[]|{}}
*/
export function deepClone(obj) {
let cloneObj = typeof obj === 'object' ? (Array.isArray(obj) ? [] : {}) : obj;
if (typeof obj === 'object') {
for (let target in obj) {
if (typeof obj[target] === 'object') {
cloneObj[target] = deepClone(obj[target]);
} else {
cloneObj[target] = obj[target];
}
}
}
return cloneObj;
}
【】浏览器
- 输入网址到页面渲染的过程
- 遇到的浏览器兼容的问题
- 浏览器的事件处理机制
- 不同浏览器的内核及css属性前缀
其他
- tcp/ip的三次握手、四次挥手
- http协议与https协议的区别
- 在项目中遇到了哪些问题,怎么解决的
- 前端优化
【】http协议与https协议的区别
**HTTP:**是最广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
**HTTPS:**是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。(Secure Sockets Layer)
**HTTPS协议的主要作用可以分为两种:**一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。
HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
【面经】2 年前端 7~9 月面试经历总结
es next 最新规范
- ECMAScript:一个由 ECMA International 进行标准化,TC39 委员会进行监督的语言。通常用于指代标准本身。
- JavaScript:ECMAScript 标准的各种实现的最常用称呼。这个术语并不局限于某个特定版本的 ECMAScript 规范,并且可能被用于任何不同程度的任意版本的 ECMAScript 的实现。
- ECMAScript 5 (ES5):ECMAScript 的第五版修订,于 2009 年完成标准化。这个规范在所有现代浏览器中都相当完全的实现了。
- ECMAScript 6 (ES6) / ECMAScript 2015 (ES2015):ECMAScript 的第六版修订,于 2015 年完成标准化。这个标准被部分实现于大部分现代浏览器。可以查阅这张兼容性表来查看不同浏览器和工具的实现情况。
- ECMAScript 2016:预计的第七版 ECMAScript 修订,计划于明年夏季发布。这份规范具体将包含哪些特性还没有最终确定
- ECMAScript Proposals:被考虑加入未来版本 ECMAScript 标准的特性与语法提案,他们需要经历五个阶段:Strawman(稻草人),Proposal(提议),Draft(草案),Candidate(候选)以及 Finished (完成)。
ES NEXT 最新的/ es2021新特征
-
string的新方法 replace.all
'大海星辰,星辰大海'.replaceAll('星辰','满眼星辰') // "大海满眼星辰,满眼星辰大海"
-
数值分隔符
贫穷限制了0的的认知,数的好心累,es2021为了大家方便,添加了下面的写法,以下划线(_)任意个数分割
1_6000_0000 // 160000000 160_000_000 // 160000000
-
新的内置对象WeakRef
WeakRef对象允许您保留对另一个对象的弱引用,而不会阻止被弱引用对象被GC回收
尽量别用 -
逻辑运算符与赋值表达式
let num = 5 num+=10 console.log(num) // 15 let a; let b=100; a||=b; //a=a||b; 等价于:if(a== 0|| a === "" ||a=== false ||a === null ||a=== undefined){a=b} a&&=b; // a=a&&b; 等价于: if(a) {a=b} a??=b; //a=a??b ; 等价于: if(a===null||a===undefined){a=b}
-
promise.any
类似于Promise.all和Promise.race,又区别于他们
Promise.any,接收一个可迭代对象,当有一个promise 成功,就会返回那个已经成功的promise
如果可迭代对象中没有一个promise成功,才会返回一个失败的promise和AggregateError类型的实例,他是Error的一个子类,用于把单一的错误集合在一起。const addRemote = async (a, b) => new Promise((resolve,reject) => { setTimeout(() => reject(), 1000) }) let promise1=addRemote(1,2) let promise2=addRemote(1,3) let promise3=addRemote(1,4) Promise.any([promise1,promise2,promise3]).then(res=>{ console.log(res,'成功') }).catch(err=>{ console.log(err,'失败') }) // test.html:26 AggregateError: All promises were rejected "失败"
应用场景:
从最快的服务器检索资源
来自世界各地的用户访问网站,如果有多个服务器,尽可能使用响应速度最快的服务器,在这种情况下使用Promise.any()方法体验最佳
Promise.all 一个失败,就是失败,有成功也是失败
Promise.any一个成功,就是成功,有失败也是成功
Promise.race谁快算谁的,不管成功或者失败,第一个结果就是最终结果。可以处理超时
new的过程
js高频面试题:new的过程发生了什么?手写new的实现代码
- 创建一个空对象,并且this变量引用该对象同时还继承了该函数的原型prototype
- 属性和方法被加入到this引用的对象中
- 最后如果没有return就隐式返回this
手写类似new的函数
// 实现类似new的函数,接受一个构造函数作为第一个参数
function create () {
let obj = {}
// 获取构造函数
let Constru = [].shift.call(arguments)
obj.__proto__ = Constru.prototype
// 其他参数
let result = Constru.apply(obj, arguments)
return result instanceof Object ? result : obj
}
以下是对实现的分析:
- 首先我们创建一个空对象obj
- 获取传入的构造函数
- 设置空对象的原型
- 绑定this到空对象obj
- 确保返回值为对象
完整例子
function Car(year, color, model) {
this.year = year;
this.color = color;
this.model = model;
}
Car.prototype.getYear = function(){
return this.year;
}
// objectFactory 函数来模拟用 new创建对象
var objectFactory = function(){
var obj = new Object(); // 克隆一个空对象;
Constructor = [].shift.call(arguments); // 获取外部传入的构造器,此例子是Car
obj.__proto__ = Constructor.prototype; // 指向正确的原型,使得obj.__proto__ 指向 Car.prototype,而不是原来的 Object.prototype。
var ret = Constructor.apply(obj, arguments); // 借用外部的构造器给obj设置属性
return typeof ret === 'object' ? ret : obj; // 确保构造器总是返回一个对象
}
// 验证
var car1 = objectFactory(Car, 2020);
console.log(car1.year); // 输出: 2020
console.log(car1.getYear()); // 输出: 2020
console.log( Object.getPrototypeOf( car1 ) === Car.prototype ); // 输出: true
和通过字面量创建对象的区别
对于对象来说,其实都是通过new产生的,无论是function Foo() 还是 let a = { b: 1}
对于创建一个简单对象来说,更推荐使用字面量的形式创建对象(无论是从性能上还是可读性上)。因为使用new Object() 的方式创建对象需要通过作用域链一层层找到Object, 但是你使用字面量形式就没有这个问题。但是对于复杂对象,以及涉及到继承关系时,最好还是用new
new存在的意义
通过new产生原对象的一个实例对象,而这个实例继承了原对象的属性和方法,new存在的意义在于它实现了JS中的继承,而不仅仅是实例化了一个对象!
bind实现方式
if (!Function.prototype.bind) {
Function.prototype.bind = function () {
var self = this, // 保存原函数
context = [].shift.call(arguments), // 保存需要绑定的this上下文
args = [].slice.call(arguments); // 剩余的参数转为数组
return function () { // 返回一个新函数,(arguments是返回函数的参数
self.apply(context,[].concat.call(args, [].slice.call(arguments)));
}
}
}
解析:
简单点理解,bind 就是用来绑定上下文的,强制将函数的执行环境绑定到目标作用域中去。与 call 和 apply 其实有点类似,但是不同点在于,它不会立即执行,而是返回一个函数。因此我们要想自己实现一个 bind 函数,就必须要返回一个函数,而且这个函数会接收绑定的参数的上下文。
闭包
「函数」和「函数内部能访问到的变量」(也叫环境)的总和,就是一个闭包。
我们首先知道闭包有3个特性:
①函数嵌套函数
②函数内部可以引用函数外部的参数和变量
③参数和变量不会被垃圾回收机制回收
好处
①保护函数内的变量安全 ,实现封装,防止变量流入其他环境发生命名冲突
②在内存中维持一个变量,可以做缓存(但使用多了同时也是一项缺点,消耗内存)
③匿名自执行函数可以减少内存消耗
坏处
①其中一点上面已经有体现了,就是被引用的私有变量不能被销毁,增大了内存消耗,造成内存泄漏,解决方法是可以在使用完变量后手动为它赋值为null;
②其次由于闭包涉及跨域访问,所以会导致性能损失,我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响
类型判断
基本数据类型:Undefined、Null、Boolean、Number、String,Symbol
引用数据类型 :Object
- typeof
console.log(typeof bool); //boolean
console.log(typeof num);//number
console.log(typeof str);//string
console.log(typeof und);//undefined
console.log(typeof nul);//object
console.log(typeof arr);//object
console.log(typeof obj);//object
console.log(typeof fun);//function
console.log(typeof s1); //symbol
typeof可以识别出基本类型boolean,number,undefined,string,symbol,但是不能识别null。不能识别引用数据类型,会把null、array、object统一归为object类型,但是可以识别出function。
所以typeof可以用来识别一些基本类型。
- instanceof
console.log(bool instanceof Boolean);// false
console.log(num instanceof Number);// false
console.log(str instanceof String);// false
console.log(und instanceof Object);// false
console.log(nul instanceof Object);// false
console.log(arr instanceof Array);// true
console.log(obj instanceof Object);// true
console.log(fun instanceof Function);// true
console.log(s1 instanceof Symbol);// false
从结果中看出instanceof不能识别出基本的数据类型 number、boolean、string、undefined、null、symbol。
但是可以检测出引用类型,如array、object、function,同时对于是使用new声明的类型,它还可以检测出多层继承关系。
其实也很好理解,js的继承都是采用原型链来继承的。比如objA instanceof A ,其实就是看objA的原型链上是否有A的原型,而A的原型上保留A的constructor属性。
所以instanceof一般用来检测对象类型,以及继承关系。
- construct
console.log(bool.constructor === Boolean);// true
console.log(num.constructor === Number);// true
console.log(str.constructor === String);// true
console.log(arr.constructor === Array);// true
console.log(obj.constructor === Object);// true
console.log(fun.constructor === Function);// true
console.log(s1.constructor === Symbol);//true
null、undefined没有construstor方法,因此constructor不能判断undefined和null。
但是他是不安全的,因为contructor的指向是可以被改变。
- Object.prototype.toString.call
console.log(Object.prototype.toString.call(bool));//[object Boolean]
console.log(Object.prototype.toString.call(num));//[object Number]
console.log(Object.prototype.toString.call(str));//[object String]
console.log(Object.prototype.toString.call(und));//[object Undefined]
console.log(Object.prototype.toString.call(nul));//[object Null]
console.log(Object.prototype.toString.call(arr));//[object Array]
console.log(Object.prototype.toString.call(obj));//[object Object]
console.log(Object.prototype.toString.call(fun));//[object Function]
console.log(Object.prototype.toString.call(s1)); //[object Symbol]
此方法可以相对较全的判断js的数据类型。
一般基本的类型可以选择typeof,引用类型可以使用instanceof。
手写Promise
大厂可能会问