js
1. 事件冒泡和事件委托
-
事件冒泡:当一个子元素的事件被触发的时候(例如onclick事件),该事件会从事件(被电击的元素)开始逐个向上传播,触发父级元素的点击事件。 -
事件委托:将子元素的事件通过冒泡的形式交由父元素来执行。比如我们平时在给ul中的li添加事件的时候,我们都是通过for循环一个个添加,如果li很多个的话,其实就有点占内存了,这个时候可以用 事件代理来优化性能。
var ul = document.getElementById('parentUl');
ul.οnclick=function (event) {
var e = event||window.event,
source = e.target || e.srcElement;//target表示在事件冒泡中触发事件的源元素,在IE中是srcElement
if(source.nodeName.toLowerCase() == "li"){ //判断只有li触发的才会输出内容
alert(source.innerHTML);
}
stopPropagation(e); //阻止继续冒泡
};
function addElement() {
var li = document.createElement('li');
li.innerHTML="我是新孩子";
ul.appendChild(li);
}
2. click()和onclick()
onclick()是绑定事件:作用执行函数代码;click()本身是方法:作用是触发onclick()事件
<script type="text/javascript">
$(function(){
$("#b2").click(function(){
$("#b1").click();
});
});
function change(){
alert("调用了方法change");
}
</script>
<button id = "b1" onclick="change()">按钮1</button>
<button id = "b2">按钮2</button>
3. require 与 import 的区别
- 两者的加载方式不同,
require 是在运行时加载,而 import 是在编译时加载
require(’. /a’)(); // a 模块是一个函数,立即执行 a 模块函数
var data = require(’. /a’). data; // a 模块导出的是一个对象
var a = require(’. /a’)[0]; // a 模块导出的是一个数组==>哪都行
import $ from ‘jquery’;
import * as _ from ‘_’;
import {a, b, c} from ‘. /a’;
import {default as alias, a as a_a, b, c} from ‘. /a’; ==>用在开头
-
规范不同,
require 是 CommonJS/AMD 规范,import 是 ESMAScript6+规范 -
特点不同
require 特点:社区方案,提供了服务器/浏览器的模块加载方案。非语言层面的标准。只能在运行时确定模块的依赖关系及输入/输出的变量,无法进行静态优化。import 特点:语言规格层面支持模块功能。支持编译时静态分析,便于 JS 引入宏和类型检验。动态绑定。
4. javascript 对象的几种创建方式
-
Object 构造函数创建
-
使用对象字面量表示法
-
使用工厂模式创建对象
-
使用构造函数创建对象
-
原型创建对象模式
-
组合使用构造函数模式和原型模式
5. 什么是原型链?
通过一个对象的__proto__可以找到它的原型对象,原型对象也是一个对象,就可以通过原型对象的__proto__,最后找到了我们的 Object.prototype, 从实例的原型对象开始一直到 Object. prototype 就是我们的原型链
6. javascript 的 typeof 返回哪些数据类型
string、boolean、number、Object(对象,数组,null)、Function、undefined、symbol(ES6)
7. JavaScript 的数据类型
String、Number、Boolean、Null、Undefined 和 Object, Symbol(ES6新增)
其中,Object 是引用数据类型,其他的都是基本数据类型(Primitive Type)。
8. 如何判断 JS 变量的一个类型(至少三种方式)
typeof、instanceof、 constructor、 prototype
9. 列举 3 种强制类型转换和 2 种隐式类型转换
强制: parseInt(), parseFloat(), Number(), Boolean(), String()隐式: +, -
10. 对闭包的理解?优缺点?
概念:闭包就是能够读取其他函数内部变量的函数。
- 三大特性:
- 函数嵌套函数。
- 函数内部可以引用外部的参数和变量。
- 参数和变量不会被垃圾回收机制回收。
- 优点:
- 希望一个变量长期存储在内存中。
- 避免全局变量的污染。
- 私有成员的存在。
- 缺点:
- 常驻内存,增加内存使用量。
- 使用不当会很容易造成内存泄露。
11. for in 和 for of的区别
for in
遍历key值,一般用于遍历对象的可枚举属性。以及对象从构造函数原型中继承的属性。对于每个不同的属性,语句都会被执行。
不建议使用 for in 遍历数组,因为输出的顺序是不固定的。
如果迭代的对象的变量值是 null 或者 undefined, for in 不执行循环体,建议在使用 for in 循环之前,先检查该对象的值是不是 null 或者 undefined。
for of
for…of 语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。
var arr = ['a','b','c']
for(value of arr){ console.log(value)} // a,b,c
var obj = {a:1,b:2,c:3}
for(key in obj){console.log(key)} // a,b,c
12. 如何判断一个对象是否为数组
- instanceof 操作符。
- 使用 ECMAScript 5 新增的 Array.isArray()方法。
- 使用使用 Object.prototype 上的原生 toString()方法判断。
Object.prototype.toString.call()优点:这种方法对于所有基本的数据类型都能进行判断,即使是 null 和 undefined 。缺点:不能精准判断自定义对象,对于自定义对象只会返回[object Object]
instanceOf优点:instanceof 可以弥补 Object.prototype.toString.call()不能判断自定义实例化对象的缺点。缺点: instanceof 只能用来判断对象类型,原始类型不可以。并且所有对象类型 instanceof Object 都是 true,且不同于其他两种方法的是它不能检测出 iframes。
Array. isArray()优点:当检测 Array 实例时,Array.isArray 优于 instanceof ,因为 Array. isArray 可以检测出 iframes缺点:只能判别数组
13. 面向对象和面向过程的异同
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
面向对象的三个基本特征是:封装、继承、多态。
封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。继承是指这样一种能力:在一个类的基础上创建一个新的类,它拥有之前类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。多态(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
14. JS 块级作用域、变量提升
JS 中作用域有:全局作用域、函数作用域, 级作用域(ES6新增)。
块作用域由 { } 包括,if 语句和 for 语句里面的{ }也属于块作用域。
变量提升
- 如果变量声明在函数里面,则将变量声明提升到函数的开头
- 如果变量声明是一个全局变量,则将变量声明提升到全局作用域的开头 解释 JavaScript 中的作用域与变量声明提升?
- 作用域只会对某个范围产生作用,而不会对外产生影响的封闭空间。在这样的一些空间里,外 部不能访问内部变量,但内部可以访问外部变量。
- 所有申明都会被提升到作用域的最顶上
- 同一个变量申明只进行一次,并且因此其他申明都会被忽略
- 函数声明的优先级优于变量申明,且函数声明会连带定义一起被提升
15. var、let、const 的区别
- var 定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。
- let 定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。
- const 用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。
- 同一个变量只能使用一种方式声明,不然会报错
16. null/undefined 的区别
-
null: Null 类型,代表“空值",代表一个空对象指针,使用 typeof 运算得到 “object",所以你可以认为它是一个特殊的对象值。 -
undefined: Undefined 类型,当一个声明了一个变量未初始化时,得到的就是 undefined。
17. 哪些操作会造成内存泄露
- 意外的全局变量引起的内存泄露
- 闭包引起的内存泄露
- 没有清理的 DOM 元素引用
- 被遗忘的定时器或者回调
- 子元素存在引起的内存泄露
- IE7/8 引用计数使用循环引用产生的问题
18. jsonp 优缺点
优点
- 它不像 XMLHttpRequest 对象实现的 Ajax 请求那样受到同源策略的限制,
JSONP 可以跨越同源策略; - 它的
兼容性更好,在更加古老的浏览器中都可以运行,不需要 XMLHttpRequest 或 ActiveX 的支持 - 在请求完毕后可以通过调用 callback 的方式回传结果。
将回调方法的权限给了调用方。这个就相当于将 controller 层和 view 层终于分 开了。我提供的 jsonp 服务只提供纯服务的数据,至于提供服务以 后的页面渲染和后续 view 操作都由调用者来自己定义就好了。如果有两个页面需要渲染同一份数据,你们只需要有不同的渲染逻辑就可以了,逻辑都可以使用同 一个 jsonp 服务。
缺点
- 它
只支持 GET请求而不支持 POST 等其它类型的 HTTP 请求 - 它
只支持跨域 HTTP 请求这种情况,不能解决不同域的两个页面之间如何进行 JavaScript 调用的问题。 3 jsonp 在调用失败的时候不会返回各种 HTTP 状态码。 4 缺点是安全性。万一假如提供 jsonp 的服务存在页面注入漏洞,即它返回的 javascript 的内容被人控制的。那么结果是什么?所有调用这个 jsonp 的网站都会存在漏洞。于是无法把危险控制在一个域名下…所以在使用 jsonp 的时候必须要保证使用的 jsonp 服务必须是安全可信的
javascript 的同源策略
同源策略是客户端脚本(尤其是Javascript)的重要的安全度量标准。它最早出自Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。
这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。
指一段脚本只能读取来自同一来源的窗口和文档的属性。
19. this指向问题
解析器在调用函数时,每次都会向函数内部传递进一个隐含的参数,这个参数就是this
this指向的是一个对象,对象称为函数执行的上下文对象
this的情况:
- 当以函数的形式调用时,this就是window,
- 当以方法的形式调用时,谁调用方法this就是谁,
- 当以构造函数的形式调用时,this就是新创建的那个对象
- 使用call和apply调用时,this是指定的那个对象
20. call() 和 apply() 的含义和区别?
都是调用一个对象的一个方法,用另一个对象替换当前对象。 call 和 apply 都是在调用时生效,改变调用者的 this 指向;bind 也是改变 this 指向,不过不是在调用时生效,而是返回一个新函数。
B.call(A, args1, args2); 即 A 对象调用 B 对象的方法。
B. apply(A, arguments); 即 A 对象应用 B 对象的方法。
call传参时参数是一个一个传apply参数为一个数组
let name = 'Jack'
const obj = {name: 'Tom'}
function sayHi() {console.log('Hi! ' + this.name)}
sayHi() // Hi! Jack
sayHi.call(obj) // Hi! Tom
const newFunc = sayHi.bind(obj)
newFunc() // Hi! Tom
20. new 操作符具体干了什么呢?
- 创建一个空对象
- 链接到原型
- 绑定this值(让Func中的this指向obj,并执行Func的函数体。)
- 判断 Func 的返回值类型:
function Func(){
}
let func= new Func();
//经历下面4步
let obj = new Object();
obj.__proto__ = Func.prototype;// 把 obj 的**proto** 指向构造函数Func的原型对象 prototype,此时便建立了 obj 对象的原型链:obj->Func.prototype->Object.prototype->null
let result = Func.call(obj) //绑定this值
//判断Func的返回值类型:如果无返回值 或者 返回一个非对象值,则将 obj 作为新对象返回;否则会将 result 作为新对象返回。
if(typeof(result)==='object'){
func = result
}else{
func=obj
}
21. 事件绑定与普通事件有什么区别
- 用普通事件
div1.οnclick=function(){};添加相同事件,下面会覆盖上面的,而事件绑定addEventListener不会 普通事件是针对非 dom 元素,不支持 DOM 事件流 事件捕获阶段目标元素阶段=>事件冒泡阶段;事件绑定是针对 dom 元素的事件,支持 DOM 事件流的
22. 事件冒泡与事件捕获
事件冒泡:由最具体的元素(目标元素)向外传播到最不具体的元素事件捕获:由最不确定的元素到目标元素
23. 对作用域链的理解
作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到 window 对象即被终止,作用域链向下访问变量是不被允许的。
24. 定时器 setInterval 有一个有名函数 fn1,setInterval(fn1, 500)与 setInterval(fn1(), 500)有什么区别?
setInterval 有一个有名函数 fn1
setInterval(fn1, 500)重复执行每 500 毫秒执行一次setInterval(fn1(), 500)只执行一次
24. 你用过 require. js 吗?它有什么特性?
- 实现 js 文件的异步加载,避免网页失去响应;
- 管理模块之间的依赖性,便于代码的编写和维护。
requireJS 的核心原理是什么?(如何动态加载的?如何避免多次加载的?如何缓存的?)
核心是 js 的加载模块,通过正则匹配模块以及模块的依赖关系,保证文件加载的先后顺序,根据文件的路径对加载过的文件做了缓存
25.对象浅拷贝和深拷贝有什么区别
在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有重新创建一个对象,则认为是浅拷贝。反之,在对引用数据类型进行拷贝的时候,创建了一个对象,并且复制期内的成员变量,则认为是深拷贝。
- 如果拷贝的对象里的
元素只有值,没有引用,那浅拷贝和深拷贝没有差别,都会将原有对象复制一份,产生一个新对象,对新对象里的值进行修改不会影响原有对象,新对象和原对象完全分离开。 - 如果拷贝的对象里的元素
包含引用(像一个列表里储存着另一个列表,存的就是另一个列表的引用),那浅拷贝和深拷贝是不同的,浅拷贝虽然将原有对象复制一份,但是依然保存的是引用,所以对新对象里的引用里的值进行修改,依然会改变原对象里的列表的值,新对象和原对象完全分离开并没有完全分离开。而深拷贝则不同,它会将原对象里的引用也新创建一个,即新建一个列表,然后放的是新列表的引用,这样就可以将新对象和原对象完全分离开。
//深拷贝实现方式
//第一种
function deepCopy(obj) {
//生成新对象
let objCopy = Array.isArray(obj)?[]:{};
if(obj && typeof obj === "object"){
for(let key in obj){
if(obj.hasOwnProperty(key)){
//判断ojb子元素是否为对象,如果是,递归复制
if(obj[key] && typeof obj[key] === "object"){
objCopy[key] = deepCopy(obj[key]);
}else{
//如果不是直接复制
objCopy[key] = obj[key];
}
}
}
}
return objCopy;
}
let obj1 = {
a:{
b:1
}
}
console.log(obj1);
let obj2 = deepCopy(obj1);
obj1.c = {
d:2
};
//obj2不受obj1的影响
console.log(obj2);
//第二种借助JSON.parse() 和 JSON.stringify()
function deepCopy2(obj) {
let _obj = JSON.stringify(obj);
let objCopy = JSON.parse(_obj);
return objCopy;
}
let obj3 = {
a:{
b:10
}
}
console.log(obj3);
let obj4 = deepCopy2(obj3);
obj3.c = {
d:20
};
//obj4不受obj3的影响
console.log(obj4);
26. 如何编写高性能的 Javascript?
- 使用 DocumentFragment 优化多次 append
- 通过模板元素 clone ,替代 createElement
- 使用一次 innerHTML 赋值代替构建 dom 元素
- 使用 firstChild 和 nextSibling 代替 childNodes 遍历 dom 元素
- 使用 Array 做为 StringBuffer ,代替字符串拼接的操作
- 将循环控制量保存到局部变量
- 顺序无关的遍历时,用 while 替代 for
- 将条件分支,按可能性顺序从高到低排列
- 在同一条件子的多( >2 )条件分支时,使用 switch 优于 if
- 使用三目运算符替代条件分支
- 需要不断执行的时候,优先考虑使用 setInterval
26.documen. write 和 innerHTML 的区别?
- document.write 是
重写整个 document, 写入内容是字符串的 html - innerHTML 是 HTMLElement 的属性,是一个元素的内部 html 内容
27. 事件绑定的方式
// 1. 嵌入 dom
<button onclick="func()">按钮</button>
// 2.直接绑定
btn.onclick = function() {};
// 3. 事件监听
btn.addEventListener("click", function() {});
28. target 和 currentTarget 区别
- event.target:返回
触发事件的元素 - event.currentTarget:返回
绑定事件的元素
29. prototype 和__proto__的关系是什么
所有的对象都拥有__proto__属性,它指向对象构造函数的 prototype 属性
prototypes是函数特有的,所有的函数都同时拥有__proto__和 protytpe 属性
函数的__proto__指向自己的函数实现 函数的 protytpe 是一个对象 所以函数的 prototype 也有__proto__属性 指向 Object.prototype,Object.prototype.__proto__指向 null
30. 遍历的区别
数组遍历forEach、 map、filter的区别
filter:array.map(function(currentValue, index, arr) {}, this),筛选过滤,返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值array.map(function(currentValue, index, arr) {}, this)返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。map() 不会对空数组进行检测。map() 不会改变原始数组。Array.forEach(function(currentValue, index, arr) {}, this), 返回值: undefined
this可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值。默认匿名函数中的this都是指向window
区别:
- filter函数,顾名思义,它是一个用来过滤的函数。他可以通过指定的过滤条件,删选出数组中符合条件的元素,并返回。
- map函数,这个函数与filter函数不同之处在于,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。而map则会返回传入函数return的值,返回值会组成一个新数组,新数组的索引结构和原数组一致,原数组不变。
- forEach函数,可以实现对数组的遍历,和map函数与filter函数不同的是它没有返回值,是undefined,不可以链式调用
- map和filter方法不会改变原数组。
- 这三个方法都不会对空数组进行检测或执行回调函数。
- 没有办法终止或者跳出forEach()循环,除非抛出异常,所以想执行一个数组是否满足什么条件,返回布尔值,可以用一般的for循环实现,或者用Array.every()或者Array.some()
var arr = [1,2,3,4,5]
arr.map(item=>item>3) // [false, false, false, true, true]
arr.filter(item=>item>3) // [4, 5]
arr.map(item=>item*2) // [2, 4, 6, 8, 10]
arr.filter(item=>item*2) // [1,2,3,4,5]
console.log(arr) // [1,2,3,4,5]
var arr = [0, 2, 4, 6, 8];
var sum = 0;
var str = arr.forEach(function(item, index, arr) {
sum += item;
console.log("sum的值为:", sum); //0 2 6 12 20
console.log(this); //window
}, this)
console.log(sum); //20
console.log(str); //undefined
for和forEach的区别
forEach又叫做增强for循环,相当于for循环的简化版,因此在一些较复杂的循环中不适用。在循环次数未知或者计算起来较复杂的情况下效率比for循环高- forEach与for循环的明显差别在于
forEach循环时循环对象(数组、集合)被锁定,不能对循环对象中的内容进行增删改操作。
// for循环:可以修改循环语句
var array = ["a","b","c","d"];
for (var i = 0; i < array.length; i ++) {
array[i] = "A";
};
console.log(array); // 结果:"A" "A" "A" "A"
// foreach循环:不能修改循环语句
var array2 = ["a","b","c","d"];
array2.forEach(function(item) {
item = "A";
});
console.log(array2); // 结果:["a","b","c","d"]
31. JavaScript 中 undefined 和 not defined 的区别
undefined是没有初始化,not defined是没有声明
32. 什么是跨域?跨域请求资源的方法有哪些?
跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域。
存在跨域的情况:
- 网络协议不同,如http协议访问https协议。
- 端口不同,如80端口访问8080端口。
- 域名不同,如qianduanblog.com访问baidu.com。
子域名不同,如abc.qianduanblog.com访问def.qianduanblog.com。域名和域名对应ip,如www.a.com访问20.205.28.90.
跨域请求资源的方法:
porxy代理、CORS跨域资源共享 (Cross-origin resource sharing)、jsonp
- porxy代理 定义:proxy代理用于将请求发送给后台服务器,通过服务器来发送请求,然后将请求的结果传递给前端。
实现方法:通过nginx代理;
注意点:如果你代理的是https协议的请求,那么你的proxy首先需要信任该证书或者忽略证书检查,否则你的请求无法成功。
- CORS跨域资源共享 (Cross-origin resource sharing) 定义:是现代浏览器支持跨域资源请求的一种最常用的方式。
使用方法:一般需要后端人员在处理请求数据的时候,添加允许跨域的相关操作:代码如下
var express = require('express');
var app = express();
var allowCrossDomain = function (req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:3001');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
app.use(allowCrossDomain);
- jsonp
定义和用法:
通过动态插入一个script标签。浏览器对script的资源引用没有同源限制,同时资源加载到页面后会立即执行。
特点:通过动态创建script来读取他域的动态资源,获取的数据一般为json格式。
<script>
function testjsonp(data) {
console.log(data.name); // 获取返回的结果
}
</script>
<script>
var scripts = document.createElement('script');
scripts.type = "text/javascript";
scripts.src = "http://localhost:8888/jsonp?callback=testjsonp";
document.head.appendChild(scripts);
</script>
缺点 :这种方式只支持get请求,无法发送post请求;
如何解决跨域问题?
- jsonp ,允许 script 加载第三方资源
- 反向代理(nginx 服务内部配置 Access-Control-Allow-Origin *)
- cors 前后端协作设置请求头部,Access-Control-Allow-Origin 等头部信息
- iframe 嵌套通讯,postmessage
32、Cookie、session和localStorage、以及sessionStorage之间的区别
| Cookie | SessionStorage | LocalStorage | indexDB | |
|---|---|---|---|---|
| 存储大小 | 4k | 5M或更大 | 5M或更大 | 无限 |
| 存储时间 | 可指定时间,没指定关闭窗口就失效 | 浏览器窗口关闭就失效 | 永久有效 | 永久有效 |
| 作用域 | 同浏览器,所有同源标签页 | 当前标签页 | 同浏览器,所有同源标签页 | |
| 存在于 | 请求中来回传递 | 客户端本地 | 客户端本地 | 客户端本地 |
| 同源策略 | 同浏览器,只能被同源同路径页面访问共享 | 自己用 | 同浏览器,只能被同源页面访问共享 |
cookie和session的区别:
cookie数据存放在客户的浏览器上,session数据放在服务器上cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用sessionsession会在一定时间内保存在服务器上,当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie- 建议将登录信息等
重要信息存放为session,其他信息如果需要保留,可以放在cookie中 - session保存在服务器,客户端不知道其中的信心;cookie保存在客户端,服务器能够知道其中的信息
session中保存的是对象,cookie中保存的是字符串session不能区分路径,同一个用户在访问一个网站期间,所有的session在任何一个地方都可以访问到,而cookie中如果设置了路径参数,那么同一个网站中不同路径下的cookie互相是访问不到的
sessionStorage、localStorage和cookie的区别
共同点:都是保存在浏览器端、且同源的
区别:
cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递,而sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下存储大小限制也不同,cookie数据不能超过4K,同时因为每次http请求都会携带cookie、所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localstorage在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的- web Storage支持事件通知机制,可以将数据更新的通知发送给监听者
- web Storage的api接口使用更方便
前端缓存
网络方面的缓存分为三块:DNS缓存、HTTP缓存、CDN缓存,也有人把这里的 HTTP 缓存称为浏览器缓存,反正懂意思就行
还有本地的就是:浏览器的本地存储和离线存储,更快提高首屏加载速度,让页面飞起
33. typeof 与 instanceof 区别
- typeof返回结果是该类型的字符串形式表示【6】(number、string、undefined、boolean、function、object)
- instanceof是用来
判断 A 是否为 B 的实例,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true,否则返回 false。 在这里需要特别注意的是:instanceof 检测的是原型。
34. 微任务和宏任务
/*
* 宏任务
* 分类: setTimeout setInterval requrestAnimationFrame
* 1. 宏任务所处的队列就是宏任务队列
* 2. 第一个宏任务队列中只有一个任务: 执行主线程的js代码
* 3. 宏任务队列可以有多个
* 4. 当宏任务队列的中的任务全部执行完以后会查看是否有微任务队列如果有先执行微任务队列中的所有任务,如果没有就查看是否有宏任务队列
*
* 微任务
* 分类: new Promise().then(回调) process.nextTick
* 1. 微任务所处的队列就是微任务队列
* 2. 只有一个微任务队列
* 3. 在上一个宏任务队列执行完毕后如果有微任务队列就会执行微任务队列中的所有任务
* */
console.log('----------------- start -----------------'); // 执行顺序1
setTimeout(() => {
console.log('setTimeout'); // 执行顺序5
}, 0)
new Promise((resolve, reject) => {
for (var i = 0; i < 5; i++) {
console.log(i); // 执行顺序2 (打印0,1,2,3,4)
}
resolve(); // 修改promise实例对象的状态为成功的状态
}).then(() => {
console.log('promise实例成功回调执行'); // 执行顺序4
})
console.log('----------------- end -----------------'); // 执行顺序3
35. 常见HTTP状态码
| 状态码 | 类别 | 描述 |
|---|---|---|
| 1xx | Informational(信息状态码) | 接受请求正在处理 |
| 2xx | Success(成功状态码) | 请求正常处理完毕 |
| 3xx | Redirection(重定向状态码) | 需要附加操作已完成请求 |
| 4xx | Client Error(客户端错误状态码) | 服务器无法处理请求 |
| 5xx | Server Error(服务器错误状态码) | 服务器处理请求出错 |
- 14种常用的HTTP状态码列表
| 状态码 | 状态码英文名称 | 中文描述 |
|---|---|---|
| 200 | OK | 请求成功。一般用于GET与POST请求 |
| 204 | No Content | 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档 |
| 206 | Partial Content | 是对资源某一部分的请求,服务器成功处理了部分GET请求,响应报文中包含由Content-Range指定范围的实体内容。 |
| 301 | Moved Permanently | 永久性重定向。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 |
| 302 | Found | 临时性重定向。与301类似。但资源只是临时被移动。客户端应继续使用原有URI |
| 303 | See Other | 查看其它地址。与302类似。使用GET请求查看 |
| 304 | Not Modified | 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源 |
| 307 | Temporary Redirect | 临时重定向。与302类似。使用GET请求重定向,会按照浏览器标准,不会从POST变成GET。 |
| 400 | Bad Request | 客户端请求报文中存在语法错误,服务器无法理解。浏览器会像200 OK一样对待该状态吗 |
| 401 | Unauthorized | 请求要求用户的身份认证,通过HTTP认证(BASIC认证,DIGEST认证)的认证信息,若之前已进行过一次请求,则表示用户认证失败 |
| 402 | Payment Required | 保留,将来使用 |
| 403 | Forbidden | 服务器理解请求客户端的请求,但是拒绝执行此请求 |
| 404 | Not Found | 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面。也可以在服务器拒绝请求且不想说明理由时使用 |
CSS
1. 让 Chrome 支持小于 12px 的文字
谷歌Chrome最小字体是12px,不管你设置成8px还是10px,在浏览器中只会显示12px,那么如何解决这个坑爹的问题呢? 我们的做法是: 针对谷歌浏览器内核,加webkit前缀,用transform:scale()这个属性进行缩放!
<style>
p span{font-size:10px;
-webkit-transform:scale(0.8);display:block;}
</style>
<p><span>测试10px</span></p>
2. 文本超出部分显示省略号
// 单行
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
// 多行
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3; // 最多显示几行
overflow: hidden;