目录
6.position 有几个值,absolute 是相对于谁的定位。
2.JavaScript 数据类型以及 typeof 返回值
17.总结JS中string、math、array的常用的方法
19.JS事件绑定(addEventListener)和普通事件(onclick)有什么区别
28.前端进阶之setTimeout 倒计时为什么会出现误差?
19、能说下 vue-router 中常用的 hash 和 history 路由模式实现原理吗?
23、Proxy 与 Object.defineProperty 优劣对比
24、Vue 怎么用 vm.$set() 解决对象新增属性不能响应的问题 ?
一、HTML
1.对 HTML 语义化的理解
见标签知其意思 header main nav aside footer h1-h6 ul li
优点:结构清晰、方便搜索引擎搜素(seo)、方便理解维护
2.区别:src 和 href
- src
比如常见的 <img src=""> 这里的 src 所指的是这个图片的所在的位置路径,script 和 iframe 也是,src 被解析的时候,会进行下载并编译,同时会暂停该文档其他资源的下载和处理,所以 js 文件的载入最好在 body 中,而不是在 head 中。
- href
href被添加,元素会被识别为 css 文件进行处理,且不会停止其它资源的运行。所以建议用 link 加载 css 文件,而不是 @import。
常用的有:
<a href=""></a> 超链接
<link rel="stylesheet" href=""> 引用css样式
3.DOCTYPE 的作用
作用: DOCTYPE 是文档类型 document type 的缩写。 主要作用是告诉浏览器的解析器使用哪种 HTML 规范来解析页面。而如果 DOCTYPE 缺失,或形式不正确,会导致 html 文档或 HTML 文档不是以标准模式(浏览器对页面的渲染具有统一的规范)而是以混杂模式(不同浏览器有不同的的页面渲染)运行。
4.HTML5 的新特性
- 简化了文档声明,HTML5 的文档声明只需要 <!DOCTYPE HTML>
- 简化了编码声明,只需要 <meta charset='utf-8'>
- 删除了一些能用 CSS 代替的就标签,比如 <i>
- 增加了一些新标签,改善文档结构的有:<header><footer>等。减少插件依赖的 <canvas><audio> 等
- 增加了一些新的 JavaScript 的 API ,比如地理定位、请求动画帧、离线存储等
- 配合一些框架,例如 cordova 和 react 等,可以开发基于 HTML5 的移动应用。
5.script 标签中的 defer 和 async
作用:平常的 script 标签如果直接使用, html 会按顺序下载和执行脚本,并阻碍后续 DOM 的渲染。 如果 script 发生延迟,就会阻碍后续的渲染,使得页面白屏。
- defer
- 异步下载文件
- 不阻碍 dom 的渲染
- 如果有多个 defer 会按顺序执行
- 执行顺序:在文档渲染后执行,在 DOMContentLoader 事件调用前执行。
2.async
- 异步下载文件
- 不影响 dom
- 如果有多个 defer 谁快先执行谁
推荐的应用场景:
defer:如果你的脚本代码依赖于页面中的 dom 元素(文档是否解析完毕),并且也不会产生其他脚本需要的数据。
async:如果你的脚本并不关心页面中的 dom 元素(文档是否解析完毕),并且也不会产生其他脚本需要的数据。
6. 行内元素 块级元素 空元素
- 行内元素: a \ b \ span \ input \ img \ strong \ br \ em \ big \ small
- 块元素: div \ ul \ ol \ li \ h1-h6 \ p \ dl \ dt \ address
- 空元素: img \ input \ link \ meta
7.meta 标签
meta 元素被用于规定页面的描述、关键词、文档的作者、最后的修改时间以及其他元数据。标签始终位于 head 元素中。
meta 属性:必选属性 content-进行描述说明的, 相当于键值; 可选属性 http-equiv、name 和 scheme, http-equiv-添加 http 头部内容,name-浏览器解析
包括:
①charset charset定义使用的字符编码
<meta charset="utf-8">
<meta http-euiqv="Content-Type" content="text/html;charset=utf-8">
②SEO
<meta name="keyword" content="csdn"> #网页关键词
<meta name="author" content="LiHua">
<meta name="description" content="we are world">#网页描述
③viewport
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0">
8.JPG和PNG的区别
1.JPG是有损压缩格式,PNG是无损压缩格式
2.JPG图片没有透明背景,PNG有透明背景
二、CSS
1.CSS 选择器,优先级
Import>内联1000>id100>class==伪类==属性选择器10>元素选择器 伪元素选择器
2.CSS 动画
- transition和animation的区别
大部分都是相同,都是随着时间改变元素的属性值,
他们的主要区别是transition需要触发一个事件才能改变属性,而animation不需要触发任何事件就可以实行。
transition为两帧,从from…to… 而animation可以一帧一帧的通过keyframes。
3.CSS选择器效率从高到低的排序如下:
Id>class>元素选择器>兄弟选择器>子代选择器>后代选择器>属性选择器>伪元素 伪类
ID选择器 比如#header
类选择器 比如.promo
元素选择器 比如 div
兄弟选择器 比如 h2 + p
子选择器 比如 li > ul
后代选择器 比如 ul a 7. 通用选择器 比如 *
属性选择器 比如 type = “text”
伪类/伪元素选择器 比如 a:hover
4.flex 布局
flex是css3新增的一种布局方式,我们可以同时设置一个元素的display属性值设置为flex,
从而使它成为一个flex容器,它的所有子元素都成为它的项目。
一个容器默认有两条轴,一个水平轴,一条是与主轴垂直的交叉轴
flex-direction来指定主轴的方向。
justify-content来指定标签在主轴的排列方式,
使用align-items来指定元素在交叉轴的排序方式。
还可以使用flex-wrap来规定当一行排列不下时的换行方式。
对于一个容器的项目,
使用order属性来指定项目的排列顺序,
flex-grow来指定当前排序空间有剩余的时候,项目放大比例。
flex-shrink来指定当前排序空间不足时, 项目缩小比例。
5.双飞翼布局
6.position 有几个值,absolute 是相对于谁的定位。
absolute :生成绝对定位的元素,相对于最近一级的父元素,且该父元素不能是static,来进行定位。
fixed:(老IE不支持)生成绝对定位的元素,通常相对于浏览器窗口或 frame 进行定位。
relative:生成相对定位的元素,相对于其在普通流中的位置进行定位。
static:默认值。没有定位,元素出现在正常的流中
三.Javascript
1.原始值和引用值类型及区别
原始值(简单数据类型):存储在栈中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。
包含五种简单数据类型:undefined、null、boolean、number 和 string ;可以通过typeof 运算符来判断一个值是否在某种类型的范围内,如果它是原始类型,还可以判断它表示哪种原始类型。
引用值(复杂数据类型):存储在堆中的对象,放在变量的栈空间中的值是该对象存储在堆中的地址,也就是说,存储在变量处的值是一个指针(内存地址),指向存储对象的堆内存中。
包含:Object、function、array等。
2.JavaScript 数据类型以及 typeof 返回值
数据类型:number、string、null、boolean、object、undefined、symbol
typeof x undefined
typeof undefined undefined
typeof true boolean
function A() {}
typeof A function
const arr = []
const obj = {}
typeof arr object
typeof obj object
3.如何判断一个对象是 Array 还是 Object?
在 typeof 判断 Array 或者 Object 的时候,其结果都是 object 那么我们怎么知道源对象是 Arrary 还是 Object 的呢?
4.类数组与数组的区别:
相同点:
- 都可用下标访问每个元素,都有length属性。
不同点:
- 数组对象的类型是Array,类数组对象的类型是object;
- 类数组不具有数组所具有的方法,
- 数组遍历可以用 for in 和 for 循环
- 类数组只能用 for 循环遍历。
常见的类数组有: 函数的参数 arguments,arguments是一个类数组对象,包含着传入函数中的所有实参集合
5.数组常用的api
- 字符转换 toString 方法将数组表示为字符串
- join()方法,将数组里 各元素组合成字符串,但连接符可自己指定
- unshift方法,是将元素插入数组的首部。
- shift方法移除数组的第一个元素并将其返回
- push方法一次可添加单个或多个元素到数组末端,也可以添加数组。
- pop方法的作用是移除数组末尾的一个元素
6.bind、call、apply的区别:
三者都是用于改变函数体内this的指向,但是bind与apply和call的最大的区别是:bind不会立即调用,而是返回一个新函数,称为绑定函数,其内的this指向为创建它时传入bind的第一个参数,而传入bind的第二个及以后的参数作为原函数的参数来调用原函数
apply和call都是为了改变某个函数运行时的上下文而存在的(就是为了改变函数内部this的指向);apply和call的调用返回函数执行结果;
如果使用apply或call方法,那么this指向他们的第一个参数,apply的第二个参数是一个参数数组,call的第二个及其以后的参数都是数组里面的元素,就是说要全部列举出来;
Bind:返回绑定函数,传入参数数列
Apply:传入参数数组
Call:传入参数数列
7.new原理
mdn上把内部操作大概分为4步:
- 创建一个空的简单JavaScript对象(即{ } );
- 链接该对象(即设置该对象的构造函数)到另一个对象 ;(因此this就指向了这个新对象)
- 执行构造函数中的代码(为这个新对象添加属性);
- 如果该函数没有返回对象,则返回this。
8.闭包
有权访问另一个函数作用域中的变量的函数;
- 第一,闭包是一个函数,而且存在于另一个函数当中
- 第二,闭包可以访问到父级函数的变量,且该变量不会销毁
- 作用1:隐藏变量,避免全局污染
- 作用2:可以读取函数内部的变量
9.原型和原型链
在JavaScript中,每当定义一个函数数据类型(普通函数、类)时候,都会天生自带一个prototype属性,这个属性指向函数的原型对象,并且这个属性是一个对象数据类型的值。
- 原型链 __proto__ 和 constructor
每一个对象数据类型(普通的对象、实例、prototype......)也天生自带一个属性__proto__,属性值是当前实例所属类的原型(prototype)。实例原型中有一个属性constructor, 它指向函数对象,即构造函数。
通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条,专业术语称之为原型链
当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果没有则会去原型对象中寻找,直到找到Object对象的原型,Object对象的原型,如果在Object原型中依然没有找到,则返回undefined。
原型链的终点:object.prototype=null
10.实现继承的几种方式以及他们的优缺点
其实js的继承本质上是通过原型链机制实现的扩展。不管是哪种继承方式,都是通过操作父类原型链和子类原型链形成关联关系实现的。只是不同实现中需要考虑不同的问题。在实际项目开发中,建议尽可能使用ES6的class extends实现。其他实现方式主要是理解背后的原理和思想。
- 原型链继承
通过修改子类的原型为父类的实例,从而实现子类可以访问到父类构造函数以及原型上的属性或者方法。属性没有私有化,原型上属性的改变会作用到所有的实例上。
实现逻辑简单,但是父类构造函数中的引用类型(比如对象/数组),会被所有子类实例共享。其中一个子类实例进行修改,会导致所有其他子类实例的这个值都会改变
function Parent() {
this.name = 'fedaily'
}
Parent.prototype.getName = function() {
return this.name;
}
function Child() {}
// 这里也可以直接写出Child.prototype = Parent.prototype
// 但是这样就不能访问到父类的构造函数的属性了,即this.name
Child.prototype = new Parent()
var child = new Child()
console.log(child.getName()) // fedaily
- 构造函数继承:
在构造子类构造函数时内部使用call或apply来调用父类的构造函数
实现了属性的私有化,但是子类无法访问父类原型上的属性。
可以实现多继承
- 组合继承
同时结合原型链继承、构造函数继承就是组合继承了。
同时解决了构造函数引用类型的问题,同时避免了方法会被创建多次的问题,但是父类构造函数被调用了两次。同时子类实例以及子类原型对象上都会存在name属性。虽然根据原型链机制,并不会访问到原型对象上的同名属性,但总归是不美。
- 寄生继承
核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点。
function Parent() {
this.name = 'fedaily'
}
Parent.prototype.getName = function() {
return this.name
}
function Child() {
Parent.call(this)
this.topic = 'fe'
}
// 仔细看这个函数的实现
inherit(Child, Parent)
function inherit(child, parent) {
var prototype = object(parent.prototype)
prototype.constructor = child
child.prototype = prototype
}
// 这个函数的作用可以理解为复制了一份父类的原型对象
// 如果直接将子类的原型对象赋值为父类原型对象
// 那么修改子类原型对象其实就相当于修改了父类的原型对象
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
这种方式就解决了组合继承中的构造函数调用两次,构造函数引用类型共享,以及原型对象上存在多余属性的问题。是推荐的最合理实现方式(排除ES6的class extends继承哈哈哈)。
-
ES6继承
ES6提供了class语法糖,同时提供了extends用于实现类的继承。这也是项目开发中推荐使用的方式。
使用class继承很简单,也很直观:
11.浅拷贝与深拷贝
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
赋值和浅拷贝的区别
当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址
浅拷贝的实现方式
- Object.assign()
Object.assign() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。当object只有一层的时候,是深拷贝
- Array.prototype.concat()
修改新对象会改到源对象
12.作用域
为可访问变量,对象,函数的集合
作用域链是[[Scope]]中所存储的执行期上下文的集合
一个执行期上下文定义了一个函数执行的环境
13.防抖与节流
防抖就类似回城,打断就得重新回。
触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。在限定时间内,总是执行最后一次。
假设设置了五秒, 最后一秒生效(也就是说, 第一次点击和第二次点击之间间隔不到5秒, 则第一次的点击会被作废)
节流就类似技能需要冷却时间到了才能用。
指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
假设设置了五秒, 第一秒生效, 后面的四秒作废.。
由于节流是第一次生效, 而防抖是最后一次生效, 所以防抖获取到最新数据。
14.Dom节点操作常用方法
- 访问/获取节点
document.getElementById(id); //返回对拥有指定id的第一个对象进行访问
document.getElementsByName(name); //返回带有指定名称的节点集合 注意拼写:Elements
document.getElementsByTagName(tagname); //返回带有指定标签名的对象集合 注意拼写:Elements
document.getElementsByClassName(classname); //返回带有指定class名称的对象集合 注意拼写:Elements
- 创建节点/属性
document.createElement(eName); //创建一个节点
document.createAttribute(attrName); //对某个节点创建属性
document.createTextNode(text); //创建文本节点
- 添加节点
document.insertBefore(newNode,referenceNode); //在某个节点前插入节点
parentNode.appendChild(newNode); //给某个节点添加子节点
- 复制节点
cloneNode(true | false); //复制某个节点 参数:是否复制原节点的所有属性
- 删除节点
parentNode.removeChild(node);
15.BOM属性对象方法
- window对象
- location对象
它提供了与当前窗口中加载的文档有关的信息,还提供了一些导航功能
- history对象
history对象是window对象的属性,它保存着用户上网的记录,从窗口被打开的那一刻算起
16.ajax的请求过程
一、原生JS中的Ajax
1、使用ajax发送数据的步骤
第一步:创建异步对象
var xhr = new XMLHttpRequest();
第二步:设置 请求行 open(请求方式,请求url):
// get请求如果有参数就需要在url后面拼接参数,
// post如果有参数,就在请求体中传递 xhr.open("get","validate.php?username="+name)
xhr.open("post","validate.php");
第三步:设置请求(GET方式忽略此步骤)头:setRequestHeader()
// 1.get不需要设置
// 2.post需要设置请求头:Content-Type:application/x-www-form-urlencoded
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
第四步:设置请求体 send()
// 1.get的参数在url拼接了,所以不需要在这个函数中设置
// 2.post的参数在这个函数中设置(如果有参数)
xhr.send(null) xhr.send("username="+name);
第五步:让异步对象接收服务器的响应数据
17.总结JS中string、math、array的常用的方法
一、String
①charAt()方法用于返回指定索引处的字符。返回的字符是长度为 1 的字符串
②indexOf()方法可返回某个指定的字符串值在字符串中首次出现的位置
③split()方法将字符串分割成字符串数组,并返回此数组
④substring()方法用于提取字符串中介于两个指定下标之间的字符,其内容是从 start 处到 stop-1 处的所有字符,其长度为 stop 减 start。
二、Math
①ceil()方法 对一个数进行向上取整
语法