答案比较精简,便于速记,复盘
基础部分
对象
- JSON.stringify() 、 JSON.parse() -> 对象字符串相互转化
- Object.keys -> 迭代对象
- Object.values -> 以数组的方式返回对象的值
- Object.prototype
- Object.prototype.hasOwnProperty -> 用于检查给定的属性/键是否存在于对象中
- Object.prototype.instanceof -> 判断给定对象是否是特定原型的类型
- Object.freeze -> 可以冻结对象,以便不能修改对象现有属性
- Object.isFrozen -> 给定对象是否被冻结
- Object.seal() -> 封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要可写就可以改变。
- Object.isSealed -> 判断对象是否被密封。
函数
可赋值给变量,可传给函数,也可从函数返回。注意变量提升,匿名函数提升
1.高阶函数
- 函数作为参数传递,
- 函数作为返回值输出
数组
1.创建数组的方法:
- var array = new Array()
- var array = []
- Array.of(1,2) // es6新增方法 // 结果为:[1,2]
2.判断是否为数组
- console.log(arr instanceof Array)
- console.log(arr.construct === Array)
- console.log(Array.isArray(arr))
3.数组常用操作
- pop()尾部删除
- push()尾部插入
- unshift()头部插入
- shift()头部删除
call、apply、bind
改变this指向。call、apply类似,立即调用。bind稍后调用
var mathLib = {
pi: 3.14,
area: function(r) {
return this.pi * r * r;
},
circumference: function(r) {
return 2 * this.pi * r;
}
};
mathLib.area.call({pi: 3.1159}, 2) //12.56636
mathLib.area.apply({pi: 3.1159}, [2]) //12.56636
mathLib.area.bind({pi: 3.1159}, 2)() //12.56636
DOM相关
1.dom0级
- 不支持添加多个事件,后面的会覆盖前面的
- 无法取消
var btn = document.getElementById("button");
btn.onclick = function(){
alert(1);
}
btn.onclick = function(){
alert(2);
} //只弹出2
2.dom2级
- 可以添加多个事件
- 不兼容低版本IE
- 支持事件冒泡,事件捕获
var btn = document.getElementById("button");
btn.addEventListener("click",function(){
alert("1");
})
btn.addEventListener("click",function(){
alert("2");
}) //先弹出1,再弹出2
3.DOM节点操作
- obj.appendChild()
- obj.insertBefore()
- obj.replace()
- obj.remove()
跨域相关
1.什么是跨域
也就是一个网站不能执行其他网站上的网址,或者说一个服务器上的文件,无法拿到另一个服务器上的文件是浏览器的同源策略,对js的一种安全限制。
当域名协议端口,有一个不同的时候就为跨域
2.解决方法
前端处理:
JSONP:
- json with padding json的一种使用模式
- 跨域产生的具体原因:由于浏览器的同源策略,ajax无法进行跨域,但是script标签中的src支持跨域
- 原理:动态创建一个script标签的,通过src调用服务器提供的js脚本,该脚本的内容是一个函数调用,该函数在本地js文件中进行定义,其中的参数就是,本地函数请求的数据,也就是服务器所将返回的数据
- 注意:与ajax的不同,ajax是通过xhr获取非本页面的数据内容,而JSONP获取的是服务器提供js脚本
后端处理:
CORS:
跨域资源共享,w3c标准
它允许浏览器向跨源(协议 + 域名 + 端口)服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制
CORS需要浏览器和服务器同时支持,浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,因此关键在于服务器实现cors接口
两者的优缺点:
- JSONP对浏览器的支持较好,IE10一下不支持CORS
- JSONP只能用于获取资源(即只读,类似于GET请求);CORS支持所有类型的HTTP请求,功能完善。(这点JSONP被玩虐,但大部分情况下GET已经能满足需求了)
- JSONP的错误处理机制并不完善,我们没办法进行错误处理;而CORS可以通过onerror事件监听错误,并且浏览器控制台会看到报错信息,利于排查。
- JSONP只会发一次请求;而对于复杂请求,CORS会发两次请求。
- 相对而言CORS更安全一点
**
typeof返回的类型 & 基础类型 &引用类型
返回的类型:string,number,object,undefined,boolean,function
基础类型:string,number,boolean,undefined,null
- 基本类型的值是不能改变的
- 基本类型不能添加属性和方法
- 基本类型的比较是值的比较
- 基本类型变量存放在栈区(栈内存)
- 也就是说基本类型在赋值操作后,两个变量是相互不受影响的。
null跟undefined的区别:
- null是表示一个空的对象,转为数值为0,undefind表示一个空的原始值,转为数值为NAN
- undefind指本该有一个值,但却并有定义,null表示没有对象,不应该有值
引用类型:Object Function Array
- 引用类型可以添加属性和方法,属性方法内又可以添加基本类型
- 引用类型的值是可变的
- 引用类型的值时同时保存在栈内存和堆内存里的对象,准确地说,引用类型的存储需要内存的栈区和堆区(堆区是指内存里的堆内存)共同完成,栈区内存保存变量标识符和指向堆内存中该对象的指针,
- 引用类型的比较是引用的比较 引用类型时按引用访问的,换句话说就是比较两个对象的堆内存中的地址是否相同,那很明显,person1和person2在堆内存中地址是不同的
- 引用类型的赋值其实是对象保存在栈区地址指针的赋值,因此两个变量指向同一个对象,任何的操作都会相互影响
类型转换
三种强制类型转换:parseInt(),parseFloat(),Number()
两种隐式类型转换:==,!!
==和===的一个区别也是前者可以类型转换,后者不能
js作用域
全局作用域、函数作用域、块作用域
this指向问题
1.普通函数调用,指向windows
window.value=1;
function getValue(){
console.log(this.value);
}
getValue();//输出1,此时的this指向window
2.对象的方法调用,指向对象
var Obj={
value:2,
getValue:function(){
console.log(this.value);//输出2,this指向Obj
}
}
3.构造器方法调用,指向构造函数实例出来的对象
function main(val){
this.value=val;
}
main.prototype.getValue=function(){
console.log(this.value);
}
var fun=new main(3);
fun.getValue();
fun.value;//输出3,this指向main的实例对象fun
4.call,apply,bind可以自定义this指向第一个参数
function showValue(){
console.log(this.value);
}
var obj={
value:4
}
showValue.call(obj)//输出4,this指向了obj对象
function showValue(){
console.log(this.value);
}
var obj={
value:4
}
var showValue2=showValue.bind(obj);
showValue2()//输出4,this指向了obj对象
原型继承
- 类属性使用
this
绑定 - 类方法使用
prototype
对象来绑定 - 为了继承属性, 使用
call
函数来传递this
- 为了继承方法, 使用 Object.create 连接父和子的原型
- 始终将子类构造函数设置为自身,以获得其对象的正确类型
callback和promise
回调函数和回调函数优雅封装
正则
略
map、reduce、filter
map 接受一个作为参数的函数, 此函数接受一个来自数组的参数。我们需要返回一个处理过的元素, 并应用于数组中的所有元素。
reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始r值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组。
https://www.jianshu.com/p/e375ba1cfc47
filter 过滤出想要的数据,对数组的每个元素进行操作并返回另外一个数组(不同于 reduce 返回的值)
错误处理方式
一个好的开发方法总是谨慎地将 JS 代码封装装在 try/catch
块周围。
始终考虑错误处理是你自己, 而不是浏览器。
提升机制
事件冒泡
addEventListener("click", handler, useCapture=false)
默认false冒泡由内而外,反之捕获,由外而内。
如何阻止事件冒泡和默认事件
- cancelBubble(IE),
- return false,
- event.preventDefault,
- event.stopPropagation()
实现多个标签之间的通信
调用localStorage,cookies等本地存储进行存储相关信息
三者的共同点:都保存在浏览器。
三者的区别:
与服务器的交互
- cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。
- 而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。
存储大小限制也不同,
- cookie数据不能超过4k,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识。
- sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
数据有效期不同,
- sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;
- localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;
- cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。
作用域不同,
- sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;
- localStorage 在所有同源窗口中都是共享的;
- cookie也是在所有同源窗口中都是共享的
那些操作会造成内存泄露
- setTimeout第一个参数是字符串而不是函数的时候就会造成内存泄露
- 闭包
- 控制台日志
- 循环(两个对象彼此引用且彼此保留)
垃圾回收方式
- 标记清除:这是js最常用的垃圾回收方法,当一个变量进入执行环境时,例如函数中声明一个变量,将其标记为进入环境,当变量离开环境时,(函数执行结束),标记为离开环境
- 引用计数: 跟踪记录每个值被引用的次数,声明一个变量,并将引用 类型赋值给这个变量,则这个值的引用次数+1,当变量的值变成了另一个,则这个值的引用次数-1,当值的引用次数为0的时候,就回收
闭包
经典闭包
function outer(){
var a = 1;
function inner(){
alert(a);
}
return inner
}
var inn = outer();
inn();
点击li返回li下标
<ul id="test">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var oUL = document.getElementById("test");
var oLi = oUl.getElementByTagName("li");
for(var i=0;i<oLi.length;i++){
oLi[i].index = i;
oLi[i].onclick = function(){
alert(this.index);
}
}
</script>
<!-- 闭包 -->
<script>
var oUL = document.getElementById("test");
var oLi = oUl.getElementByTagName("li");
for(var i=0;i<oLi.length;i++){
oLi[i].index = i;
oLi[i].onclick = (function(a){
return function(){
alert a;
}
})(i)
}
</script>
new操作符到底干了什么
- 创建一个新对象
- 将构造函数的作用域赋值给新对象(所以this指向了这个新对象)
- 执行构造函数的代码(为这个新对象添加属性)
- 返会新对象
js严格模式
“use strict”
消除js一些不合理的用法
消除代码运行的一些不安全之处
增加运行速度
为未来新版本js做铺垫
- 变量必须声明
- 对象不能出现重复属性名
- arguments改变,不会影响函数参数
- eval,arguments变为关键字,不能作为变量名
- 不允许使用with
- 不用call,apply,bind改变this指向,一般函数调用指向null
ajax请求
ajax请求四步
- 创建一个xhr对象 var xhr = new XmlHttpRequest()
- 判断就绪状态为4时执行代码
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
console.log(responseText);
}
}
- 创建请求 xhr.open(‘get’,’url’,true)
- 发送请求 xhr.send(null)
在浏览器中输入URL到整个页面显示在用户面前时这个过程中到底发生了什么
- DNS解析
- TCP连接
- 发送HTTP请求
- 服务器处理请求并返回HTTP报文
- 浏览器解析渲染页面
- 连接结束
数组去重的一种相对好理解的方法
利用indexOf方法的去重
indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
var arr = [1,1,2,3,4,2,6,4,5,7];
var nArr = [];
function removeItem(arr){
for(var i=0;i<arr.length;i++){
if(nArr.indexOf(arr[i])==-1){
nArr.push(arr[i]);
}
}
return nArr;
}
console.log(removeItem(arr));
HTTP相关
1.常用的HTTP方法有哪些
GET:
POST:
PUT:
DELETE:
2.GET与POST方法的区别
- get主要是从服务器获取资源,post主要是像服务器发送数据
- get传输数据通过url请求,利用k=v的形式放在url后面,用?连接,多个用&连接而post是存放在,ajax中的data中的,get传输的过程使用户可见 的,而post是对用户不可见的。
- get传输的数据量小,因为受url的长度限制,但是效率高,post能上传的数据量大
- post较get更安全一些
- get方式传递的中文字符可能会乱码,post支持标准字符集,可以正确传递中文字符
3.http请求报文与响应报文格式
请求报文包含三部分:
- 请求行:包含请求方法、URI、http版本信息
- 请求首部字段
- 请求内容实体
响应报文包含三部分: - 状态行:包含HTTP版本、状态码、状态码的原因短语
- 响应首部字段
- 响应内容实体
4.http状态码
- 100-199:成功接收请求,但需要进行下一步请求
- 200-299:成功接收请求,并完成整个处理过程
- 300-399:为完成全部请求,客户需近一步细化需求
- 400-499:客户端请求有错误,包括语法错误或不能正常执行
- 500-599:服务器端出现错误
5.http缺点与https
- 通信使用明文不加密,内容可能被窃听
- 不验证通信方身份,可能遭到伪装
- 无法验证报文完整性,可能被篡改
https就是加上加密处理(一般是SSL安全通信线路)+认证+完整性保护
常用: - 200 正常,表示一切正常,返会的是正常请求结果
- 302/307 临时重定向,表示请求的文档,已被临时移动到别处
- 304 未修改,调用缓存的数据
- 403 服务器拒绝客户请求
- 404 服务器不存在客户想要找的资源
- 500 服务器内部错误
ES6相关
let const
- let相当于给js新增了块级作用域,声明的变量只在let命令所在的代码块内有效
const也是声明变量,它声明的变量,不能改变,可以用来声明第三方库变量的应用
class extends super
class定义一个类,其中有一个construct方法,construct方法中的this代表实例对象,construct以外还有其他的方法,construct内定义的方法属性是实例对象自己的,construct外的方法属性是所有实例对象共享的
- class之间可以通过extends实现继承
- super指代父类的实例,子类construct中必须先调用super()方法,因为子类没有自己的this对象,是继承父类的this对象
arrow function(箭头函数)
除了书写简洁了很多,最大的优点是this指向,使用箭头函数,函数内部的this就是定义时所在的对象。箭头函数根本没有自己的this,this是继承外面的,它内部的this就是外层代码块的this
template string(模板字符串)
ajax调用数据库,需要向文档中插入大段html的时候,传统的字符串拼接太麻烦,引入模板工具库会稍微好点,不过还是没有es6的template string简单,可以直接用反单引号包括代码块``,用${}来引用变量,所有的空格缩进都会保留到输出中
destructuring(解构赋值)
es6按照一定模式,从数组和对象中提取值,对变量进行赋值,这就成为解构,也就是说,运用es5的方法,数组和对象中的变量需要,一个个进行赋值,而es6可以一步到位
default,rest(默认值,扩展语法)
当函数忘记传参的时候,给它一个默认值,传统方法是在函数中运用||,es6可以直接在参数中写上
function animal(type){
type = type || 'cat'
console.log(type)
}
animal()
function animal(type = 'cat'){
console.log(type)
}
animal()
function animals(...types){
console.log(types)
}
animals('cat', 'dog', 'fish') //["cat", "dog", "fish"]
gulp
gulp是一种自动化构建工具,前端工程化开发的一种工具,增强开发流程
使用方便,npm安装,新建gulpfile.js,导入gulp模块,let gulp = require(‘gulp’)
通过default任务去定义工作流
最后在终端执行gulp来进行自动化操作
api很简单只有四种
- gulp.task 创建任务 :参数任务名称,前置任务数组,回调函数
- gulp.src 寻找文件:通过路径找到一个或多个文件
- gulp.dest 输出到指定目录:如果没有就新建一个
- gulp.watch 监听文件变化,执行任务
- pipe具体不清楚,总之,除了gulp.src之外,其他执行条件都要放在.pipe()中
Bootstrap
Bootstrap和Foundation的比较
1.UI元素的不同
- Bootstrap给出了能想到的一切元素,也就是试图提供所有定义好的UI,比如一个导航,给予一个默认导航的样式
- Foundation只给定了限定的几种元素,可以自己自定义,更适合创造
2.尺寸单位不一样,
- Bootstrap是px
- Foundation是rem
3.网格布局有所不同
- Foundation 的网格可以自动适配当前浏览器的宽度,Foundation 则会灵活适配当前的浏览器宽度, 这是一种新的技术手段, 自动适配的同时, 可以表现的与 Transformer 一样的效果.
- Boostrap 则是预定义了几种网格尺寸来适配主流的设备和屏幕.Bootstrap 会在你改变浏览器宽度的时候突然改变它的网格.
4.移动设备
- Foundation移动设备优先
- Bootstrap也支持移动设备
4.社区
- Bootstrap有一个完备的社区,有什么问题几乎都可以迅速解决
- Foundation则没有,需要自力更生