文章目录
-
- 一 、第一回合
-
-
- 1.开发中遇到的困难?
- 2. Css的盒子模型
- 3. Pull和fetch的区别
- 4. SPA单页面项目
- 5.SEO优化
- 6.BOM浏览器对象模型
- 7.数组、对象、字符串中的一些方法
- 8.解构赋值
- 9...args剩余参数(扩展运算符)
- 10.arguments 对象
- 11. Promise以及底层封装
- 12.浅拷贝深拷贝
- 13.组件之间的通信
- 14.JS数据类型/数据结构
- 15.对象和数组
- 16.数据类型的检测方式(包括区分对象和数组)
- 17.instanceof手写实现
- 18将一个数组转换为二进制
- 19.HTTP状态码
- 20.项目部署
-
- 二、第二回合
-
-
- 1.VUE vuex的五大属性和工作原理
- 2.vue生命周期之间的差别
- 3.HTMLmeta标签的作用
- 4.Doctype有什么作用
- 5.本地存储
- 6.用户注册登录实现大概步骤
- 7.CSS盒子居中显示
- 8.Flex布局
- 9.MVVM模式
- 10.节流和防抖
- 11.懒加载
- 12.预编译、作用域、变量提升、事件委派
- 13.JS执行机制
- 14.异步任务(宏任务和微任务)
- 15.定时器的秒数为0是不是立即执行函数
- 16.Es6的常用的新特性
- 18.跨域的方法
- 19.v-if v-show
- 20.nodejs的express
-
- 三、第三回合
-
-
- 1.JS垃圾回收机制
- 2.form表单的使用以及相应的属性值
- 3.vue中的双向数据绑定原理(重点深入学习)
- 4.vue单向数据流
- 5.undefined、null、NaN有什么区别?
- 7.如何获取安全的undefined 值?
- 8.Object.is() 与比较操作符 “=== ” 、 “==” 的区别?
- 9. 什么是 JavaScript 中的包装类型?
- 10.const 对象的属性可以修改吗
- 11.new 操作符的实现步骤
- 12.this指向问题(JS高级)
- 13.JavaScript 脚本延迟加载的方式有哪些?
- 14.对 JSON 的理解
- 15.什么是 DOM 和 BOM?
- 16.原型和原型链的理解
- 17.作用域、作用域链的理解
- 18.Proxy 可以实现什么功能?
- 19.常用的正则表达式有哪些?
- 20.escape、encodeURI、encodeURIComponent 的区别
-
- 四、第四回合
-
-
- 1.什么是尾调用,使用尾调用有什么好处?
- 2.ES6 模块与 CommonJS 模块有什么异同?
- 3.for...in 和 for...of 的区别
- 4.ajax、axios、fetch(前台请求后台数据的方式)
- 5. parseInt()的用法
- 6.浏览器运行机制
- 7.border-radius:50%和100%究竟有什么区别
- 8.alt和title
- 9. new Number(1)和1是否全等
- 10.a.length 重新赋值后会怎样
- 11.CSS属性继承
- 12.vue文件变成.html文件渲染
- 13.观察者模式+发布订阅模式
- 14.JS继承
- 15CDN
- 16.重排和重绘
- 17.template 标签
- 18.elementUI深度样式
- 19.浅谈Canvas和SVG的区别
- 20.v-for和v-if优先级?
-
- 五、第五回合
-
-
- 1.请求方式(get,post,其它)
- 2.CSS单位
- 3.判断一个字符串是否是回文(算法实现)
- 4.v-text和v-html
- 5.隐式转换、类型转换
- 6.迭代器
- 7.link和@import
- 8.CSS样式隐藏元素
- 9.CSS样式display
- 10.如何实现浏览器内多个标签页之间的通信?
- 11.cookie设置,获取,删除
- 12.声明式编程和命令式编程
- 14.高阶函数
- 15.闭包
- 16.Vue、Angular、React区别
- 17.CSS中的伪类
- 18.CSS动画
- 19.前端设计模式
- 20.XSS攻击
-
- 六、软技能问题
-
-
- 1.为什么学习前端
- 2.你觉得前端人员应该掌握哪些知识?
- 4.如何看待加班?
- 5.如何学习一门新技术(平时如何学习)
- 6.周围朋友同学如何评价你
- 7.你有什么想问我的?
- 8.你遇到的最大挑战?完成之后你的成就感?
- 9.前端与后端的区别?
-
前言:小伙伴们,本篇文章是博主自己在面试过程中的一些面试题的记录,自己在总结回顾记录的同时希望也能帮助到你们,可以结合对应的知识点去理解和查看!有什么不对的地方欢迎伙伴们指正!大家一起学习!一共有五大回合,如果在后续面试过程中还会持续更新!
小提示重要!:简历上的内容(项目+技能)自己一定要准备好,防止被问起。
开始学习!
一 、第一回合
1.开发中遇到的困难?
- 问题:才开始做项目的时候,以为插件使用简单,vue项目中轮播图的使用,swiper插件的使用,查看官方的文档是一定要有节点DOM(相应的结构)渲染出来才会有对应的动态效果。
vue中mounted生命周期函数–>组件挂载完毕就会调用,HTML已经被渲染到了页面上,这个阶段可以执行dom操作,可以进行数据请求,但是还是v-for在遍历来自于Vuex(数据:通过ajax向服务器发请求,存在异步)并且v-for的遍历也是需要时间的遍历数据渲染结构的(没法保证v-for的遍历完成), - 解决:思考了一下vue生命周期函数以及vue中的封装好的函数方法。nextTick函数:在下次DOM更新, 循环结束之后,执行延迟回调。在 修改数据之后 立即使用这个方法,获取更新后的DOM
- 收获:组件实例的$nextTick+watch方法,在今后经常使用,经常结合第三方插件使用,获取更新后的DOM节点
2. Css的盒子模型
- 标准盒模型(W3C):box-sizeing:content-box(默认值)
标准盒模型总宽度/高度:margin+border+padding+内容区宽度/高度( 即 width/height 不包含 padding 和 border 值 )) - 怪异盒模型(IE盒模型):box-sizing:border-box
标准盒模型总宽度/高度:margin+ (内容区宽度/高度 + padding + border) ( 即 width/height 包含 padding 和 border 值 ))
3. Pull和fetch的区别
- git pull将远程的仓库的变化下载下来,与和本地的分支做合并
- git fetch将远程的仓库的变化下载下来,并没有和本地的分支做合并
git在项目中常用命令流程
1.配置author信息
git config --global user.name “你的名字”
git config --global user.email “你的邮箱”
2.git clone 远程仓库链接
3.git stash “信息"本地保存自己的创建的代码
4.git pull 拉取远程的仓库的代码和本地分支做合并
5.解决冲突
6.git add 仓库(目录)中的所有文件添加进git管理
7.git commit 提交到本地仓库
8.git push 提交到远程仓库
4. SPA单页面项目
-
概念:SPA( single-page application )仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS实现页面的渲染加载。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互、避免页面的重新加载。
-
优点:
- 用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
- 基于上面一点,SPA 相对服务器压力小;
- 前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
-
缺点:
- 初次加载耗时多:为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统一加载,部分页面按需加载
- 前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理;
- SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。
-
劣势解决:
- SPA单页面应用实现前进与后退功能
前言:SPA单页面应用:在使用ajax与服务器数据交互过程中,实现局部数据的更新时,浏览器地址栏的url链接并没有发生改变,浏览器因为不会保存更新记录(浏览器会记录地址栏的url资源链接,如果url链接发生变化,浏览器会把该url链接保存到一个特殊的数据结构中,这样当用户点击返回与前进按钮时,会快速访问已经被记录的url链接资源。)。这时候再去返回就会出现非期待性的结果
- 解决方案:设置window.location.hash(location.hash)+ 监听window.onhashchange
//在ajax与服务器进行交互时,设置window.location.hash的值:
function updateView (attr){
$.ajax({
type:...,
url:...,
data:{attr : attr},
success:function(datas){
//设置hash值
window.location.hash = "#"+attr;
//do somthing
},
error:function(status){
//do somthing
}
});
}
//attr 这个值最好是该次请求所需的参数 设置onhashchange事件监听
window.onhashchange=function(){
var attr=window.location.hash.replace("#","");
updateView (attr);
}
//但是上述这样单纯的只要用户点击第一页的视图,ajax请求成功后,会主动改变hash值,这时候又触发onhashchange,又一次更新视图,两次访问服务器。
//解决办法
//设置一个全局变量,记录hash值的改变是怎样引起的:
var innerDocClick;
$('body').on('mouseleave',function(){
innerDocClick=false;//鼠标在页面外(点击了返回按钮)
});
$('body').on('mouseover',function(){
innerDocClick=true;//鼠标在页面内(没有点击返回按钮)
});
window.onhashchange=function(){
if(!innerDocClick)//若点击了返回按钮 加条件判断去更改hash值
{
var attr=window.location.hash.replace("#","");
updateView (attr);
}
}
第二种解决方法是在页面中嵌入一个隐藏 iframe,由于浏览器可以对 DOM 树中 iframe 节点的 src 属性进行历史记录跟踪,这样通过在逻辑上建立一条“页面 URL – 页面内 iframe URL – 页面状态”的对应链,同样可以在 IE 中建立片段标识符与页面状态的联系。
5.SEO优化
- 概念:seo是搜索引擎优化。是一种利用搜索引擎的规律提高网站在有关搜索引擎的排名,是一种网络营销方式。
搜索引擎的规律:是靠搜索关键字来让自己的网站在搜索栏的第一页内,展示在用户的最前面,能让用户第一时间看到自己的网站。
- 1.站内优化:
- META标签的优化:例如:title,keywords,description等的优化;(logo图片)
- 网站文章的更新:每天保持站内文章的更新;
- 2.站外优化:
- 友链互换:与一些和你网站相关性比较高,整体质量比较好的网站交换链接,巩固稳定关键词排名。
补充
高质量网站有哪些特点
1.内容受众
2.时效性强
3.设计与布局整洁干净
4.无虚假违法信息
6.BOM浏览器对象模型
-
1.window对象
- 概念:BOM的核心对象是window,它表示浏览器的一个实例,它也是ECMAScript规定的Globle对象,也就是说网页中任何一个对象都是在window这个对象里面的
常用的方法:
1.alert()
2.定时器
-
2.location对象
- 概念: location属性用于获得当前窗口中加载的文档有关的信息或者设置窗体的URL,并且可以解析URL,因为返回的是一个对象,因此可以叫做location对象,还有一些导航功能,值得注意的是location既是window对象的属性,又是document对象的属性,既window.location和document.location 引用的是同一个对象。
- URL: Uniform Resource Locator 统一资源定位符 :是互联网上标准的地址。互联网上的每个文件都有唯一的URL,包含 通过地址属性可以得到不同的url的信息图片location对象的属性
常用的方法:
location.href = “http://www.666.com”; //页面跳转到该网址
location.assign(“http://www.666.com”); //页面跳转到该网址
location.hash用于设置页面的标签值
- 3.navigator对象:
- 概念:该对象里面保存着浏览器的各种信息,判断浏览器的各种信息就是从该对象里的属性来读取,具体属性如下图:
常用的方法:
navigator.cookicEnablcd:判断是否启用cookic
navigator.userAgent:判断浏览器的名称和版本号
navigator.plugins:保存浏览器中所有插件信息的集合
<script>
function hasPlugin(name) {
name = name ? name.toLocaleLowerCase() : '';
console.log('name = ' + name);
var plugins = navigator.plugins;
for (var i = 0; i < plugins.length; i++) {
//console.log(typeof plugins[i]);
console.log(plugins[i].name);
return plugins[i].name.toLocaleLowerCase().indexOf(name) !== -1 ? true : false;
}
}
var r = hasPlugin('pdf');
console.log(r);
- 4.history对象:
- 概念:该对象保存着用户上网的历史记录,从窗口被打开的那一刻算起
常用方法:
1.前进:history.forward();history.go(1);
2.后退:history.back();history.go(-1);
3.获取记录个数:history.length:
7.数组、对象、字符串中的一些方法
8.解构赋值
- 概念:变量的解构赋值,ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。这种方式的出现大大提高了代码的扩展性
- 常见的使用场景
- 1.交换变量的值
let x = 1;
let y = 2;
[x, y] = [y, x];
- 2.从函数返回多个值
//返回一个数组,用结构赋值可以非常方便的取到对应值
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
//返回一个对象,获取对应的属性值
function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = example();
- 3.取 JSON 数据
解构赋值对提取 JSON 对象中的数据
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]
// 上面代码可以快速提取 JSON 数据的值。
- 对象的解构赋值
- 数组的解构赋值
- 1.同时赋值多个变量
let arr = [a,b,c,d] = [1,2,3,4]
- 2.解构嵌套数组
//解构嵌套数组,就是模式匹配,只要等号两边的层级结构相同,就可以拿到对应位置的值
const arr = [1, [2, 3, [4, 5, 6]]];
const [a, [b, c, [d, e, f]]] = arr;
- 3 相同“模式”的不完全解构
let [a, b, c] = [1, 2, 3, 4]; // 1 2 3
let [a, b, c, d] = [1, 2, 3]; // 1 2 3 undefined
let [a, [b, c, [d, e]]] = [1, [2, 3, [4, 5, 6]]]; // 1 2 3 4 5
- 4.解构的默认值
let [a = true] = [];
a // true
注意
数组的解构是根据它的位置(模式)对应的
解构操作允许有默认值,但一定是已经声明的。
如果等号的右边不是数组(或者严格地说,不是可遍历的结构)那么将会报错
9…args剩余参数(扩展运算符)
展开运算:允许一个表达式在某处展开。展开运算符在多个参数(用于函数调用)或多个元素(用于数组字面量)或者多个变量(用于解构赋值)的地方可以使用。
- 1.函数调用中使用展开运算符(传参)
在ES6之前将整个数组里面的元素依次作为实参传递给函数形参的时候使用Function.prototype.apply的特性
let arr = [1,2,3]
function test(a,b,c){}
test.apply(null,args) //通过apply特性将数值的形式转换为数组对应传递进去
ES6之后展开运算符
let arr = [1,2,3]
function test(a,b,c){}
test(..arr) //将数组展开进行传递参数
- 2.数组中使用展开运算符(合并数组,类数组对象变成数组)
a.合并数组
let arr = [1,2,3]
let arr1 = [...arr,4,5,6] //1,2,3,4,5,6
b.展开运算符可以用于数组的一些方法中(push函数)
let arr = [1,2,3]
let arr1 = [4,5,6]
arr1.push(...arr) //4,5,6,1,2,3
c.类数组对象变成数组
let a=new Set([1,2,3,4,5,2,1]) // a : Set(5) {1, 2, 3, 4, 5}
let b=[...a] // (5) [1, 2, 3, 4, 5]
- 3.解构赋值(解构赋值中展开运算符只能用在最后)
let [arg1,arg2,...arg3] = [1, 2, 3, 4]
arg1 //1
arg2 //2
arg3 //['3','4']
- 4.对象中的展开运算符(和数组类似)
let {x,y,...z}={x:1,y:2,a:3,b:4};
x; //1
y; //2
z; //{a:3,b:4}
let z={a:3,b:4};
let n={x:1,y:2,...z};
n; //{x:1,y:2,a:3,b:4}
let a={x:1,y:2};
let b={z:3};
let ab={...a,...b};
ab //{x:1,y:2,z:3}
剩余参数:剩余参数语法允许我们将一个不定数量的参数表示为一个数组。
- 1.函数调用
function test(a,b,...args){} //...args == [4,5,6]
test(1,2,3,4,5,6)
- 2.解构赋值(解构赋值中展开运算符只能用在最后)
let [arg1,arg2,...arg3] = [1, 2, 3, 4]
arg1 //1
arg2 //2
arg3 //['3','4']
扩展运算符的作用及使用场景
- 对象的扩展运算符
- (…)用于取出参数对象中的所有可遍历属性,拷 贝到当前对象之中。
- 等价于Object.assign 方法用于对象的合并,将源对象(source)的所有可 枚举属性,复制到目标对象(target)。Object.assign 方法的第一
个参数是目标对象,后面的参数都是源对象。(如果目标对象与源对 象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面 的属性)- 数组扩展运算符
- 可以将一个数组转为用逗号分隔的参数序列,且每 次只能展开一层数组
- 将数组转换为参数序列
- 复制数组,连接数组(contact)
- 将字符串转为真正的数组(任何 Iterator 接口的对象,都可以用扩展运算符转为真正的数组)
- 函数中使用扩展运算符,可以使用在形参上代替argument
10.arguments 对象
1.定义:arguments是一个对应传递给函数参数的类数组对象,arguments对象是所有非箭头函数都有的一个局部变量。你可以使用arguments对象在函数中引用函数的参数。此对象包含传递给函数的每个参数,第一个参数在索引0处。
2.特性:
- arguments对象并不是一个数组,除了length和索引元素之外,任何数组的属性都没有。当然它可以被转换为数组
const args = Array.from(arguments);
const args = [...arguments];
- arguments存在属性callee:
属性callee相当于调用自身函数,可以用作匿名函数的递归:
var sum = function (n) {
if (1 == n){
return 1;
} else {
return n + arguments.callee(n - 1); //6 5 4 3 2 1 } } alert(sum(6)); 输出结果:21
}
3.作用:
a.无需明确命名参数,就可以重写函数,在函数代码中,使用特殊对象 arguments,开发者无需明确指出参数名,就能访问它们
function sayHi(message) {
alert(arguments[0]); // 此处将打印message参数的值
}
b.检测参数个数( arguments.length )
function howManyArgs() {
alert(arguments.length);
}
howManyArgs("string", 45);
howManyArgs();
howManyArgs(12); // 上面这段代码将依次显示 "2"、"0" 和 "1"。
c.针对同一个方法被多处调用,但是参数数量不确定的情况下,可以更具arguments索引进行判断。
function func1() {
console.log(arguments[0]); // 1
console.log(arguments[1]); // 2
console.log(arguments[2]); // 3
}
func1(1, 2, 3)
d.模拟函数重载
用 arguments 对象判断传递给函数的参数个数,即可模拟函数重载
当只有一个参数时,doAdd() 函数给参数加 5。如果有两个参数,则会把两个参数相加,返回它们的和。所以,doAdd(10) 输出的是 “15”,而 doAdd(40, 20) 输出的是 “60”。
function doAdd() {
if(arguments.length == 1) {
alert(arguments[0] + 5);
} else if(arguments.length == 2) {
alert(arguments[0] + arguments[1]);
}
}
doAdd(10); //输出 "15"
doAdd(40, 20); //输出 "60"
11. Promise以及底层封装
补充
异步编程出现原因
js是单线程,同一时刻只允许一个代码块执行,耗时任务时,UI渲染阻塞
详情请看链接
- 概念上:promise是一门新的技术,E6中新出的规范,是用来解决JS中进行异步编程的新的解决方案(旧的方案是单纯的使用回调函数,会造成回调地狱)
- 表达上:是回调函数的形式,主要通过promise对象用来封装一个异步操作并可以获取其成功和失败的结果值
- 优势上:指定回调函数的方式更加灵活、支持链式调用,可以解决回调地狱问题
- 状态:pending 未决定的、resloved / fullfilled 成功、rejected 失败一旦改变不会再变
- 使用场景:异步AJAX请求,node中fs模块读取文件
12.浅拷贝深拷贝
2.拷贝数据的方式:
(1)直接赋值给一个变量(2)Object.assign() 浅拷贝ES6新出接口相当于扩展运算符
(3)Array.prototype.slice() 浅拷贝
(4)Array.prototype.concat() 浅拷贝
(5)扩展运算符…arr 浅拷贝
(6)JSON.parse(JSON.stringify()) 深拷贝
(7)Loadsh库中的API,如:.clone()、.cloneDeep()浅拷贝深拷贝
浅拷贝(对象,数组)
特点:拷贝的时候只是拷贝了一份引用,修改拷贝以后的数据会影响原来的数据。
浅拷贝只是拷贝一层,更深层次对象级别的值拷贝引用
如何浅拷贝:1.直接赋值 2.遍历赋值 3.ES6的语法糖,object.assign(给谁,拷贝谁)只要一层就没有问题
let a = {
age: 1,
color:[1,2,3],
like:{
sing:4,
dance:5
}
}
let b = {}
Object.assign(b, a);
b.like.sing = 2;
console.log(a.like.sing) // 原本是4现在变成了2这就是浅拷贝拷贝了复杂类型的地址
深拷贝(深度克隆)
特点:拷贝的时候会生成一份新的数据,修改拷贝以后的数据不会原数据。
拷贝多层,每一层的数据都会拷贝
let a = {
age: 1,
color:[1,2,3],
like:{
sing:4,
dance:5
}
}
let b = {}
var deepCopy = function(newObj,oldObj){
for(let k in oldObj){
// k是属性名,oldObj[k]是属性值
// 进行递归判断
let item = oldObj[k]
if(item instanceof Array){
// 设置新的对象的属性名并且声明类型
newObj[k] = []
// 再次调用
deepCopy(newObj[k],item)
}else if(item instanceof Object){
newObj[k] = {}
// 再次调用
deepCopy(newObj[k],item)
}else {
newObj[k] = item
}
}
}
deepCopy(b,a)
、、、简化代码
function deepClone(obj) {
var myObj = obj instanceof Array ? [] : {}
for (let key in obj) {
myObj[key] = typeof (obj[key]) =='object'?deepClone(obj[key]): obj[key]
}
return myObj
}
补充:深拷贝其他的实现方法
JSON.parse(JSON.stringify(obj))也可以实现深拷贝,但是弊端较多,例如无法识别undefined,symbol
lodash库里面的API_.cloneDeep(value).clone()
13.组件之间的通信
1、props和emit
2、Ref和
p
a
r
e
n
t
/
parent/
parent/children
3、eventBus\emit\on 兄弟、父子组件通信
4、$attrs\listeners 隔代通信
5、Provide\inject 隔代组件通信
6、Vuex
7、Pubsub库
父子组件props/
e
m
i
t
/
emit/
emit/parent/ref/
a
t
t
r
s
兄弟组件
attrs 兄弟组件
attrs兄弟组件parent/$root/eventbus/vuex
跨层级关系eventbus/vuex/provide+inject
14.JS数据类型/数据结构
数据类型区分:
- 基本数据类型
1.Symbol 代表创建后独一无二且不可变的数据类型,它主要是为了 解决可能出现的全局变量冲突的问题
2. BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数, 使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。
3.为什么会有 BigInt 的提案:JavaScript 中 Number.MAX_SAFE_INTEGER 表示最⼤安全数字,计算 结果是 9007199254740991,即在这个数范围内不会出现精度丢失(⼩ 数除外)。但是⼀旦超过这个范围,js 就会出现计算不准确的情况, 这在⼤数计算的时候不得不依靠⼀些第三⽅库进⾏解决,因此官⽅提 出了 BigInt 来解决此问题。
- 引用数据类型
存储位置区分
- 栈:原始数据类型直接存储在栈(stack)中的简单数据段,占据空间 小、大小固定,属于被频繁使用数据,所以放入栈中存储;
- 堆:引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固 定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈 中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引 用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
数据结构中
- 栈中数据的存取方式为先进后出。
- 堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。
操作系统中,内存被分为
- 栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的 值等。其操作方式类似于数据结构中的栈
堆区内存一般由开发者分配释放,若开发者不释放,程序结束时可 能由垃圾回收机制回收
15.对象和数组
一、区别?
-
数组表示有序数据的集合,而对象表示无序数据的集合。如果数据的顺序很重要,就用数组,否则就用对象
-
数组是种有顺序的链表,对象是无顺序的键值对。
-
数组有length属性,对象没有
二、判断一个对象为空对象 -
使用 JSON 自带的.stringify 方法来判断
let obj = {}
console.log(JSON.stringify(obj) == "{}"); //true
- ES6 新增的方法 Object.keys()来判断
let obj = {}
console.log(Object.keys(obj).length <= 0); //true
三、
16.数据类型的检测方式(包括区分对象和数组)
- typeof(数组,null和对象都是object,不能区分),能检测undefined、Boolean、number、string、object、function
- instanceof
instanceof 可以正确判断对象的类型,其内部运行机制是判断在其 原型链中能否找到该类型的原型。instanceof 运算符可以用来测试一个对象在其原型链 中是否存在一个构造函数的 prototype 属性 - 对象的constructor属性
constructor 有两个作用,一是判断数据的类型,二是对象实例通过 constrcutor 对象访问它的构造函数。需要注意,如果创建一个对象 来改变它的原型,constructor 就不能用来判断数据类型了
var arr = [1,2,3,1];
var obj = {
a:“A”,
c:“C”
}
console.log(arr.constructor === Array)//true
console.log(obj.constructor === Object) //true
- Array.isArray([]) //true ES6语法
- Object.prototype.toString.call(arr) 利用对象原型上的的toString可以准确判断是什么类型,call()改变this指向,这里是借用Object的方法
拓展:
1.为什么不用Object.toString?
答:虽然所有对象的原型链最顶端都是Object.prototype,但同时Object本身也是一个构造函数,继承于Function,而Array、function 等类 型作为 Object 的实例,都重写了 toString 方法。因此根据原型链上的知识,采用 obj.toString() 不能得到其对象类型,只能将 obj 转换为字符串类型;因此,在想要 得到对象的具体类型时,应该调用 Object 原型上的 toString 方法。2.num.toString()//“123”
- 把数字转换为字符串
- num.toString(2)//转换为二进制的字符串
17.instanceof手写实现
判断构造函数的原型是否出现在对象的原型链上的任何位置
// 判断构造函数的原型是否出现在对象的原型链上的任何位置
// left对象 right构造函数
function myInstanceof (left,right){
// 1.获取对象的原型
let proto = Object.getPrototypeOf(left)
// 2.获取构造函数的prototype对象
let prototype = right.prototype
while(true){
// 对象的原型不存在则返回或者递归判断的结束条件
if(!proto) return false
// 当构造函数的原型和对象的原型相等
if(proto = prototype) return true
// 如果没有找到,就继续从原型上去找,通过Object.getPrototype方法用来获取指定对象的原型
proto = Object.getPrototypeOf(proto)
}
}
18将一个数组转换为二进制
1.let a = x % n (n为几进制)
2. res += a
3. x / n
19.HTTP状态码
200 成功状态码
202服务器已经接收到请求数据,但尚未进行处理
204 NoContent 该状态码代表服务器接收的请求已成功处理,但在返回的响应报文中不含实体的主体部分在这里插入代码片
206 Partial Content 发送范围请求头Range抓取到资源的部分内容(大文件下载、分割多个部分同时下载等)
3XX响应结果表明浏览器需要执行某些特殊的处理以正确处理请求。
301 永久重定向(永久移动)该状态码表示请求的资源已被分配了新的URI已被分配了新的URI,以后应使用资源现在所指的URI
302 暂时重定向(临时移动)该状态码表示请求的资源已被分配了新的URI,希望用户(本次)能使用新的URI访问,但是这个的改变不是永久的。
303 该状态码表示由于请求对应的资源存在着另一个URI,应使用GET方法定向获取请求的资源。303状态码和302状态码有着相同的功能,但303状态码明确表示客户端应采用GET方法获取资源,这点与302状态码有区别
304协商缓存(请求的资源未修改)该状态码表示客户端发送附带条件的请求时,服务器允许请求访问资源,但未满足条件的情况。
304状态码返回时,不包含任何响应的主体部分
307临时重定向
400服务端无法理解(客户端语法错误)
401用户需要验证 该状态码表示发送请求需要有通过HTTP认证(BASIC认证、DIGEST认证)的认证信息
403请求已成功,但被拒绝未获得文件系统的访问授权,访问权限出现某些问题(从未授权的发送源IP地址试图访问)等列举的情况都有可能是发生403的原因
404找不到资源,请求资源不存在
500服务器内部错误 有可能是Web应用存在的bug或某些临时的故障
505服务器不支持请求的HTTP协议版本
20.项目部署
系统开发:修改端口server.port = 80 打包
服务器准备、环境配置:云服务,阿里云—云服务器ECS—实例—创建实例—购买服务器(cpu ,内存,硬盘,操作系统镜像)—网络配置(分配公网IPV4地址,带宽,安全组中Linux端口22,window端口3389)—会有公网和私网IP,用户名和密码
在操纵系统中安装目标程序所需要的环境:用FTP工具将本地上传到服务器,建立连接—主机:公网IP,协议:SFTP/SSH 端口: 用户名: 密码:
程序部署及运行:打包–上传(FTP工具)—启动
域名绑定:字母与IP绑定,访问域名相当于访问IP地址,购买域名—域名备案(ICP)—域名解析(解析,添加记录:记录值是IP地址,域名)
二、第二回合
1.VUE vuex的五大属性和工作原理
state, getters, mutations, actions, modules。
1.state:vuex的基本数据,用来存储变量
在vue中使用 this.$store.state.userId
2.geeter:从基本数据(state)派生的数据,相当于state的计算属性,具有返回值的方法
在vue中使用 this.$store.getters.userIdDouble
3.mutation:提交更新数据的方法,必须是同步的(如果需要异步使用action)。每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
commit 同步操作,写法: this.$store.commit(‘mutations方法名’,值)
4.action:和mutation的功能大致相同,不同之处在于 ==》1. Action 提交的是 mutation,而不是直接变更状态。 2. Action 可以包含任意异步操作。
dispatch:异步操作,写法: this.$store.dispatch(‘mutations方法名’,值)
5.modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
简单来说就是可以把以上的 state、mutation、action、getters 整合成一个user.js,然后放到store.js里面
2.vue生命周期之间的差别
生命周期:每一个vue实例从创建到销毁的过程就是vue这个实例的生命周期
生命周期过程:开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、卸载等一系列过程
- 1.beforeCreate(创建前)在实例初始化之后执行此时对象还未创建,el 和data并未初始化,因此无法访问 methods,data ,computed等方法和数据。
使用场景:可以在此时加一些 loading 效果,在 created 时进行移除。
- 2.create(创建后) 最早开始使用data和methods中的数据的钩子函数,这个阶段可以数据请求,但是不能dom操作。
使用场景:需要异步请求数据的方法可以在此时执行,完成数据的初始化。
- 3.beforeMounted(挂在前)挂载开始之前被调用,把data里面的数据和模板生成html,完成了el和data初始化,注意此时还没有挂载到html页面上。
- mounted(挂载后)挂载完成,HTML已经被渲染到了页面上,这个阶段可以执行dom操作,可以进行数据请求。
使用场景: 当需要操作 dom 的时候执行,可以配合$.nextTick 使用进行单一事件对数据的更新后更新dom。
- 4.beforeUpdate(更新前)数据更新前调用,当data的数据发生改变会执行这个钩子 内存中数据是新的 页面是旧的。
- 5.update(更新后) 由于数据更改导致的虚拟 DOM 重新渲染,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。注意 updated 不会保证所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以在 updated 里使用 vm.$nextTick。
使用场景: 当数据更新需要做统一业务处理的时候使用。
- 6.beforeDestory(销毁前)实例销毁之前调用,在这一步还可以做一些释放内存的操作
- destory(销毁后)实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有.的事件监听器被移除,所有的子实例也都被销毁。
- 7.errorCaptured 当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。
- 8.activated keep-alive 缓存的组件激活时调用。
- 9.deactivated keep-alive 缓存的组件停用时调用。
- 10.$nextTick
- Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。(Vue 在更新 DOM 时是异步执行的)
- vue响应式的改变一个值以后,此时的dom并不会立即更新,如果需要在数据改变以后立即通过dom做一些操作,可以使用$nextTick获得更新后的dom。(根据异步请求获取后的数据从而渲染DOM结构,可以结合wacth监听属性配合)
- $nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM。
补充
VUE数据请求放在created还是mounted?
如果在mounted钩子函数中请求数据可能导致页面闪屏问题
其实就是加载时机问题,放在created里会比mounted触发早一点,如果在页面挂载完之前请求完成的话就不会看到闪屏了
3.HTMLmeta标签的作用
meta标签用来描述一个HTML网页文档的属性
有四种属性:1.charset、2.name、3.content、4.http-equiv
- charset: 页面中的必须标签,说明页面是UTF-8格式,防止乱码。
unicode UTF-8详情http://t.csdn.cn/P8WaN - name: name属性主要用于描述网页,content中为属性对应的属性值,content中的属性值主要是便于搜索引擎机器人查找信息和分类信息用的。
name的参数有:
keywords(关键字)为搜索引擎提供网站的关键字
description(网站内容描述)为搜索引擎提供网站主要内容。
application-name(应用程序名称)
viewport(用于移动端页面控制)指定页面控制及缩放比例。content内容如下:
width:设置layout viewport 的宽度,为一个正整数,或字符串"width-device"
initial-scale:设置页面的初始缩放值,为一个数字,可以带小数,通常为1.0(1.0为正常大小)
minimum-scale:允许用户的最小缩放值,为一个数字,可以带小数
maximum-scale:允许用户的最大缩放值,为一个数字,可以带小数
- http-equiv:指示服务器在发送实际的文档之前先在要传送给浏览器的 MIME 文档头部包含名称/值对。
http-equiv的参数有:refresh重定向,在规定的时间之后跳转到另一页面
<meta http-equiv="refresh" content="5;url=http://www.w3school.com.cn" />
4.Doctype有什么作用
DOCTYPE是document type (文档类型) 的缩写。声明位于文档的最前面,处于标签之前,它不是html标签。主要作用是告诉浏览器的解析器使用哪种HTML规范或者XHTML规范来解析页面。
5.本地存储
把数据存到用户的浏览器里面
设置方便,易于读取,甚至刷新页面也不会丢失数据
只能储存字符串,可以将对象JSON.stringify()编码后存储
6.用户注册登录实现大概步骤
登录页面、用户点击登录过程,从前端拿数据和后台拿数据以及从数据库拿数据
用户点击页面登录—前端页面vue组件获取表单的值—判断是登录还是注册,处理请求—后端—返回成功或失败数据
- 1.注册–通过数据库存储用户信息(名字,密码)接口post
- 2.登录–登录成功的时候,后台为了区分用户是谁,下发令牌token,用户前台持久化localStorage.setItem存储token。(组件派发action:userLogin通过Vuex的异步操作action,执行dispatch操作—执行异步操作,发送post请求(此处因为是前后端分离项目,通过webpack的proxy解决跨域问题)—请求发送到后端后,),路由在进行跳转。
- 3.登录过后用户信息页展示,在首页中的mounted中派发action
- 4.退出登录,清除token,action不能直接操作state,commit提交给mutation修改state
注意:
vuex仓库存储数据—不是持久化
配置路由守卫:router.beforeEach((to,from,next)=》{}) //进行条件判断然后跳转路由
7.CSS盒子居中显示
1.定位 子绝父相
- 1.1 margin设置为auto
.child {
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
margin: auto; }
- 1.2 transform使子盒子往“回”移动自己宽高的一半
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
2.flex布局
将父盒子设置成弹性盒容器
让子元素水平居中,垂直居中
.parent {
display: flex;
justify-content: center;
align-items: center;
}
- 3.inline-block行内块元素
text-align: center; 只对行内元素和行内块元素有用
.parent {
text-align: center;
line-height: 500px;
}
.child {
display: inline-block;
vertical-align: middle; vertical-align 属性设置一个元素的垂直对齐方式。middle把此元素放置在父元素的中部。
}
CSS盒子右边固定,左边自适应
1.固定盒子浮动+ 自适应盒子width: 100%;//宽度等于百分之百
.left {
float: left;
width: 200px;
height: 400px;
background: red;
}
.right {
width: 100%;//宽度等于百分之百
height: 400px;
margin-left: 200px;
background: blue;
}
2.flex布局父容器设置 display:flex;Right部分设置 flex:1
.box{ display: flex;}
.left{width:200px;background: red;}
.right{width:%;flex:1;background: blue;}/等于左边栏宽度/
3.左右两边都绝对定位
.left{width:200px;background: red; position: absolute;left:;}
.right{width:100%;background: blue;position: absolute;left:200px;}/等于左边栏宽度/
8.Flex布局
Flex布局后,子元素的float、clear和vertical-align属性将失效
(父)容器的一些属性:
- flex-direction 属性设置容器主轴的方向
- flex-wrap 置当项目在容器中一行无法显示的时候如何处理
- flex-flow 属性是flex-deriction和flex-wrap属性的简写,默认值为[row nowrap]
- justify-content 设置项目在容器中的对齐方式
- align-items 项目在交叉轴上是如何对齐显示的
(子)项目上的属性:
- order 设置项目排序的位置,默认值为0,数值越小越靠前
- flex flex-grow属性、flex-shrink属性、flex-basis属性的简写。默认值为:0 1 auto;
- align-self 当前项目可以和其他项目拥有不一样的对齐方式
9.MVVM模式
MVVM分为Model、View、ViewModel三者。
- Model:代表数据模型,数据和业务逻辑都在Model层中定义;
- View:代表UI视图,负责数据的展示;
- ViewModel:负责监听Model中数据的改变并且控制视图的更新,处理用户交互操作;
- Model和View并无直接关联,而是通过ViewModel来进行联系的,Model和ViewModel之间有着双向数据绑定的联系。因此当Model中的数据改变时会触发View层的刷新,View中由于用户交互操作而改变的数据也会在Model中同步。
这种模式实现了Model和View的数据自动同步,因此开发者只需要专注对数据的维护操作即可,而不需要自己操作dom。
补充
MVC:原生JS方法
10.节流和防抖
节流:一定的间隔时间内只执行一次,如果这个单位时间内触发多次函数,只有一次生效。 滚动事件,鼠标点击事件
防抖:事件被触发n秒后再执行回调,n秒内又被触发则重新计时
11.懒加载
懒加载也叫延迟加载
- 图像懒加载:指的是在长网页中延迟加载图像,是一种很好优化网页性能的方式。
首先将页面上的图片的 src 属性设为空字符串,而图片的真实路径则设置在 data-original 属性中,当页面滚动的时候需要去监听 scroll 事件,在 scroll 事件的回调中,判断我们的懒加载的图片是否进入可视区域,如果图片在可视区内则将图片的 src 属性设置为 data-original 的值,这样就可以实现延迟加载。
- 路由懒加载:整个网页默认是刚打开就去加载所有页面,路由懒加载就是只加载你当前点击的那个模块。按需去加载路由对应的资源
将路由相关的组件,不再直接导入了,而是改写成异步组件的写法,只有当函数被调用的时候,才去加载对应的组件内容。
routes: [
{ path: '/login', component: () => import('@/views/login/index.vue') },
{ path: '/home', component: () => import('@/views/home/home.vue') }
]
12.预编译、作用域、变量提升、事件委派
预编译
- Js引擎会在正式执行之前先进行一次预编译,在这个过程中,首先将变量声明及函数声明提升至当前作用域的顶端,然后进行接下来的处理
作用域
- 变量作用域:变量起作用的范围。函数以外的变量都称之为全局变量,以内的称为局部变量,局部变量和全局变量同名时,局部变量优先。
- 函数作用域:也称为局部作用域,函数声明时就形成,在函数内声明的所有变量在函数体内始终有定义。函数内部的变量不会被函数外部访问,函数内部可以访问全局的变量。
变量提升
- 变量提升:只会提升变量的声明,不会提升变量的赋值初始化
- 函数提升:一般使用函数声明和函数表达式(var a = function (){})声明函数,将函数声明整个都提升到当前作用域的顶部。函数提升优先于变量提升
事件委派
- 事件的委派也叫事件代理,简单理解就是:原本是某个元素需要绑定的事件,现在将这个事件交给别的元素去做,正常我们把它交给父级元素,比如:原本是给li绑定点击事件,现在交给它父级ul绑定,利用冒泡原理,点击li的时候会触发ul的事件;
- 好处:提升性能, 比如要给100个li安装点击事件,正常我们会用for循环去个每个li安装,这样与访问dom的次数多,性能也比较低;利用冒泡原理,给ul安装点击事件(就是委派ul代理这个事件),点击li的事件由ul去执行,这样就只访问一次dom,性能就提升了;
13.JS执行机制
js最大特点是单线程的,单线程意味着所有任务需要排队
- JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事
- JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。如果多个线程一起操作同一个DOM就会引发很多问题。
- 多核CPU的计算能力,HTML5提出Web Worker标准,允许javascript脚本创建多个线程,于是js出现了同步和异步。
- JS解决单线程的弊端:同步任务和异步任务,异步任务放在任务队列中,同步任务是主线程上执行的任务。只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入”任务队列”(task queue)的任务,只有”任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
同步异步任务执行机制
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。 事件循环:主线程从”任务队列”中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)
14.异步任务(宏任务和微任务)
1.js宏任务有:
15.定时器的秒数为0是不是立即执行函数
回答:不是
- setTimeout(fn, 0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是说,当前代码执行完(执行栈清空)以后,尽可能的早执行。它在“任务队列”的尾部添加一个事件,因此要等到同步任务和“任务队列”现有的事件都处理完,才会得到执行。
- HTML5标准setTimeout()的第二个参数的最小值不得小于4毫秒,如果低于这个值,则默认是4毫秒。在此之前。老版本的浏览器都将最短时间设为10毫秒。另外,对于那些DOM的变动(尤其是涉及页面重新渲染的部分),通常是间隔16毫秒执行。
16.Es6的常用的新特性
- 箭头函数
- 解构赋值
- 剩余参数
- let,const
- symbol,bigInt
- class类继承
补充面试题:
1.箭头函数与普通函数区别
- 箭头函数没有this,所以需要通过查找作用域链来确定this的值
- 箭头函数没有自己的arguments对象,但是可以访问外围函数的arguments对象
- 不能通过 new 关键字调用,同样也没有 new.target值和原型
2.let,const解决什么问题
解决:变量污染问题 引入块级声明:声明在指定块的作用域之外无法访问的变量
Var:定义一个变量,可以重复赋值,重复定义;有变量提升,变量可以在声明之前使用,值为undefined;在浏览器环境下声明变量会挂载到window上。
Let:定义一个变量,可以重复赋值,不可以重复定义;块级作用域,也称词法作用域,没有变量提升,存在暂时性死区;全局作用域下创建一个新的绑定,该绑定不会添加为全局对象的属性。
Const:定义一个常量,声明时必须赋值,也就是必须初始化,不可以重复赋值,不可以重复定义,常量如果是对象,对象中的值可以修改;块级作用域,也称词法作用域,没有变量提升,存在暂时性死区3.暂时性死区( temporal dead zone,简称TDZ
- ES6新增的let、const关键字声明的变量会产生块级作用域,如果变量在当前作用域中被创建之前被创建出来,由于此时还未完成语法绑定,如果我们访问或使用该变量,就会产生暂时性死区的问题,由此我们可以得知,从变量的创建到语法绑定之间这一段空间,我们就可以理解为‘暂时性死区’
其他方面也会出现暂时性死区域吗?- let/const关键字未出现之前,typeof运算符是百分之百安全的,现在也会引发暂时性死区的发生,像import关键字引入公共模块、使用new
class创建类的方式,也会引发暂时性死区,究其原因还是变量的声明先与使用
18.跨域的方法
CORS:
JSONP:
可跨域标签
<img src=""> //图片
<link href=""> //css
<script src=""> //程序
配置代理服务器:
19.v-if v-show
- V-show不会对DOM进行操作,而是操作display值
- V-if对DOM进行操作,对其进行增加和删除
- V-if相对消耗浏览器的性能,若频繁的切换,使用v-show较好
20.nodejs的express
定义:最小且灵活的web应用程序框架,为web和移动应用程序提供了一组强大的功能,它的行为就像是一个中间件,可以帮助管理服务器和路由。
优点:简单、灵活、简约和可扩展;提供快速生成工具express-generator,快速开发web应用。
其他框架
Koa:是一个新的web框架,由Express幕后的原班人马打造,致力于成为web应用和API开发领域中的一个更小、更富有表现力、更健壮的基石。用async函数代替回调函数。优点:集成大量webAPI,没有绑定中间件;非常轻量;try/catch更好处理错误;代码可读性和维护性相对较高。
Hapi:基础功能相对丰富的框架,开发人员专注于业务而不是项目构建。优点:提供了缓存、身份验证和输入验证;提供众多企业插件。
三、第三回合
1.JS垃圾回收机制
原文链接:详情
来源:解决内存的泄露,垃圾回收机制会定期(周期性)找出那些不再用到的内存(变量),然后释放其内存。
现在各大浏览器通常采用的垃圾回收机制有两种方法:1.标记清除,2.引用计数。
- 标记清除
js中最常用的垃圾回收方式就是标记清除。垃圾回收机制在运行的时候会给存储再内存中的所有变量都加上标记(可以是任何标记方式),然后,它会去掉处在环境中的变量及被环境中的变量引用的变量标记(闭包)。而在此之后剩下的带有标记的变量被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后垃圾回收机制到下一个周期运行时,将释放这些变量的内存,回收它们所占用的空间。
工作原理:
当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。
工作流程:
垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记; 去掉环境中的变量以及被环境中的变量引用的变量的标记;
被加上标记的会被视为准备删除的变量; 垃圾回收器完成内存清理工作,销毁那些带标记的值并回收他们所占用的内存空间。
到目前为止,IE、Firefox、Opera、Chrome、Safari的js实现使用的都是标记清除的垃圾回收策略或类似的策略,只不过垃圾收集的时间间隔互不相同。
- 引用计数
语言引擎有一张"引用表",保存了内存里面所有资源(通常是各种值)的引用次数。如果一个值的引用次数是0,就表示这个值不再用到了,因此可以将这块内存释放。
工作原理:跟踪记录每个值被引用的次数。
工作流程:
声明了一个变量并将一个引用类型的值赋值给这个变量,这个引用类型值的引用次数就是1
同一个值又被赋值给另一个变量,这个引用类型值的引用次数加1;
当包含这个引用类型值的变量又被赋值成别的值了,那么这个引用类型值的引用次数减1; 当引用次数变成0时,说明没办法访问这个值了。
当垃圾收集器下一次运行时,它就会释放引用次数是0的值所占的内存;
扩展:
但是,为了减少内存垃圾,我们还是可以对javascript代码进行彻底检查,有些代码中存在明显的产生过多内存垃圾的问题代码,这些正是我们需要检查并且完善的。
2.form表单的使用以及相应的属性值
type:
- type=”text”是定义表单里面的单行文本框;
- type=”password” 定义密码框;
- type=”radio” 单选勾选框;
- type=”checkbox” 多选勾选框;
- type=”submit” 提交按钮;
- type=”reset” 重置按钮;
- type=”button”或者 两种方式都可以实现空按钮;
menthod - 其中 get/post 之间的区别
- get传送的数据量较小,不能大于2KB。post传送的数据量较大,
- get安全性非常低,post安全性较高。但是执行效率却比Post方法
好。
action - action=url用来指定处理提交表单的格式.它可以是一个URL地址(提交给程式)或一个电子邮件地址.
target - ”“指定提交的结果文档显示的位置:
-
- _blank :在一个新的、
无名浏览器窗口调入指定的文档;
- _blank :在一个新的、
- _self :在指向这个目标的元素的相同
的框架中调入文档; - _parent :把文档调入当前框的直接的 frameset框中;
3.vue中的双向数据绑定原理(重点深入学习)
vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变;
- 核心:关于VUE双向数据绑定,其核心是 Object.defineProperty()方法
- (1)Object.defineProperty(obj, prop, descriptor) ,这个语法内有三个参数,分别为 obj (要定义其上属性的对象) prop (要定义或修改的属性) descriptor (具体的改变方法)
- (2)简单地说,就是用这个方法来定义一个值。当调用时我们使用了它里面的get方法,当我们给这个属性赋值时,又用到了它里面的set方法;
4.vue单向数据流
vue单向数据流:在vue中需要遵循单向数据流原则
在父传子的前提下,父组件的数据发生会通知子组件自动更新
子组件内部,不能直接修改父组件传递过来的props => props是只读的
5.undefined、null、NaN有什么区别?
从数据类型上:
- undefined和null是原始数据类型,当使用双等号对两种类型的 值进行比较时会返回 true,使用三个等号时会返回 false,NaN表示为not a number,用typeof检测undefined返回undefined,null返回object,NaN返回number
从使用场景上:
- undefined 表示未定义是所有没有赋值变量的默认值,是自动赋值为undefined
- null 表示空值,可以用null赋值给变量去清空变量
- NaN的场景就比较多,比如数据的类型转换时,被转换的数据不含有可以转换的部分,就会返回NaN
注意:NaN是一种特殊类型的的number,它与任何数据都不相等,包括自己本身,其他数据类型和NaN运算的结果都是NaN
7.如何获取安全的undefined 值?
因为 undefined 是一个标识符,不是保留字,所以可以被当作变量来使用和赋值, 但是这样会影响 undefined 的正常判断。表达式 void ___ 没有返 回值,因此返回结果是 undefined。void 并不改变表达式的结果, 只是让表达式不返回值。因此可以用 void 0 来获得 undefined。
void后跟一个表达式 void(expression),他会执行这个表达式,然后返回undefined
可以使用void 0来代替undefined,因为undefind不是保留字。所以在某些浏览器下,undefind的值可能会被修改。
8.Object.is() 与比较操作符 “=== ” 、 “==” 的区别?
- 使用双等号(==)进行相等判断时,如果两边的类型不一致,则会进 行强制类型转化后再进行比较。
- 使用三等号(===)进行相等判断时,如果两边的类型不一致时,不 会做强制类型准换,直接返回 false。
- 使用 Object.is 来进行相等判断时,一般情况下和三等号的判断相 同,它处理了一些特殊的情况,比如 -0 和 +0 不再相等,两个 NaN 是相等的 一般情况下NaN不与任何类型相等包括自身
9. 什么是 JavaScript 中的包装类型?
在 JavaScript 中,基本类型是没有属性和方法的,但是为了便于操 作基本类型的值,在调用基本类型的属性或方法时 JavaScript 会在 后台隐式地将基本类型的值转换为对象,例如字符串
const a = 'abc'
console.log(a.length); //3
- 使用Object ()函数显式地将基本类型转换为包装类 型
- valueOf ()方法将包装类型倒转成基本类型
10.const 对象的属性可以修改吗
- const 保证的并不是变量的值不能改动,而是变量指向的那个内存地 址不能改动
- 对于基本类型的数据(数值、字符串、布尔值),其值 就保存在变量指向的那个内存地址,因此等同于常量
- 引用类型的数据(主要是对象和数组)来说,变量指向数据的 内存地址,保存的只是一个指针,const 只能保证这个指针是固定不 变的,至于它指向的数据结构是不是可变的,就完全不能控制了(例如给对象添加一个新的方法和值)
11.new 操作符的实现步骤
- 1.创建一个新对象
- 2.将构造函数的作用域赋给新对象(也就是将对象的__proto__属性 指向构造函数的 prototype 属性)
- 3.构造函数中的 this 指向该对象,执行构造函数中的代码(也就是 为这个对象添加属性和方法)
- 4.返回新的对象
如果是new一个箭头函数可以吗?
回答:不可以,箭头函数它没有prototype,也没有自己的this 指向,更不可以使用 arguments 参数,所以不能 New 一个箭头函数。
12.this指向问题(JS高级)
this 是执行上下文中的一个属性,它指向最后一次调用这个方法的 对象。
- 默认绑定
- 隐式绑定
- 显示绑定
call(默认传入数据没有格式)
applay(传入数据是一个数组)
bind(传入参数可以是数组或者直接传入都可)但是bind可以减少call和apply多次绑定同一个对象造成的代码冗余。因为bind会返回一个回调函数,在使用多顶绑定时直接调用回调函数即可。
- new关键字进行绑定
13.JavaScript 脚本延迟加载的方式有哪些?
延迟加载就是等页面加载完成之后再加载 JavaScript 文件。js 延 迟加载有助于提高页面加载速度。
- defer 属性:给 js 脚本添加 defer 属性,这个属性会让脚本的加 载与文档的解析同步解析,然后在文档解析完成后再执行这个脚本文 件,这样的话就能使页面的渲染不被阻塞。多个设置了defer 属性的脚本按规范来说最后是顺序执行的,但是在一些浏览器中可能不是 这样。
- async 属性:给 js 脚本添加 async 属性,这个属性会使脚本异步 加载,不会阻塞页面的解析过程,但是当脚本加载完成后立即执行 js 脚本,这个时候如果文档没有解析完成的话同样会阻塞。多个 async 属性的脚本的执行顺序是不可预测的,一般不会按照代码的顺序依次 执行。
- 动态创建 DOM 方式:动态创建 DOM 标签的方式,可以对文档的加载 事件进行监听,当文档加载完成后再动态的创建 script 标签来引入 js 脚本。
- 使用 setTimeout 延迟方法:设置一个定时器来延迟加载 js 脚本文 件
- 让 JS 最后加载:将 js 脚本放在文档的底部,来使 js 脚本尽可能 的在最后来加载执行。
14.对 JSON 的理解
- JSON 是一种基于文本的轻量级的数据交换格式。它可以被任何的编 程语言读取和作为数据格式来传递。
- 在项目开发中,使用 JSON 作为前后端数据交换的方式。在前端通过 将一个符合 JSON 格式的数据结构序列化为 JSON 字符串,然后将它传递到后端,后端通过 JSON 格式的字符串 解析后生成对应的数据结构,以此来实现前后端数据的一个传递
- 因为 JSON 的语法是基于 js 的,因此很容易将 JSON 和 js 中的对 象弄混,但是应该注意的是 JSON 和 js 中的对象不是一回事,JSON 中对象格式更加严格,比如说在 JSON 中属性值不能为函数,不能出 现 NaN 这样的属性值等,因此大多数的 js 对象是不符合 JSON 对 象的格式的。
在 js 中提供了两个函数来实现 js 数据结构和 JSON 格式的转换 处理
JSON.stringify 函数,通过传入一个符合 JSON 格式的数据结构, 将其转换为一个 JSON 字符串。如果传入的数据结构不符合 JSON 格 式,那么在序列化的时候会对这些值进行对应的特殊处理,使其符合 规范。在前端向后端发送数据时,可以调用这个函数将数据对象转化 为 JSON 格式的字符串。
JSON.parse() 函数,这个函数用来将 JSON 格式的字符串转换为一 个 js 数据结构,如果传入的字符串不是标准的 JSON 格式的字符串 的话,将会抛出错误。当从后端接收到 JSON 格式的字符串时,可以 通过这个方法来将其解析为一个 js 数据结构,以此来进行数据的访 问
15.什么是 DOM 和 BOM?
- DOM 指的是文档对象模型,它指的是把文档当做一个对象,这个对象 主要定义了处理网页内容的方法和接口。
- DOM 的最根本的对象 document 对象也是 BOM 的 window 对象的子对象。
- BOM 指的是浏览器对象模型,它指的是把浏览器当做一个对象来对待, 这个对象主要定义了与浏览器进行交互的法和接口。BOM 的核心是 window,而 window 对象具有双重角色,它既是通过 js 访问浏览器 窗口的一个接口,又是一个 Global(全局)对象。
- window 对象含有 location 对象、navigator 对象、screen 14
对象等子对象
16.原型和原型链的理解
- 原型:在 JavaScript 中是使用构造函数来新建一个对象的,每一个构造函 数的内部都有一个 prototype 属性,它的属性值是一个对象,这个 对象包含了可以由该构造函数的所有实例共享的属性和方法。当使用 构造函数新建一个对象后,在这个对象的内部将包含一个指针,这个 指针指向构造函数的 prototype 属性对应的值,在 ES5 中这个指针 被称为对象的原型
- Object.getPrototypeOf() 方法,可以通过这个方法来获取对象的原 型。
- 原型链:当访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原 型,于是就这样一直找下去,也就是原型链的概念。
- JavaScript 对象是通过引用来传递的,创建的每个新对象实 体中并没有一份属于自己的原型副本。当修改原型时,与之相关的对 象也会继承这一改变
- 原型链的终点:由于 Object 是构造函数,原型链终点 Object.prototype.proto, 而 Object.prototype.proto=== null // true,所以,原型链 的终点是 null。原型链上的所有原型都是对象,所有的对象最终都 是由 Object 构造的,而 Object.prototype 的下一级是 Object.prototype.proto。
17.作用域、作用域链的理解
作用域:
全局作用域
- 最外层函数和最外层函数外面定义的变量拥有全局作用域
- 所有未定义直接赋值的变量自动声明为全局作用域
- 所有 window 对象的属性拥有全局作用域 全局作用域有很大的弊端,过多的全局作用域变量会污染全局命名空 间,容易引起命名冲突
函数作用域
- 函数作用域声明在函数内部的变零,一般只有固定的代码片段可以访 问到作用域是分层的,内层作用域可以访问外层作用域,反之不行
块级作用域
-使用 ES6 中新增的 let 和 const 指令可以声明块级作用域,块级作用 域可以在函数中创建也可以在一个代码块中的创建(由{ }包裹的代 码片段) - let 和 const 声明的变量不会有变量提升,也不可以重复声明 在循环中比较适合绑定块级作用域,这样就可以把声明的计数器变量 限制在循环内部。
作用域链:
- 在当前作用域中查找所需变量,但是该作用域没有这个变量,那这个 变量就是自由变量。如果在自己作用域找不到该变量就去父级作用域 查找,依次向上级作用域查找,直到访问到 window 对象就被终止, 这一层层的关系就是作用域链。
- 作用域链的作用是保证对执行环境有权访问的所有变量和函数的有 序访问,通过作用域链,可以访问到外层环境的变量和函数。
18.Proxy 可以实现什么功能?
ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例
- 希望监听一个对象的相关操作,那么我们可以先创建一个代理对象(Proxy对象);
- 之后对该对象的所有操作,都通过代理对象来完成,代理对象可以监听我们想要对原对象进行哪些操作 首先,我们需要new
- Proxy对象,并且传入需要侦听的对象以及一个处理对象,可以称之为handler; üconst p = new Proxy(target,
- handler) 之后的操作都是直接对Proxy的操作,而不是原有的对象,因为我们需要在handler里面进行侦听;
19.常用的正则表达式有哪些?
大佬整理的很全,大家自行跳转链接,但是希望能够养成自己动手编辑正则的技能。
20.escape、encodeURI、encodeURIComponent 的区别
JavaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encodeURIComponent
- escape是对字符串(string)进行编码(而另外两种是对URL),作用是让它们在所有电脑上可读
- encodeURI方法不会对下列字符编码 ASCII字母、数字、~!@#$&*()=:/,;?+’
- encodeURIComponent方法不会对下列字符编码 ASCII字母、数字、~!*()’
总结
escape()除了 ASCII 字母、数字和特定的符号外,对传进来的字符串全部进行转义编码,因此如果想对URL编码,最好不要使用此方法。而encodeURI() 用于编码整个URI,因为URI中的合法字符都不会被编码转换。encodeURIComponent方法在编码单个URIComponent(指请求参 数)应当是最常用的,它可以讲参数中的中文、特殊字符进行转义,而不会影响整个URL。
四、第四回合
1.什么是尾调用,使用尾调用有什么好处?
尾调用指的是函数的最后一步调用另一个函数。
- 代码执行是基于执行 栈的,所以当在一个函数里调用另一个函数时,会保留当前的执行上 下文,然后再新建另外一个执行上下文加入栈中。
- 使用尾调用的话, 因为已经是函数的最后一步,所以这时可以不必再保留当前的执行上 下文,从而节省了内存,这就是尾调用优化
- 但是 ES6 的尾调用优 化只在严格模式下开启,正常模式是无效的
2.ES6 模块与 CommonJS 模块有什么异同?
- CommonJs中使用module.exports导出变量及函数,也可以导出任意类型的值,CommonJs解决了变量污染,文件依赖等问题
Node.js 导出 module.exports = {} exports.xxx = ‘xxx’ 引入:require()
- ESmoudel:解决了变量污染问题,依赖顺序问题,Es Module语法也是更加灵活,导出值也都是导出的引用,导出变量是可读状态,这加强了代码可读性。
单个导出(export)、默认导出(export default),单个导出在导入时不像CommonJs一样直接把值全部导入进来了,Es Module中可以导入我想要的值。那么默认导出就是全部直接导入进来,当然Es Module中也可以导出任意类型的值
ES6 导出:export 导入:import xxx from ‘/xxx’
两者区别:
CommonJs
CommonJs可以动态加载语句,代码发生在运行时
CommonJs混合导出,还是一种语法,只不过不用声明前面对象而已,当我导出引用对象时之前的导出就被覆盖了
CommonJs导出值是拷贝,可以修改导出的值,这在代码出错时,不好排查引起变量污染
Es Module
EsModule是静态的,不可以动态加载语句,只能声明在该文件的最顶部,代码发生在编译时
Es Module混合导出,单个导出,默认导出,完全互不影响
Es Module导出是引用值之前都存在映射关系,并且值都是可读的,不能修改
3.for…in 和 for…of 的区别
for…of 是 ES6 新增的遍历方式,允许遍历一个含有 iterator 接口 的数据结构(数组、对象等)并且返回各项的值
区别:
- for…of 遍历获取的是对象的键值,for…in 获取的是对象的键名;
- for… in 会遍历对象的整个原型链,性能非常差不推荐使用,而 for … of 只遍历当前对象不会遍历原型链;
4.ajax、axios、fetch(前台请求后台数据的方式)
ajax: 是指的是通过 JavaScript 的 异步通信,从服务器获取 XML 文档从中提取数据, 再更新当前网页的对应部分,而不用刷新整个网页。原生冗余。
jquery封装的$ajax
请求的格式默认是表单格式
$.ajax({
//扩展方法,设置请求方法
methods:"POST"
//请求的参数 (1.post默认表单格式的提交,2.get:queryString)
//3.json格式请求
header:{'Content-type':'application/json'}
//请求参数
data:JSON.stringfy({a:10})
//请求地址
url(http://localhost:99),
//拿到调用的数据
success:function(data){
conssole.log(data)
}
})
fetch
现在浏览器自带,不用下载任何的js包
//返回的是promise
fetch("http:/localhost:99?b=2",{
//加入指定参数
method:"POST"
//以表单的形式提交
//也可以JSON方式提交
header:{"content-type":"application/x-www-form-urlencoded"}
//请求参数
body:"a=12&b=33"
}).then(response=>response.json()).then(data=>console.log(data)
axios
不仅可以再前端进行http的请求,也可以在后端进行http的请求
请求的格式默认是JSON格式
axios({
url:"http://localhost:99?b=2",
method:"POST",
//支持表单的格式提交
header:{"content-type":"application/x-www-form-urlencoded"}
data:"a=123&b=156"
data:{a:12}
//then方法 拿到调用的数据
}).then(res=>console.log(res.data))
详情总结链接
5. parseInt()的用法
- parseInt方法接收两个参数,parseInt(string,radix?);
- string:要被解析的值。如果参数不是一个字符串,则将其转换为字符串(toString)。字符串开头的空白符将会被忽略。tostring()也是可以转换进制。
- radix:可选。从 2 到 36,表示被解析的值的进制。例如说指定 10 就等于指定十进位。
6.浏览器运行机制
- 构建DOM 树
- 构建渲染树
- 布局渲染树(重排)layout
- 绘制渲染树(重绘)paint
重绘重排的代价:耗时,导致浏览器卡慢
优化:合并多次的DOM和样式的修改,直接改变元素的className
7.border-radius:50%和100%究竟有什么区别
- 建议使用border-radius = 50% 来避免浏览器不必要的计算。值得注意的是在涉及到与圆角相关动画的情况下,值为50%和100%,在动画效果上会有不同。
- 其实这是W3C对于重合曲线有这样的规范:如果两个相邻角的半径和超过了对应的盒子的边的长度,那么浏览器要重新计算保证它们不会重合。
8.alt和title
- alt定义元素的替换文本,title定义元素的提示文本。
- alt 属性只能用在 img、area、input元素中
- 给p标签添加属性title,把鼠标移动到该段落的文字上面,就会显示title内容,起到补充说明和提示的效果
9. new Number(1)和1是否全等
let a = 1
let b = new Number(1) //Numer构造函数创建出来的数字(对象)
console.log(a == b);
console.log(a===b);
10.a.length 重新赋值后会怎样
let a = [1,2,3,4,5,6]
// a.length = 10
// console.log(a); //空属性*4
a.length = 3
console.log(a); //相当于截取字符串
11.CSS属性继承
关键字:inherited
12.vue文件变成.html文件渲染
.vue—>编译之后变为渲染函数—>渲染虚拟DOM树->(跟踪依赖关系)—>渲染真实DOM
13.观察者模式+发布订阅模式
观察者模式:将有观察方法的观察者存到被观察者中(数组存储),当被观察者更新状态的时候,再调用观察者的观察方法(update)
发布订阅模式:简单模式:发布者有发布和订阅方法,订阅的时候传入订阅者进去,保存订阅者(数组存储),发布时循环数组订阅者依次进行通知。有callback方法.
14.JS继承
现继承的方法原生和新特性(class)
原型链继承
构造函数继承
组合继承
寄生继承
寄生组合继承
类继承
15CDN
概念:内容分发网络。
- 其目的是通过在现有的internet中增加一层新的网络架构,将网站的内容发布到最接近用户的网络边缘,使用户可以就近取得所需的内容,提高用户访问网站的响应速度。CDN有别于镜像,因为它比镜像更智能,或者可以做这样一个比喻:CDN=更智能的镜像+缓存+流量导流。
- 通过相互连接的网络系统,将源站中的资源分发找到最靠近用户的网络节点(边缘节点),更快更加高效的将资源,图片视频等文件发送给用户,从而高性能的,可扩展的并且低成本的将内容传递给用户。
- 常用的cdn服务器有自己购买,以及开源的服务器,国际上常用的unpkg,vue就是用这个CDN从国外派发到我们国内
16.重排和重绘
-
重绘(repaint):就是在⼀个元素的外观被改变,但没有改变布局(宽⾼)的情况下发⽣, 如改变visibility、outline、背景色等等,重绘只是页面的一部分需要重新绘制,但是元素的尺寸和位置并没有发生变化。
-
重绘几乎不可避免,只要用户进行交互动作,页面势必会重新渲染。
-
重排(reflow):就是DOM的变化影响到了元素的⼏何属性(宽和高), 浏览器会重新计算元素的几何属性,如:改变窗⼝大小、改变文字大小、 内容的改变、浏览器窗口变化, style属性的改变等等。
-
重排一定会引起重绘,重绘不一定引起重排。
17.template 标签
html中的template标签中的内容在页面中不会显示。但是在后台查看页面DOM结构存在template标签。这是因为template标签天生不可见,它设置了display:none;属性。加载后可以使用 JavaScript 来显示它
写法一:
<script type="x-template" id="why">
<div>
<div class="num">{{ count }} </div>
<button class="increment" @click="increment">+1</button>
<button class="decrement" @click="decrement">-1</button>
</div>
</script>
写法二:
<template>
<div>
<div class="num">{{ count }} </div>
<button class="increment" @click="increment">+1</button>
<button class="decrement" @click="decrement">-1</button>
</div>
</template>
18.elementUI深度样式
两种方法
- 类名前:/deep/
- 类名后: ::v-deep
补充
1.字体渐变步骤
- 添加渐变: background-image: linear-gradient(#96daf7, #21a9e4)
- 剪辑:background-clip: text
- 显示:color: transparent
2.CSS pointer-events 属性- pointer-events 属性定义元素是否对指针事件做出反应
- 默认值:auto| none
19.浅谈Canvas和SVG的区别
SVG: SVG可缩放矢量图形(Scalable Vector Graphics)是基于可扩展标记语言XML描述的2D图形的语言,SVG基于XML就意味着SVG DOM中的每个元素都是可用的,可以为某个元素附加Javascript事件处理器。
Canvas: Canvas是画布,通过Javascript来绘制2D图形,是逐像素进行渲染的。其位置发生改变,就会重新进行绘制。
区别:
1、Canvas是使用javaScript程序绘制动态生成的,SVG是使用xml文档描述来绘图。从这点来看:SVG更适合用来做动态交互,而且SVG绘图更容易编辑
2、SVG是基于矢量的,所以它能够很好的处理图形大小的变大。canvas是基于位图的图像,他不能改变大小,只能缩放显示,最适合带有大型渲染区域的应用程序(比如谷歌地图)
3、canvas支持的颜色比SVG多,更适合图像密集型的游戏之类使用,其中的许多对象会被频繁重绘
20.v-for和v-if优先级?
- 在开发实践中很少遇见这两个放一起的情况
- 文档中明确指出永远不要把 v-if 和 v-for 同时用在同一个元素上
- vue2中,v-for的优先级是高于v-if,把它们放在一起,输出的渲染函数中可以看出会先执行循环再判断条件,哪怕我们只渲染列表中一小部分元素,也得在每次重渲染的时候遍历整个列表,这会比较浪费;另外需要注意的是在vue3中则完全相反,v-if的优先级高于v-for,所以v-if执行时,它调用的变量还不存在,就会导致异常
五、第五回合
1.请求方式(get,post,其它)
URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个网络上的资源,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的查 ,改 ,增 ,删 4个操作。
- GET:一般用于获取/查询资源信息
- POST: 向指定资源提交数据进行处理请求(提交表单、上传文件),又可能导致新的资源的建立或原有资源的修改。
- HEAD: 和GET本质是一样的,区别在于HEAD不含有呈现数据,而仅仅是HTTP头信息。有的人可能觉得这个方法没什么用,其实不是这样的。想象一个业务情景:欲判断某个资源是否存在,我们通常使用GET,但这里用HEAD则意义更加明确。
- PUT:这个方法比较少见。HTML表单也不支持这个。本质上来讲, PUT和POST极为相似,都是向服务器发送数据,但它们之间有一个重要区别,PUT通常指定了资源的存放位置,而POST则没有,POST的数据存放位置由服务器自己决定。
- DELETE:删除某一个资源。基本上这个也很少见,不过还是有一些地方比如amazon的S3云服务里面就用的这个方法来删除资源。
- OPTIONS:这个方法很有趣,但极少使用。它用于获取当前URL所支持的方法。若请求成功,则它会在HTTP头中包含一个名为“Allow”的头,值是所支持的方法,如“GET, POST”。
2.CSS单位
- px:px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的。
- %:一般宽泛的讲是相对于父元素,但是并不是十分准确
- em:当使用em单位时,像素值将是em值乘以使用em单位的元素的字体大小。em 单位转为像素值,取决于他们使用的字体大小。 此字体大小受从父元素继承过来的字体大小,除非显式重写与一个具体单位。 一般用于按钮、菜单、标题等有自己字体大小
- rem:当使用rem单位,他们转化为像素大小取决于页根元素的字体大小,即 html 元素的字体大小。 根元素字体大小乘以你 rem 值。rem 单位翻译为像素值是由 html 元素的字体大小决定的。 此字体大小会被浏览器中字体大小的设置影响,除非显式重写一个具体单位。 一般用于媒体查询
- vh:css3新单位,viewpoint height的缩写,视窗高度,1vh等于视窗高度的1%。
- vw:css3新单位,viewpoint width的缩写,视窗宽度,1vw等于视窗宽度的1%。
举个例子:浏览器宽度1200px, 1 vw = 1200px/100 = 12 px。
3.判断一个字符串是否是回文(算法实现)
str.split(‘’).reverse().join(‘’);
先将字符串转换为数组然后翻转再转换为字符串进行比较。
4.v-text和v-html
v-text和v-html起了插值表达式{{}}作用,将msg中的信息显示在视图中。在v-html的运行中,它解析了HTML代码。而v-text并没有解析,它将msg原样输出
v-html 指令的作用:设置元素的innerHTML
v-text指令无论内容是什么,只会解析为文本
解析文本使用v-text,需要解析html结构使用v-html
5.隐式转换、类型转换
在数字计算过程中会将:==“” false 0 null NaN undefined == 转换为Boolean的false
6.迭代器
迭代器不可以使用break、continue.
For:遍历数组
forEach:ES5标准,遍历数组,不可以使用break、continue、return语句。只是执行操作,不会生成数组
Map:遍历数组,传入函数,三个参数(element index arr),执行相应的操作,生成新数组。
For in:ES5标准,遍历数组索引和对象属性,原型链上的所有属性都将被访问到,消耗性能,可以使用hasOwnProperty检测一个属性是否是私有属性,存在于实例还是原型中。可使用break、continue、return语句
For of:ES6标准,遍历数组的值,可使用break、continue、return语句
7.link和@import
- link是在页面加载的的同时一起加载的,@import是页面加载完毕后才加载的
- 可以通过 JS 操作 DOM ,插入link标签来改变样式;由于 DOM 方法是基于文档的,无法使用@import的方式插入样式
- link不仅可以导入样式表,还可以导入其他如如favicon,但@import只能导入样式表
8.CSS样式隐藏元素
定位到屏幕外边、透明度变换、display、opacity、
- opacity 属性的效果是给背景颜色添加透明度,取值范围是0~1, 但也会让处于背景颜色中的字体一同透明, 单用效果很好
- visibility给元素设置visibility: hidden也可以隐藏这个元素,但是隐藏元素仍需占用与未隐藏时一样的空间,也就是说虽然元素不可见了,但是仍然会影响页面布局。
- display如果给一个元素设置了display: none,那么该元素以及它的所有后代元素都会隐藏,它是前端开发人员使用频率最高的一种隐藏方式。隐藏后的元素无法点击,无法使用屏幕阅读器等辅助设备访问,占据的空间消失
补充:
visibility和display的区别
- visibility具有继承性,给父元素设置visibility:hidden;子元素也会继承这个属性。但是如果重新给子元素设置visibility: visible,则子元素又会显示出来。这个和display: none有着质的区别
- visibility: hidden不会影响计数器的计数,如图所示,visibility: hidden虽然让一个元素不见了,但是其计数器仍在运行。这和display: none完全不一样
- CSS3的transition支持visibility属性,但是并不支持display,由于transition可以延迟执行,因此可以配合visibility使用纯css实现hover延时显示效果。提高用户体验。
9.CSS样式display
- block”可将元素将显示为块级元素
- none 与visibility属性的hidden值不同,其不为被隐藏的对象保留其物理空间,它就会消失在网页中,但元素并没有在文档中删除,只是隐藏在网页结构中,不在网页中显示而已。不占据物理空间,网页中不显示,但是DOM结构还在
- inline”主要是用来将块级元素转换成行内元素
10.如何实现浏览器内多个标签页之间的通信?
localStorage,Cookie等本地存储方式
- localStorage
在一个标签页里面使用 localStorage.setItem(key,value)添加(修改、删除)内容;在另一个标签页里面监听 storage 事件。即可得到 localstorge 存储的值,实现不同标签页之间的通信。 - 调用cookie+setInterval()
将要传递的信息存储在cookie中,每隔一定时间读取cookie信息,即可随时获取要传递的信息。
document.cookie=“name=”+name;
11.cookie设置,获取,删除
- 设置
document.cookie=key + “=” + val +" - 获取
document.cookie.replace(/[ ]/g,“”); //获取cookie,并且将获得的cookie格式化,去掉空格字符 - 删除
封装删除cookie函数
12.声明式编程和命令式编程
声明式编程:框架完成 声明数据 声明方法 挂载到对应的DOM结构
命令式编程:原生自己给浏览器命令
14.高阶函数
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
只需满足以下任意一个条件,即是高阶函数:
- 接受一个或多个函数作为输入
- return 返回另外一个函数
15.闭包
子函数就是闭包,闭包就是能够读取其他函数内部的变量的函数
闭包主要和作用域有关,变量全局变量,局部变量,
- 在函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。函数内 部声明变量的时候,一定要使用var命令,如果不用的话,你实际上声明了一个全局变量。
-那如何在函数外部访问函数内部的局部变量呢?我们就可以在父函数内部定义一个子函数,子函数可以访问父函数的局部变量,然后返回这个函数,这样可以在父函数的外部读取局部变量。
应用:读取函数内部变量,还有保存变量的值或者说结果缓存
缺点:内存泄露,由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包
16.Vue、Angular、React区别
Angular :一个应用设计框架与开发平台,用于创建高效、复杂、精致的单页面应用。
React :一个用于构建用户界面的 JavaScript 库
Vue :一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
大佬总结的详情:链接
17.CSS中的伪类
链接伪类:link visited hover active
结构伪类:first-child last-child nth-child(n) nth-last-child(n)
N: even odd n 2n等
目标伪类::target { }
18.CSS动画
动画常见属性 :
animation帧动画
animation-name :动画名称
animation-duration:持续时间
animation-timing-function :动画速度曲线
animation-delay:动画开始时间
animation-iteration-count:规定动画播放次数默认是1
animation-direction:规定动画在下一个周期逆向播放,默认是nomal
19.前端设计模式
- 单例模式 一般在全局模式确保实例存在
- 工厂模式 对原型链进行操作,不同场景创建不同实例
- 策略模式 将算法的使用与算法的实现分离开来,避免多重判断调用哪些算法
- 代理模式
- 观察者模式 发布订阅模式
- 模块模式 指定类想暴露的属性和方法(私有变量#声明,或者在构造函数中声明)
- 构造函数模式
- 混合模式
20.XSS攻击
攻击者在html中嵌入js脚本。
解决方法:
1、使用escapeHTML()对特殊字符进行转换
2、验证href内容,禁止以JavaScript开头
3、在http头部set-cookie,防止浏览器执行恶意代码
4、设置Httponly来禁止js脚本访问cookie
5、设置Secure,仅在https请求发送cookie
六、软技能问题
1.为什么学习前端
- node.js,微信小程序等框架,让前端经过一定的学习后也可以进行移动端开发。
- 前端写出来之后直接就能看到,更有成就感。
2.你觉得前端人员应该掌握哪些知识?
- 前端基础:HTML,浏览器,CSS,JS
- 前端核心:ajax, 服务端语言
- 前端的流行框架(vue)和模块化开发
- 计算机基础:了解计算机网络,数据库等
4.如何看待加班?
在没有更多的经验情况下,要多去抓紧时间沉淀。
反问:对加班如何看待效率会比较低的看法
5.如何学习一门新技术(平时如何学习)
- 先通过系统的视频学习
- 在跟着视频学习过程后做好总结
- 寻找对应的项目进行练手实践
6.周围朋友同学如何评价你
具有合作精神,良好的交流沟通能力,性格虽然开朗活泼,但是做事沉稳耐心
7.你有什么想问我的?
- 定期会有技术分享交流会吗?
- 如果我有幸入职,对于我这个岗位,您对我3-5年的职业规划的建议是什么?
- 请问贵公司对于员工有什么职业发展方面的培训吗?
- 感谢您这次对我的面试,请问我的经历和能力,有哪些是不符合公司预期的吗?或者您觉得我有哪些方面需要加强呢?
- 团队成员有多少人呢,前端人员大概有多少?
8.你遇到的最大挑战?完成之后你的成就感?
在学习前端的过程中,遇到比较大的挑战是学习JS时,JS是基于面向对象,有对象这个概念,又不完全是面向对象编程,没有class这个概念,关于继承与原型链一开始很难理解,最后通过查资料,看视频和前端人员博客等,搞清楚整个的一个发展规范,最后深入理解JS的这种编程思想。
9.前端与后端的区别?
- 前端:客户端开发,在应用程序和网站屏幕上看到的所有内容都属于前端
- 后端:服务端开发,在后端服务器和浏览器或应用程序之间存储网站、应用数据和中间媒介的服务器都属于后端。
- 前端开发人员团队设计网站的外观,并通过测试不断修改 后端开发人员团队开发软件,并构建支持前端的数据库架构
这五个大的回合包含了常见的前端八股文,如果全都掌握了,面对初级的面试基本没有问题!但是还是得去对应模块知识点多去积累!!
大家一起进步,慢慢积累鸭!