写在开头
转眼到了该实习的时间,或许还是自己不够优秀把,感觉挺搞心态的,我的第一份投递的公司直接就刷了我,我连面试的资格都没有,当时看到“不匹配”三个字的时候,我顿时有点了难受,心态感觉被搞了一下。或许这就是现实把。
然后我独自思考了5分钟后,还是得从自己找找问题,我要想凭什么其它公司就会招我,谁又会愿意找一个萌新然后还要发钱给他呢? 想来还是自己不够优秀,简历上也没什么好多要写的,但是 我的追求不会放弃,我的野心依旧在,可能眼前才能支撑不了我的野心,不如冷静下来沉心学习吧。
接下来的内容,是我这些天自己总结和整理的,关于前端实习面经,当然还会一直更新下去,直到我拿到让自己满意的 Offer !
以下就是本人整理的部分内容,希望对你会有一点帮助,加油吧,追梦的人!
HTML相关
html5有哪些新特性
新特性:
- HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。
- 拖拽释放(Drag and drop) API
- 语义化更好的内容标签(header,nav,footer,aside,article,section)
- 音频、视频API(audio,video)
- 画布(Canvas) API
- 地理(Geolocation) API
- 本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;
- sessionStorage 的数据在浏览器关闭后自动删除
- 表单控件,calendar、date、time、email、url、search
- 新的技术webworker, websocket, Geolocation
html5移除了哪些元素
- 纯表现的元素:basefont,big,center,font, s,strike,tt,u;
- 对可用性产生负面影响的元素:frame,frameset,noframes;
如何处理HTML5新标签的浏览器兼容问题
IE8/IE7/IE6支持通过document.createElement方法产生的标签,
可以利用这一特性让这些浏览器支持HTML5新标签,
当然最好的方式是直接使用成熟的框架、使用最多的是html5shim框架
<!--[if lt IE 9]>
<script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script>
<![endif]-->
如何区分 HTML 和 HTML5
DOCTYPE声明\新增的结构元素\功能元素
JS相关
Var和不Var有啥区别?
在一个函数中Var,在外部是访问不道德,所以我们需要闭包
如果不用Var,就是全局作用域了,外部可以访问,此时的上下文就是window
可迭代,意味着我能够通过 for…in 循环来访问该对象的所有属性. 还能通过 Object.keys() 方法获取该对象的所有属性名.
可修改,意味着我能修改该对象的所有属性的值,通过为这些属性赋予一个新值就能修改: ob.a = 1000;.
可配置,意味着我能修改属性的行为,让该对象的属性都是不可迭代的、不可修改的和不可配置的. 只有可配置的属性才能通过 delete 被删除.
深入:var与不var区别就在可配置属性上,声明一个全局变量,其实是给window增加一个属性,由于window对象是全局对象,默认可不加,全局作用域下,window也可以用this来代替
“delete”不可以删除那些可配置为false的属性,某些内置对象的属性是不可配置的,比如通过变量声明或者函数声明创建的全局对象的属性。
怎么看一个属性是对象自有的还是从原型链继承下来的?
其实就是问in和hasOwnProperty()操作
原型链上继承过来的属性无法通过hasOwnProperty检测到,返回false
in能检测原型链的属性,但for in通常却不行
js对象能带-吗?
Object中的key规定了是字符串,但是加了- 就用不了.调用
因为解释器分不清是不是减号 -
关于闭包的问题
闭包指的是能够访问另一个函数作用域的函数,简单来说,闭包就是一个函数,这个函数能够访问其它函数作用域中的变量。 eg:
function outer() {
var a = '变量1'
var inner = function () {
console.info(a)
}
return inner // inner 就是一个闭包函数,因为他能够访问到outer函数的作用域
}
数组去重
中间件
js有哪些数据类型
6中原始数据类型:
- Number 表示数字类型
- String 表示文本类型
- Null 特指对象的值未设置
- Undefined 没有被赋值的变量的默认值
- Boolean 表示逻辑实体,有true和false两个值
- Symbol 符号(Symbols)是ECMAScript 第六版中定义的。符号类型是唯一的并且不可修改
引用类型:Object
基本数据类型和引用数据类型有什么区别
怎么判断不同的js数据类型
- typeof 操作符:返回一个字符串,表示未经计算的操作数的类型
typeof操作符对于简单数据类型,返回其本身的数据类型,函数对象返回function,其它对象均返回Object
null返回Object - instanceof :用来判断A是否是B的实例,表达式为 A instanceof B,返回值为Boolean类型的值
instanceof 检测的是原型
,只能用来判断两个对象是否属于实例关系,而不能判断一个对象实例具体属于哪种类型。
let a = [];
a instanceof Array // true
a instanceof Object // true
变量a的_proto_直接指向Array.prototype,间接指向Object.prototype,,按照instanceof的判断规则,a就是Object的实例。针对数组的这个问题,ES5提供了Array.isArray()方法。该方法确认某个对象本身为Array
类型
- constructor:当一个函数被定义时,js引擎会为其添加prototype原型,然后在prototype上添加一个constructor属性,并让其指向该函数的引用
null
和undefined
是无效的对象,因此不会有constructor存在,需要通过其它方式来判断。
函数的constructor是不稳定的,主要体现在自定义对象上,当开发者重写prototype
后,原有的constructor引用会丢失,constructor会默认为Object
function F() {};
var f = new F;
f.constructor == F // true
F.prototype = {a: 1}
var f = new F
f.constructor == F // false
在构造函数F.prototype没有被重写之前,构造函数F就是新创建对象f的数据类型。当F.prototype被重写之后,原有的constructor引用被丢失,默认为Object
因此,为了规范开发,在重写对象原型时一般都需要重新给constructor赋值,以保证对象实例的类型不被篡改
- tostring :Object的原型方法,默认返回当前对象的【class】。这是一个内部属性,其格式为[Object xxxx] ,其中xxxx就是对象的类型
Object.prototype.toString.call('') ; // [object String]
Object.prototype.toString.call(11) ; // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call([]) ; // [object Array]
undefined和null有什么区别
null 表示没有对象,即该出不该有值
典型用法:
- 作为函数的参数,表示该函数的参数不是对象
- 作为对象原型链的终点
undefined 表示缺少值,就是此处应该有一个值,但是还没有定义
典型用法:
- 变量被声明了,但没有赋值时,就等于undefined
- 调用函数时,应该提供的参数没有提供时,该参数等于undefined
- 对象没有赋值的属性,该属性的值为undefined
- 函数没有返回值时,默认返回undefined
== 和 === 的区别
“==” 就代表会先把两端的变量试图转换成相同类型,然后再比较;
“===” 就代表会直接去比较类型是否相同,如果类型相同则继续比较值是否相同。
举个栗子:
使用 typeof bar === “object” 来确定 bar 是否是对象的潜在陷阱是什么?如何避免这个陷阱?
尽管 typeof bar === “object” 是检查 bar 是否对象的可靠方法,令人惊讶的是在JavaScript中 null 也被认为是对象!
因此,令大多数开发人员惊讶的是,下面的代码将输出 true 控制台:
要答全问题,还有其他两件事情值得注意:
- 首先,上述解决方案将返回 false,当 bar 是一个函数的时候。在大多数情况下,这是期望行为,但当你也想对函数返回 true 的话,你可以修改上面的解决方案为:
第二,上述解决方案将返回 true,当 bar 是一个数组(例如,当 var bar = [];)的时候。
在大多数情况下,这是期望行为,因为数组是真正的对象,但当你也想对数组返回 false 时,你可以修改上面的解决方案为:
use strict是什么意思?使用它区别是什么?
use strict是一种ECMAscript 5 添加的(严格)运行模式,这种模式使得 Javascript 在更严格的条件下运行,
使JS编码更加规范化的模式,消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为。
默认支持的糟糕特性都会被禁用,比如不能用with,也不能在意外的情况下给全局变量赋值;
全局变量的显示声明,函数必须声明在顶层,不允许在非函数代码块内声明函数,arguments.callee也不允许使用;
消除代码运行的一些不安全之处,保证代码运行的安全,限制函数中的arguments修改,严格模式下的eval函数的行为和非严格模式的也不相同;
提高编译器效率,增加运行速度;
为未来新版本的Javascript标准化做铺垫。
什么是window对象? 什么是document对象?
-
window对象
在全局作用域中声明的变量、函数都是window对象的属性和方法。
window对象是相对于web浏览器而言的,依赖于浏览器,在浏览器中全局对象指的就是window对象
-
document对象
document对象是window对象的一个属性,是显示于窗口内的一个文档。而window对象则是一个顶层对象,它不是另一个对象的属性。document可以理解为文档,就是你的网页,而window是你的窗口,就是你的浏览器包含的。
区别:
① window 指窗体。document指页面。document是window的一个属性。
② 用户不能改变 document.location(因为这是当前显示文档的位置)。但是,可以改变window.location (用其它文档取代当前文档)window.location本身也是一个对象,而document.location不是对象
数组对象有哪些常用方法
修改器方法:
- pop(): 删除数组的最后一个元素,并返回这个元素
- push():在数组的末尾增加一个或多个元素,并返回数组的新长度
- reverse(): 颠倒数组中元素的排列顺序
- shift(): 删除数组的第一个元素,并返回这个元素
- unshift(): 在数组的开头增加一个或多个元素,并返回数组的新长度
- sort(): 对数组元素进行排序,并返回当前数组
- splice(): 在任意的位置给数组添加或删除任意个元素
访问方法:
- concat(): 返回一个由当前数组和其它若干个数组或者若干个非数组值组合而成的新数组
- join(): 连接所有数组元素组成一个字符串
- slice(): 抽取当前数组中的一段元素组合成一个新数组
- indexOf(): 返回数组中第一个与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1
- lastIndexOf(): 返回数组中最后一个(从右边数第一个)与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1
迭代方法:
- forEach(): 为数组中的每个元素执行一次回调函数,最终返回 undefined
- every(): 如果数组中的每个元素都满足测试函数,则返回 true,否则返回 false
- some(): 如果数组中至少有一个元素满足测试函数,则返回 true,否则返回 false
- filter(): 将所有在过滤函数中返回 true 的数组元素放进一个新数组中并返回
- map(): 返回一个由回调函数的返回值组成的新数组
js有哪几种创建对象的方式
对象字面量
var obj = {}
Object 构造函数
var obj = new Object()
工厂模式
function Person(name, age) {
var o = new Object()
o.name = name;
o.age = age;
o.say = function() {
console.log(name)
}
return o
}
缺点: 每次通过Person创建对象的时候,所有的say方法都是一样的,但是却存储了多次,浪费资源
构造函数模式
function Person(name, age) {
this.name = name
this.age = age
this.say = function() {
console.log(name)
}
}
var person = new Person('hello', 18)
构造函数模式隐试的在最后返回return this
所以在缺少new
的情况下,会将属性和方法添加给全局对象,浏览器端就会添加给window对象,可以根据return this 的特性调用call
或者apply
指定this
原型模式
function Person() {}
Person.prototype.name = 'hanmeimei';
Person.prototype.say = function() {
alert(this.name);
}
Person.prototype.friends = ['lilei'];
var person = new Person();
实现了方法与属性的共享,可以动态添加对象的属性和方法。但是没有办法创建实例自己的属性和方法,也没有办法传递参数
构造函数和原型组合
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.say = function() {
console.log(this.name)
}
var person = new Person('hello')
怎么实现对对象的拷贝(深拷贝和浅拷贝)
浅拷贝
- 拷贝原对象引用
- 可以使用Array.prototype.slice() 来完成对一个数组或对象的浅拷贝
- Object.assign() 方法
深拷贝
- 最常用的方式就是 JSON.parse(JSON.stringfy(目标对象)),缺点就是只能拷贝符合
JSON
数据标准类型的对象
什么是闭包,为什么要使用它
简单来说,闭包就是能够读取其他函数内部变量的函数
function Person() {
var name = 'hello'
function say () {
console.log(name)
}
return say()
}
Person() // hello
由于 JavaScript 特殊的作用域,函数外部无法直接读取内部的变量,内部可以直接读取外部的变量,从而就产生了闭包的概念
用途:
最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中
注意点:
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露
作用域的概念
内部环境可以通过作用域链来访问外部环境的属性和方法,但是,外部环境不能访问内部环境的任何属性和方法。注意,只能通过定义函数来延长作用域链条。
作用域链的作用主要用于查找标识符,当作用域需要查询变量的时候会沿着作用域链依次查找,如果找到标识符就会停止搜索,否则将会沿着作用域链依次向后查找,直到作用域链的结尾。
介绍一下js中的原型,原型链,它们有何特点
首先明确一点,JavaScript 是基于原型的
每个构造函数(constructor)都有一个原型对象(prototype),原型对象都包含一个指向构造函数的指针,而实例(instance)都包含一个指向原型对象的内部指针.
图解:
- 每一个构造函数都拥有一个prototype属性,这个属性指向一个对象,也就是原型对象
- 原型对象默认拥有一个constructor属性,指向指向它的那个构造函数
- 每个对象都拥有一个隐藏的属性[[prototype]],指向它的原型对象
什么是原型链:
JavaScript中所有的对象都是由它的原型对象继承而来。而原型对象自身也是一个对象,它也有自己的原型对象,这样层层上溯,就形成了一个类似链表的结构,这就是原型链
所有原型链的终点都是Object函数的prototype属性。Objec.prototype指向的原型对象同样拥有原型,不过它的原型是null,而null则没有原型
清楚了原型链的概念,我们就能更清楚地知道属性的查找规则,比如前面的 p 实例属性.如果自身和原型链上都不存在这个属性,那么属性最终的值就是 undefined ,如果是方法就会抛出错误
js如何实现继承
原型链继承
function Animal() {}
Animal.prototype.name = 'cat'
Animal.prototype.age = 1
Animal.prototype.say = function() {console.log('hello')}
var cat = new Animal()
cat.name // cat
cat.age // 1
cat.say() // hello
最简单的继承实现方式,但是也有其缺点
- 来自原型对象的所有属性被所有实例共享
- 创建子类实例时,无法向父类构造函数传参
- 要想为子类新增属性和方法,必须要在new语句之后执行,不能放到构造器中
构造继承
function Animal() {
this.species = "动物"
}
function Cat(name, age) {
Animal.call(this)
this.name = name
this.age = age
}
var cat = new Cat('豆豆', 2)
cat.name // 豆豆
cat.age // 2
cat.species // 动物
使用 call 或 apply 方法,将父对象的构造函数绑定在子对象上.
组合继承
function Animal() {
this.species = "动物"
}
function Cat(name){
Animal.call(this)
this.name = name
}
Cat.prototype = new Animal() // 重写原型
Cat.prototype.constructor = Cat
如果没有Cat.prototype = new Animal()这一行,Cat.prototype.constructor是指向Cat的;加了这一行以后,Cat.prototype.constructor指向Animal.这显然会导致继承链的紊乱(cat1 明明是用构造函数Cat生成的),因此我们必须手动纠正,将Cat.prototype对象的constructor值改为Cat
extends 继承 ES6 新增继承方式,Class 可以通过 extends 关键字实现继承
class Animal {
}
class Cat extends Animal {
constructor() {
super();
}
}
使用 extends 实现继承,必须添加 super 关键字定义子类的 constructor,这里的super() 就相当于 Animal.prototype.constructor.call(this)
new操作符具体做了什么
- 创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型
- 属性和方法被加入到 this 引用的对象中
- 新创建的对象由 this 所引用,并且最后隐式的返回 this
同步和异步的区别,怎么异步加载 JavaScript
同步模式
又称为阻塞模式,javascript 在默认情况下是会阻塞加载的。当前面的 javascript 请求没有处理和执行完时,会阻止浏览器的后续处理
异步模式
异步加载又叫非阻塞,浏览器在下载执行 js 同时,还会继续进行后续页面的处理
异步加载 JavaScript
- 动态添加 script 标签
- defer
- async
defer属性和async都是属于 script 标签上面的属性,两者都能实现 JavaScript 的异步加载。不同之处在于:async 在异步加载完成的时候就马上开始执行了,defer 会等到 html 加载完毕之后再执行
跨域问题的产生,怎么解决它
由于浏览器的 同源策略,在出现 域名、端口、协议有一种不一致时,就会出现跨域,属于浏览器的一种安全限制。
解决跨域问题有很多种方式,常用的就是以下几种:
- jsonp 跨域:动态创建script,再请求一个带参网址实现跨域通信.缺点就是只能实现 get 一种请求
- document.domain + iframe跨域:两个页面都通过js强制设置document.domain为基础主域,就实现了同域.但是仅限主域相同,子域不同的跨域应用场景
- 跨域资源共享CORS:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置
- nginx反向代理接口跨域:同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题
- WebSocket协议跨域
谈谈对 this 的理解
在 JavaScript 中,研究 this 一般都是 this 的指向问题,核心就是 this 永远指向最终调用它的那个对象,除非改变 this 指向或者箭头函数那种特殊情况
function test() {
console.log(this);
}
test() // window
var obj = {
foo: function () { console.log(this.bar) },
bar: 1
};
var foo = obj.foo;
var bar = 2;
obj.foo() // 1
foo() // 2
// 函数调用的环境不同,所得到的结果也是不一样的
关于this指向问题
apply()、call()和 bind() 是做什么的,它们有什么区别
相同点:三者都可以改变 this 的指向
不同点:
- apply 方法传入两个参数:一个是作为上下文的对象,另一个是作为函数所组成的数组
var obj = {
name : 'sss'
}
function func(firstName, lastName){
console.log(firstName + ' ' + this.name + ' ' + lastName);
}
func.apply(obj, ['A', 'B']); // A sss B
- call 方法第一个参数也是作为作为函数上下文的对象,但是后面传入的是一个参数列表,而不是单个数组
var obj = {
name: 'sss'
}
function func(firstName, lastName) {
console.log(firstName + ' ' + this.name + ' ' + lastName);
}
func.call(obj, 'C', 'D'); // C sss D
- bing接受的参数有两个部分,第一个参数是作为函数上下文的对象,第二部分参数是一个列表,可以接受多个参数
var obj = {
name: 'sss'
}
function func() {
console.log(this.name);
}
var func1 = func.bind(null, 'xixi');
func1();
apply、call 方法都会使函数立即执行,因此它们也可以用来调用函数
bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数。而原函数 func 中的 this 并没有被改变,依旧指向全局对象 window
bind 在传递参数的时候会将自己带过去的参数排在原函数参数之前
function func(a, b, c) {
console.log(a, b, c);
}
var func1 = func.bind(this, 'xixi');
func1(1,2) // xixi 1 2
什么是内存泄漏,哪些操作会造成内存泄漏
内存泄漏:是指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束
可能造成内存泄漏的操作:
- 意外的全局变量
- 闭包
- 循环引用
- 被遗忘的定时器或者回调函数
你可能还需要知道 垃圾回收机制
什么是事件代理,它的原理是什么
事件代理:通俗来说就是将元素的事件委托给它的父级或者更外级元素处理
原理:利用事件冒泡机制实现的
优点:只需要将同类元素的事件委托给父级或者更外级的元素,不需要给所有元素都绑定事件,减少内存空间占用,提升性能; 动态新增的元素无需重新绑定事件
对AMD和CMD的理解,它们有什么区别
AMD和CMD都是为了解决浏览器端模块化问题而产生的,AMD规范对应的库函数有 Require.js,CMD规范是在国内发展起来的,对应的库函数有Sea.js
AMD和CMD最大的区别是对依赖模块的执行时机处理不同
1、AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块
2、CMD推崇就近依赖,只有在用到某个模块的时候再去require
对ES6的了解
ECMAScript 6.0 是 JavaScript 语言的下一代标准
新增的特性:
- 声明变量的方式 let const
- 变量解构赋值
- 字符串新增方法 includes() startsWith() endsWith() 等
- 数组新增方法 Array.from() Array.of() entries() keys() values() 等
- 对象简洁写法以及新增方法 Object.is() Object.assign() entries() keys() values()等
- 箭头函数、rest 参数、函数参数默认值等
- 新的数据结构: Set 和 Map
- Proxy
- Promise对象
- async函数 await命令
- Class类
- Module 体系 模块的加载和输出方式
箭头函数有什么特点
ES6 允许使用箭头=> 定义函数
var f = v => v;
// 等同于
var f = function (v) {
return v;
}
注意点:
- 函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象
- 不可以当作构造函数,也就是说,不可以使用 new 命令,否则会抛出一个错误
- 不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替
Promise 对象的了解
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大.所谓 Promise ,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果 —— ES6 入门-阮一峰
Promise 对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
特点:
- 对象的状态不受外界影响
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果
- Promise 新建后就会立即执行
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
})
Promise 实例生成以后,可以用 then 方法分别指定 resolved 状态和 rejected 状态的回调函数
promise.then(function(value) {
// success
}, function(error) {
// failure
})
then 方法返回的是一个新的Promise实例
Promise.prototype.catch 用于指定发生错误时的回调函数,具有冒泡性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获
getJSON('/post/1.json').then(function(post) {
return getJSON(post.commentURL);
}).then(function(comments) {
// some code
}).catch(function(error) {
// 处理前面三个Promise产生的错误
});
catch 方法返回的还是一个 Promise 对象,因此后面还可以接着调用 then 方法
出去上述方法,Promise 还有其他用法,小伙伴们可以在这里查看大佬写的文章 ES6入门-阮一峰
async 函数以及 await 命令
async 函数是什么?一句话,它就是 Generator 函数的语法糖
语法糖是指在不影响功能的情况下,添加某种方法实现同样的效果,从而方便程序开发.Vue.js的v-bind和v-on指令都提供了语法糖,也可以说是缩写。
async 特点:
-
async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。当函数执行的时候,一旦遇到 await 就会先返回,等到异步操作完成,再接着执行函数体内后面的语句
-
async 函数内部 return 语句返回的值,会成为 then 方法回调函数的参数
-
async 函数返回的 Promise 对象,必须等到内部所有 await 命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到 return 语句或者抛出错误
-
async 函数内部抛出错误,会导致返回的 Promise 对象变为 reject 状态。抛出的错误对象会被 catch 方法回调函数接收到
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function asyncPrint(value, ms) {
await timeout(ms);
console.log(value);
}
asyncPrint('hello world', 50);
await 命令: await 命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值
async function f() {
// 等同于
// return 123;
return await 123;
}
f().then(v => console.log(v))
// 123
await 命令后面是一个thenable对象(即定义then方法的对象),那么await会将其等同于 Promise 对象.也就是说就算一个对象不是Promise对象,但是只要它有then这个方法, await 也会将它等同于Promise对象
使用注意点:
- await 命令后面的 Promise 对象,运行结果可能是 rejected,所以最好把 await 命令放在 try…catch 代码块中
- 多个 await 命令后面的异步操作,如果不存在继发关系,最好让它们同时触发
- await 命令只能用在 async 函数之中,如果用在普通函数,就会报错
export 与 export default有什么区别
export 与 export default 均可用于导出常量、函数、文件、模块等
在一个文件或模块中,export、import 可以有多个,export default 仅有一个
通过 export 方式导出,在导出时要加 { },export default 则不需要
使用 export default命令,为模块指定默认输出,这样就不需要知道所要加载模块的变量名; export 加载的时候需要知道加载模块的变量名
export default 命令的本质是将后面的值,赋给 default 变量,所以可以直接将一个值写在 export default 之后
前端性能优化
对JS引擎执行机制的理解
首选明确两点:
JavaScript 是单线程语言
JavaScript 的 Event Loop 是 JS 的执行机制, 也就是事件循环
console.log(1)
setTimeout(function(){
console.log(2)
},0)
console.log(3)
// 1 3 2
JavaScript 将任务分为同步任务和异步任务,执行机制就是先执行同步任务,将同步任务加入到主线程,遇到异步任务就先加入到 event table ,当所有的同步任务执行完毕,如果有可执行的异步任务,再将其加入到主线程中执行
视频详解, 传送门
setTimeout(function(){console.log(1);},0);
new Promise(function(resolve){
console.log(2);
for(var i = 0; i < 10000; i++){
i == 99 && resolve();
}
}).then(function(){
console.log(3)
});
console.log(4);
// 2 4 3 1
在异步任务中,定时器也属于特殊的存在。有人将其称之为 宏任务、微任务,定时器就属于宏任务的范畴。
CSS相关
CSS 选择符有哪些
1.id选择器( # myid)
2.类选择器(.myclassname)
3.标签选择器(div, h1, p)
4.相邻选择器(h1 + p)
5.子选择器(ul > li)
6.后代选择器(li a)
7.通配符选择器( * )
8.属性选择器(a[rel = “external”])
9.伪类选择器(a: hover, li:nth-child)
不可继承的样式
border padding margin width height
优先级算法如何计算
优先级:
!important > id > class > tag
important 比 内联优先级高,但内联比 id 要高
盒模型概念
个人理解是整个html页面就是无数个通过特定的布局结合在一起的,每个盒子包括内容(content)、内边距(padding)、边框(border)、外边距(margin)。
高度塌陷问题
父元素的高度,默认被子元素撑开。例如子元素设置浮动,则会导致其完全脱离文档流,子元素脱离文档流将无法撑开父元素,导致父元素的高度丢失,就是我们所说的高度塌陷问题。
例如,我们想要的界面是如下:
然而,可能会出现如下情况:
解决办法:
参考:前端基础问题 – 高度塌陷问题详解(面试重点问题)
position的几个属性
- static 默认,指示元素出现在正常的文档流中
- relative(相对定位) 相对于该元素在文档流中的正常位置进行偏移定位,
占用文档流
。常用作绝对定位元素的容器块。 - absolute(绝对定位)较少直接单独使用在正常的文档流中,而是配合relative来进行一些更灵活更精确的定位。换言之,就是绝对定位
主要运行于进行了相对定位的元素框架层里面
,然后依据该层的最左上点作为基点进行便宜。常用作动画结构。 - fixed(固定定位)相对于浏览器窗口的最左上点作为基点进行偏移定位,应用比较少,主要是运用与浏览器贴边定位。和绝对定位一样可以用在固定定位的框架层里面。常用作漂浮广告,返回顶部。
- z-index属性,使用以上三种定位后,都会使正常的文档流在一定程度上发生变化,造成元素显示重叠问题,也就是上文所提及到的塌陷问题。使用该属性能够设置优先级,数值越大,优先级越高,该属性只对使用了定位的元素有效。
新增的属性:
- sticky(粘性布局) 结合了相对和固定定位两种,常见使用场景是实现头部导航栏固定。
CSS 中 display 的 block,inline,inline-block 这三个属性有什么区别
-
display: block
1.block元素会独占一行,多个bolck元素会各自新起一行。默认情况下,block元素宽度会自动填满其父元素宽度。
2.可以设置width、height、padding、margin属性 -
display: inline
1.inline元素不会独占一行,多个相邻的元素会排在同一行内,直到排不下才会换新一行。宽度会随元素内容变化而变化
2.无法设置width、height,padding和水平方向外边距margin会产生边距效果,其它的不会。 -
display: inline-block
1.简单说是将对象呈现为inline对象,但对象的内容作为block对象呈现。比如我们可以给一个link(a元素)inline-block属性值,使其既具有block的宽度高度特性又具有inline的同行特性。
参考:CSS 中 display 的 block,inline,inline-block
另附display其它值:
none:设置元素不可见;
flex:开启弹性布局;
table:作为块级表格显示;
list-item:像块级元素一样显示,并添加样式列表标记;
inherit:继承父元素的display属性;
常见的块级元素和内联元素有哪些
- 块级元素:div、 form 、 table 、p 、pre、 h1 ~ h6 、dl 、ol 、ul等
- 内联元素:span、 a 、strong、 em 、label 、input 、select 、textarea 、 img 、br等
解释盒模型宽高值得计算方式,边界塌陷,负值作用,box-sizing概念
- 盒模型:IE 678 下(不添加doctype) 使用ie盒模型,宽度 = 边框 + padding + 内容宽度; chrom、IE9+、(添加doctype) 使用标准盒模型, 宽度 = 内容宽度。
- box-sizing : 为了解决标准黑子和IE盒子的不同,CSS3增添了盒模型属性box-sizing,content-box(默认),border-box 让元素维持IE传统盒子模型, inherit 继承 父盒子模型;
- 边界塌陷:块元素的 top 与 bottom 外边距有时会合并(塌陷)为单个外边距(合并后最大的外边距),这样的现象称之为 外边距塌陷。
- 负值作用:负margin会改变浮动元素的显示位置,即使我的元素写在DOM的后面,我也能让它显示在最前面。
BFC(Block Formatting Context) 是什么?应用?
BFC 就是 ‘块级格式上下文’ 的格式,创建了BFC的元素就是一个独立的盒子,不过只有BLock-level box可以参与创建BFC,它规定了内部的Bloc-level Box 如何布局,并且与这个独立盒子里的布局不受外部影响,当然它也不会影响到外面的元素。
应用场景:
- 解决margin叠加的问题
- 用于布局(overflow: hidden),BFC不会与浮动盒子叠加。
- 用于清除浮动,计算BFC高度。
如何实现浏览器内多个标签页之间的通信
调用localstorge、cookies等本地存储方式
为什么要清除浮动?清除浮动的方式?
- 清除浮动主是要为了解决父级元素因为子级浮动引起内部高度为0的问题(父级没有高度的情况);很多情况下不方便给父亲高度,比如新闻,不知道新闻里面多少字,不方面给高度,一般是让里面的内容自动撑开高度。这个时候就需要清除浮动,用clear 属性:清除浮动
- 清除方式:
1、父级盒子定义一个height
2、父级盒子定义overflow:hidden/auto;
3、额外标签法:在浮动盒子的后面加一个空标签,例如
.clear{
clear:both;
}
4、使用after伪元素清除浮动
.clearfix:after{
display:block; /* 转换为块级元素*/
content:"."; /* 内容为小点,尽量加不要空,防止旧版本有空隙*/
height:0; /* 高度为0*/
visibility:hidden;/* 隐藏小点*/
clear:both;
}
.clearfix{
*zoom:1; /* *代表IE6和IE7能识别的特殊符号,带有这个*的属性,只有IE6和IE7才执行,zoom就是IE6和IE7清除浮动的方法,IE6和IE7浏览器的处理方式,所以必须加上*/
}
5、使用before和after双伪元素清除法
.clearfix:before,.clearfix:after{
display:table; /* 转换为块级元素*/
content:""; /* 为空*/
}
.clearfix:after{
clear:both;
}
.clearfix{
*zoom:1;
}
CSS3有哪些新特性
- 实现圆角border-radius,阴影box-shadow,边框图片border-image
- 对文字加特效text-shadow,强制文本换行word-wrap,线性渐变linear-gradient
- 实现旋转transform:rotate(90deg),缩放scale(0.85,0.90),translate(0px,-30px)定位,倾斜- skew(-9deg,0deg);
- 增加了更多的CSS选择器、多背景、rgba()
- 唯一引入的伪元素是::selection;
- 实现媒体查询@media,多栏布局flex
- 过渡transition,动画animation
盒子水平居中方式
- 将margin-left和margin-right设置为auto,或者margin:0,auto;(父盒子必须有高度)
- 先让盒子向左移动父盒子宽度的一半,再往回移动自身宽度的一半
- 先把盒子转换成inline-block +,然后text-align:center,使盒子水平居中
- 使用绝对定位
div{
position:absolute;
width:100px;
height:100px;
left:50%;
margin-left:-50px;
}
盒子垂直居中方式
- 使用margin计算盒子的上下边距,使其垂直居中
- 将盒子转换成display:table-cell,再vertical-align:middle;使盒子垂直居中
- 先让盒子向下移动父盒子高度的一半,再往回移动自身高度的一半
盒子垂直水平居中方式
- 使用绝对定位 + left:50%,top: 50% + margin-left:(自身宽度的一半),margin-top:(自身高度的一半)
- 使用绝对定位 + left:50% ,top: 50%+ translate(-50%,-50%)
- 使用绝对定位 + left: 0,right: 0, top: 0, bottom: 0 + margin:auto
- 使用弹性盒子布局,给父标签设置属性,display: flex; justify-content: center; (水平居中)align-items: center;(垂直居中)
opacity和rgba的区别
- opacity
opacity是一个属性,有opacity属性的所有后代元素都会继承 opacity 属性
.box{
opacity:0.4; //取值从 0.0 (完全透明)到 1.0(完全不透明)
}
- rgba
rgba是一个属性值,语法为rgba(r,g,b,a);rgba只会作用于它本身,不会作用于子元素上
.box{
background: rgba(0,0,255,0.4); // 不限于背景颜色,可以是文字颜色,阴影等
}
CSS隐藏元素的几种方法(至少说出三种)
- Opacity:元素本身依然占据它自己的位置并对网页的布局起作用。它也将响应用户交互;
- Visibility:与 opacity 唯一不同的是它不会响应任何用户交互。此外,元素在读屏软件中也会被隐藏;
- Display:display 设为 none 任何对该元素直接打用户交互操作都不可能生效。此外,读屏软件也不会读到元素的内容。这种方式产生的效果就像元素完全不存在;
- Position:不会影响布局,能让元素保持可以操作;
- Clip-path:clip-path 属性还没有在 IE 或者 Edge 下被完全支持。如果要在你的 clip-path 中使用外部的 SVG 文件,浏览器支持度还要低;
请描述一下cookies,sessionStorage和localStorage的区别?
相同点:都会在浏览器端保存,有大小和同源限制。
不同点:
1、cookie会随请求发送到服务器,作为会话表示,服务器可修改cookie。web storage不会随请求发送到服务器。
2、cookie有path的概念,子路径可以访问父路径的cookie,父路径不可以访问子路径的cookie。
3、有效期: cookie在设置的有效期内有效,默认为浏览器关闭消失。sessionStorage在会话窗口关闭后失效,localStorage长期有效,需主动删除。
4、sessionStorage不能共享,localStorage在同源文档之间可以共享,cookie在同源且符合path规则的文档之间可以共享。
5、localStorage的修改会触发其他文档的update事件。
6、cooie有secure属性要求HTTPS传输。
7、浏览器不能保存超过300个cookie,单个服务器不能超过20个,每个cookie不能超过4k。webStorage可以支持5M的存储。
css文件引入的方式有哪些?
引入方式3种:行内添加定义style属性值,页面头部内内嵌在style标签中调用和外链调用css文件
link和@import有什么区别?
link属于XHTML标签,除了加载CSS外,还能用于定义RSS, 定义rel连接属性等作用;而
@import是CSS提供的,只能用于加载CSS;
页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;
import是CSS2.1 提出的,只在IE5以上才能被识别,而link是XHTML标签,无兼容问题;
常见的浏览器内核有哪些?
Trident内核:IE,MaxThon,TT,The World,360,搜狗浏览器等。[又称MSHTML]Gecko内核:Netscape6及以上版本,FF,MozillaSuite/SeaMonkey等
Presto内核:Opera7及以上。 [Opera内核原为:Presto,现为:Blink;]
Webkit内核:Safari,Chrome等。 [ Chrome的:Blink(WebKit的分支)]
简述前端性能优化的方式
1、减少DOM操作
2、部署前,图片压缩,代码压缩
3、优化js代码结构,减少冗余代码
4、减少http请求,合理设置HTTP缓存
5、使用内容分发cdn加速
6、静态资源缓存
7、图片延迟加载
对前端工程化的理解
开发规范
模块化开发
组件化开发
开发仓库
性能优化
项目部署
开发流程
开发工具
Vue
Vue生命周期
前端框架(framework ) 与 库(library) 怎么区别
库,更多是一个封装好的特定集合,提供给开发者使用,而且是特定与某一方面的集合(方法和函数),库没有控制权,控制权在使用者手中
前端框架,顾名思义就是一套架构,控制权在框架本身,使用者需按照框架的某种规范进行开发
mvvm mvc是什么区别 原理
MVC(Model-View-Controller)
MVC是比较直观的架构模式,用户操作->View(负责接收用户的输入操作)->Controller(业务逻辑处理)->Model(数据持久化)->View(将结果反馈给View)。
MVC使用非常广泛,比如JavaEE中的SSH框架
MVVM(Model-View-ViewModel)
如果说MVP是对MVC的进一步改进,那么MVVM则是思想的完全变革。它是将“数据模型数据双向绑定”的思想作为核心,因此在View和Model之间没有联系,通过ViewModel进行交互,而且Model和ViewModel之间的交互是双向的,因此视图的数据的变化会同时修改数据源,而数据源数据的变化也会立即反应view。
从输入URL到页面加载发生了什么?【经典】
html是怎么渲染的
计算机网络
tcp和udp协议
tcp属于传输层,ip属于网络层,http是应用层
tcp提供面向连接的传输,通信前要先建立连接(三次握手机制),udp提供无连接的传输,通信前不需要建立连接
tcp提供可靠(有序,无差错,不丢失,不重复)的传输,udp提供不可靠的传输。
tcp面向字节流的传输,因此它可将信息分割成组,并在接收端将其重组,udp面向数据报的传输,没有分组开销
tcp提供拥塞控制和流量控制机制,udp不提供
http和https的区别
首先,我们的网站的URL分为两个部分:通信协议和域名地址。
简单来说,域名地址表示不同的页面
网站中的通信协议一般就是http和https协议
http协议是一种明文数据传输的协议,存在安全隐患。
而https协议是在http基础上增加了数据加密,在数据传输之前,对数据进行加密,然后再发送服务器。这样,就算传输过程中被截获,但数据时加密了的,所以个人信息时安全的。
另外,还有的区别就是当访问https的网站时,地址栏会显示“安全锁”,其次,对于百度和谷歌搜索引擎的话,https更加占有优势。
tcp三次握手与四次挥手
tcp三次握手:
起初A和B都处于close关闭状态
B创建tcb,初遇listen收听状态,等待A请求
第一次握手:A创建tcb,发送连接请求,进入syn-sent同步已发送状态。
第二次握手:B收到连接请求,向A发送确认和连接请求,进入syn-rcvd同步收到状态。
第三次握手:A收到B的确认和连接请求后,向B发出确认,A进入established已连接状态。
B收到A的确认收到进入established已连接状态
http协议的请求方法
http请求方法一般有8种:GET、HEAD、PUT、DELETE、POST、OPTIONS、TRACE、CONNECT
- get 最常见,发送一个请求来获取服务器上的某一资源。资源通过一组http头和呈现数据(如html文本,或者图片视频等)返回给客户端。
- head 和get本质一样,不过返回的仅仅是http头,区别是如果是判断某个资源是否存在,通常使用head进行判断更加明确。
- put 和post相似,都是向服务器发送数据,但put通常指定了资源的存放位置,然而post位置是由服务器来决定的。
- delete 删除某一个资源,请求服务器删除request-url所标识的资源。
- post 向服务器提交数据。用途广泛,几乎所有提交操作都可以完成。post向指定资源提交数据进行请求处理(提交表单、上传文件),有可能导致新资源的建立或原资源的修改
- options 很少使用,获取当前url所支持的方法,若请求成功,会在http头包含一个名为“allow”的头,值是所支持的方法,如“get、post”等
- trace 回显服务器收到的请求,用于测试和诊断。
- connect http/1.1协议中将连接改为管道方式的代理服务器。
get和post有什么区别
- get是客户端向服务器发送请求网页页面的请求,请求获取服务器上的某一资源。post是客户端向服务器上传一些文件的请求,向服务器提交数据。
- get请求参数会在url后进行传递,请求数据会附在url之后,以?分割url和传输数据,参数一件以&相连等等。
get请求提交数据不安全,数据置于请求行,客户端地址栏可见
。而post方法提交数据安全,数据置于消息主体内,客户端不可见。
- get传输的数据有大小限制,因为是通过url来提交数据的。而post提交的数据大小没有限制。
- get请求的数据会被浏览器缓存起来,用户名和密码将明文出现在url中,其他人可以查阅浏览历史记录,不安全。在服务器端,用Request.QueryString来获取get方式提交来的数据。post表示可能修改服务器上的资源请求,在服务器端,用post方法提交的数据,只能用Request.Form来获取。
操作系统
进程和线程的区别
进程:在操作系统中,能够独立运行,并且作为资源分配的基本单位。它表示运行中的程序。
线程:是进程中的一个实例,作为系统调度和分派的基本单位。是进程中的一段序列,能够完成进程中的一个功能。
两者的区别和联系:
- 同一个进程可以包含多个线程,一个进程至少包含一个线程,一个线程只能存在于一个进程中。
- 同一个进程下的所有线程能共享该进程下的资源
- 进程结束后,该进程下的所有线程都会销毁,而一个线程的结束不会影响同一进程下的其它线程
- 线程是轻量级的进程,它的创建及销毁所需的时间比进程小得多,所有操作系统的执行功能都是通过创建线程来完成的。
- 线程在执行时是同步和互斥的,因为他们共享同一个进程下的资源
- 在操作系统中,进程是拥有系统资源的独立单元,它可以拥有自己的资源。一般而言,线程不具有自己的资源,但能够访问隶属进程的资源。
同步和异步的区别
同步就是发送请求后,等待服务器返回结果,才会执行下一步。异步则是不等服务器返回,直接并行执行下一步,服务器返回结果会通过处理回调函数执行。
同步是阻塞模式,异步是非阻塞模式
阻塞和非阻塞的区别
应用进程请求I/O操作时,如果数据未准备好,请求立即返回就是非阻塞,不立即返回就是阻塞。
简单来说,就是做一件事如果不能立即获得返回,需要等待,就是阻塞。否则就是非阻塞
数据库
Mysql中主键与外键的区别
主键:唯一标识一条记录,保证不重复不为空,保证数据完整性
外键:某表的外键是另一张表的主键,可以重复,可以为空,用来和其他表建立联系。
问题:为什么要设置外键,可以通过where语句查询也是一样?
当删除了设置外键的主键后,所有的外键都会被自动删除,例如: