前端扫盲1

1、状态码301和302

301是永久重定向,302是临时重定向。
302重定向只是暂时的重定向,搜索引擎会抓取新的内容而保留旧的地址,因为服务器返回302,所以,搜索搜索引擎认为新的网址是暂时的。
而301重定向是永久的重定向,搜索引擎在抓取新的内容的同时也将旧的网址替换为了重定向之后的网址。

2、post 请求和 put 请求的区别

使用PUT时,必须明确知道要操作的对象,如果对象不存在,创建对象;如果对象存在,则全部替换目标对象。同样POST既可以创建对象,也可以修改对象。
但用POST创建对象时,之前并不知道要操作的对象,由HTTP服务器为新创建的对象生成一个唯一的URI;使用POST修改已存在的对象时,一般只是修改目标对象的部分内容。

htttp 的请求有 options(返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性)、post、get、put、head、delete、trace(回显服务器收到的请求,主要用于测试或诊断)、connect(HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。)

3、http1 http2 http3 的区别

参考链接

4、event loop 事件

  • js的异步执行逻辑依赖于event loop 机制,但是这套机制定义在HTML标准中,是宿主环境给脚本提供了这一机制才让脚本有了异步执行的能力,根据 js 宿主环境的不同,可以分为浏览器的事件循环和 node 的事件循环

  • 异步任务:异步任务就是不立即执行,在未来的某一刻执行,不进入主线程而是暂时挂起,等有结果时则会把它对应的回调函数添加到任务队列中

  • 任务队列:时间循环有一个或多个任务队列,任务队列是一组任务,而不是一个队列,因为事件循环处理模型的第一步是从任务队列中选择一个可运行的任务,而不是直接拿第一个任务

  • 宏任务: script(整体代码),setTimeout, setInterval, setImmediate,I/O, UI rendering

  • 微任务: promise().then, Object.observe, MutationObserver

<script>
  console.log(1)
  setTimeout(() => console.log(2), 200)
  setTimeout(() => {
    console.log(3)
    setTimeout(() => console.log(4), 50)
  }, 100)
  new Promise(resolve => {
    console.log(5)
    resolve()
    }).then(() => {
    console.log(6)
  })
  setTimeout(() => {
    new Promise(resolve => {
      console.log(7)
      resolve()
    }).then(() => {
      console.log(8)
    })
  })
  console.log(9)
</script>

1、首先,这段代码会作为宏任务而被添加到宏任务队列里面。这时候,宏任务队列只有一个任务,主线程为空,执行这个任务。
2、console.log(1)入栈,打印1,执行完毕,出栈
3、setTimeout入栈,挂起,等待200ms后将回调函数添加到宏任务队列
4、setTimeout入栈,挂起,等待100ms后将回调函数添加到宏任务队列
5、promise入栈,打印5,然后将then添加到微任务队列
6、setTimeout入栈,挂起,等待4ms后将回调函数加入到宏任务队列。这里提一嘴,HTML5标准规定了setTimeout()的第二个参数的最小值(最短间隔),不得低于4毫秒。
7、console.log(9)入栈,打印9,执行完毕,出栈
8、主线程为空,检查微任务队列是否有函数,发现有,入栈执行,打印6
到这里,不考虑其他的渲染什么的,本次事件循环就结束了,这时候的打印结果就是1 5 9 6 。
主线程又空了,事件轮询模块会一直轮询宏任务队列是否有任务可以执行。而很明显,在三个挂起的setTimeout里面,第六步的setTimeout是最快将
回调函数添加到宏任务队列的。这时候就可以进行下一个事件循环了。
9、循环开始,首先会打印7,然后将then添加到微任务队列,因为本次循环没有其他事做了,接着就执行微任务队列里的任务,打印8
10、继续轮询,而第四步比第三步更快,先打印3,又发现了setTimeout,继续挂起
而这时候第十步和地三步的哪个更快呢?这就要考虑在第三步到第十步之前有没有耗时的任务了。我们这里并没有什么耗时任务,所以第十步依然会比
第三步先执行。打印4,最后打印2 。整个代码就执行完毕了。

参考链接

5、深入理解箭头函数

箭头函数没有 this 它的this 在外部环境中寻找

箭头函数 VS bind
箭头函数 => 和使用 .bind(this) 调用的常规函数之间有细微的差别:

.bind(this) 创建了一个该函数的“绑定版本”。
箭头函数 => 没有创建任何绑定。箭头函数只是没有 this。this 的查找与常规变量的搜索方式完全相同:在外部词法环境中查找。

箭头函数没有 arguments

不能使用new 进行调用

6、call, apply, bind 的详解

this 指向的是调用它的对象,箭头函数里没有 this ,它会指向当前最近不是箭头函数的 this ,找不到就是 window
作用:动态修改当前当前函数内部的环境对象的 this 指针指向

apply() 方法调用一个函数, 其具有一个指定的this值,以及作为 一个数组(或类似数组的对象) 提供的参数

语法:func.apply(thisArg, [argsArray])

thisArg 必选。在 func 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。

argsArray 可选。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果该参数的值为 null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。

例:

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(arr) {
  Product.apply(this, arr); //this指向实例对象food
  this.category = 'food';
}

let food = new Food(['cheese', 5])

call() 方法使用一个指定的 this 值和单独给出的 一个或多个参数 来调用一个函数。
function.call(thisArg, arg1, arg2, …)

thisArg 可选。在 function 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。

arg1, arg2, … 指定的参数列表。

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.bind(this, name, price)(); //this指向实例对象food
  this.category = 'food';
}

let food = new Food('cheese', 5);

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

语法:

function.bind(thisArg[, arg1[, arg2[, …]]])

thisArg 调用绑定函数时作为 this 参数传递给目标函数的值。如果使用new运算符构造绑定函数,则忽略该值。当使用 bind 在 setTimeout 中创建一个函数(作为回调提供)时,作为 thisArg 传递的任何原始值都将转换为 object。如果 bind 函数的参数列表为空,或者thisArg是null或undefined,执行作用域的 this 将被视为新函数的 thisArg。

arg1, arg2, … 当目标函数被调用时,被预置入绑定函数的参数列表中的参数。

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.bind(this, name, price)(); //this指向实例对象food
  this.category = 'food';
}

let food = new Food('cheese', 5);

三者区别
apply 使用 数组 作为参数;

call 使用 参数列表 作为参数;

bind 使用 参数列表 作为参数,且创建了一个新的函数,需要 被调用 才会起作用。

7、xss注入攻击

XSS,是跨站脚本(Cross-site scripting)的简称,这是一种网站应用程序的安全漏洞攻击,代码注入的一种,其允许恶意用户将代码注入到网页上,之后其他用户在观看网页时就会受到影响,这类攻击通常包含了HTML以及用户端脚本语言如JavaScript等。
XSS攻击可以分为两类:反射型和存储型
反射型:
反射型XSS是非持久化的,需要欺骗用户自己去点击带有特定参数的XSS代码链接才能触发,一般是欺骗用户点击特定链接来进行恶意攻击,攻击代码就在url当中。
例如:

正常的:http://www.dvwa.com/vulnerabilities/xss_r/?name=index
获取用户cookie:http://www.dvwa.com/vulnerabilities/xss_r/?name=<script>alert(document.cookie)</script>

存储型:
存储型XSS攻击,是指将恶意代码被当做正常数据插入到服务器上的数据库中,当用户正常访问页面的时候,恶意代码从数据库中提取出来并被触发。

这类方法和反射型最大的区别在于其攻击载荷的存储位置不同,反射型XSS的攻击载荷并不存储在服务器上,攻击时需要将链接发送给特定用户,存储型XSS的攻击载荷直接保存在了服务器上,因此很多时候是无差别攻击。

DOM based XSS
DOM based XSS通过恶意脚本修改页面的DOM节点来发起攻击,是发生在前端的攻击。DOM型XSS的特殊之处在于,用户的输入经过了DOM操作,特别是在innerHTML、ajax中经常出现。

一般的攻击流程大致如下:

攻击者构造出特殊的URL,其中包含恶意代码,例如
用户打开带有恶意代码的URL
用户浏览器接受到响应后执行解析,前端JavaScript取出URL中的恶意代码并执行
恶意代码窃取用户数据并发送到攻击者的网站,冒充用户行为,调用目标网站接口执行攻击者指定的操作。

8、‘==’ 的流程

如果对比双方的类型不一样的话,就会进行类型转换。判断流程为:

  • 首先会判断两者类型是否相同。相同的话比大小,类型不相同的话,那么就会进行类型转换
  • 会先判断是否在对比 null 和 undefined,是的话就会返回 true
  • 判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number
  • 判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断
  • 判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断

9、for in 和 for of 的区别

for in 遍历的是数组/对象的key值

for of适用遍历数/数组对象/字符串/map/set等拥有迭代器对象(iterator)的集合,但是不能遍历对象,因为没有迭代器对象,但如果想遍历对象的属性,你可以用for in循环(这也是它的本职工作)或用内建的Object.keys()方法

for in遍历的是数组的索引(即键名),而for of遍历的是数组元素值

for in总是得到对象的key或数组、字符串的下标

for of总是得到对象的value或数组、字符串的值

10、浏览器的事件机制

什么是事件:
事件是用户操作页面时发生的交互动作,比如click/move等,事件除了用户触发的动作外,还可以是文档加载、窗口滚动和大小调整。事件被封装为一个event对象,包含了事件的属性和方法。
事件流:
事件流就是事件的流向,先捕获,再到事件源,最后再冒泡,在DOM2级事件模型中,事件流分为三个阶段:事件捕获、事件处理、事件冒泡。
DOM2级事件模型:
一共三个过程:事件捕获阶段:事件从document一直向下传播到目标元素,依次检查经过的结点是否绑定了事件监听函数,如果绑定则执行。后两个阶段与IE事件模型相同。
事件冒泡:
事件冒泡就是元素自身的事件被触发后,如果父元素有相同的事件,如onclick 事件,那么元素本身的触发状态就会传递,也就是冒泡到父元素,父元素的相同事件也会一级一级根据嵌套关系向外触发,直到 document/window,冒泡过程结束。
如何阻止事件冒泡

  • 普通浏览器:event.stopPropagation()
  • IE浏览器:event.cancelBubble = true

事件委托
事件委托就是把子元素响应事件的函数委托到父元素,由父元素统一处理多个子元素的事件。事件委托的优点是内存消耗少,效率较高、可以动态绑定事件。

11、原型链和闭包

原型:
每个对象都有一个 proto 属性指向它的 prototype 原型对象
每个构造函数都有一个 prototype 原型对象
prototype 原型对象里的 constructor 指向构造函数本身
在这里插入图片描述
实例对象的__proto__指向构造函数的prototype,从而实现继承。

prototype对象相当于特定类型所有实例对象都可以访问的公共容器

在这里插入图片描述
例子:

function Person (name, age) {
    this.name = name
    this.age = age
}
Person.prototype.getName = function () { console.log(this.name)}

function Teacher (name, age, subject) {
    Person.call(this, name, age)
    this.subject = subject
}
Teacher.prototype = Object.create(Person.prototype) //把Person.prototype的备份直接拷贝到Teacher.prototype(直接赋值的话是引用关系)
Teacher.prototype.constructor = Teacher //构造函数指向原型对象本身

var teacher = new Teacher('jack', 25, Math)

teacher.age
25
teacher.name
"jack"

闭包:
闭包是可以访问另一个函数对象内部变量的表达式

当一个函数能够记住并访问到其所在的词法作用域及作用域链,特别强调是在其定义的作用域外进行的访问,此时该函数和其上层执行上下文共同构成闭包。

  1. 闭包一定是函数对象

  2. 闭包和词法作用域、作用域链、垃圾回收机制等息息相关

  3. 函数内保持对上层作用域的引用 *

  4. 当函数在其定义的作用域外进行访问时,才产生闭包 *

  5. 闭包是由该函数和其上层执行上下文共同构成 *

12、跨域问题及解决办法

跨域问题:受浏览器同源策略(协议,域名,端口相同)的限制,浏览器向服务器发送跨域请求的时候会发生的问题
解决办法:

  • jsonp:只支持 GET,不支持 POST 请求,不安全 XSS
  • cors:需要后台配合进行相关的设置
  • postMessage:配合使用 iframe,需要兼容 IE6、7、8、9
  • document.domain:仅限于同一域名下的子域
  • websocket:需要后台配合修改协议,不兼容,需要使用 http://socket.io
  • proxy:使用代理去避开跨域请求,需要修改 nginx、apache 等的配置

jsonp
JSONP(JSON with Padding(填充))是 JSON 的一种“使用模式”,本质不是 Ajax 请求,是 script 标签请求。

JSONP 请求本质上是利用了 “Ajax 请求会受到同源策略限制,而 script 标签请求不会” 这一点来绕过同源策略。

JSONP 缺点
只支持 GET 请求
只支持跨域 HTTP 请求这种情况,不能解决不同域的两个页面之间如何进行 JavaScript 调用的问题
调用失败的时候不会返回各种 HTTP 状态码。
安全性,万一假如提供 JSONP 的服务存在页面注入漏洞,即它返回的 javascript 的内容被人控制的。

跨域资源共享 CORS
跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的 Web 应用被准许访问来自不同源服务器上的指定的资源。 — MDN

Nginx Proxy
Nginx 是一种高性能的反向代理服务器,可以用来轻松解决跨域问题。

反向代理拿到客户端的请求,将请求转发给其他的服务器,主要的场景是维持服务器集群的负载均衡,换句话说,反向代理帮其它的服务器拿到请求,然后选择一个合适的服务器,将请求转交给它。

Nginx 相当于起了一个跳板机,这个跳板机的域名也是client.com,让客户端首先访问 client.com/api,这当然没有跨域,然后 Nginx 服务器作为反向代理,将请求转发给server.com,当响应返回时又将响应给到客户端,这就完成整个跨域请求的过程。

websocket
没有同源限制,客户端可以与任意服务器通信。

13、webpack 中loader 和plugin 的区别

loader 是文件解析器,用来预处理文件,比如css-loader解析css文件,并将其处理成

plugin 是插件,用来增强文件功能,比如说将css提取到一个单独的文件当中。他可以为每一个包含css的js文件创建一个css文件。

二者区别:
loader即为文件加载器,操作的是文件,将文件A通过loader转换成文件B,是一个单纯的文件转化过程。

plugin即为插件,是一个扩展器,丰富webpack本身,增强功能 ,针对的是在loader结束之后,webpack打包的整个过程,他并不直接操作文件,而是基于事件机制工作,监听webpack打包过程中的某些节点,执行广泛的任务。

14、进程和线程的比较

一个程序至少有一个进程,一个进程至少有一个线程.
线程的划分尺度小于进程,使得多线程程序的并发性高。
进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.

进程和线程的主要差别在于它们是不同的操作系统
资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程

15、weakmap 和 weakset

通常,当对象、数组之类的数据结构在内存中时,它们的子元素,如对象的属性、数组的元素都被认为是可达的。

例如,如果把一个对象放入到数组中,那么只要这个数组存在,那么这个对象也就存在,即使没有其他对该对象的引用。

let john = { name: "John" };

let array = [ john ];

john = null; // 覆盖引用

// 前面由 john 所引用的那个对象被存储在了 array 中
// 所以它不会被垃圾回收机制回收
// 我们可以通过 array[0] 获取到它

类似的,如果我们使用对象作为常规 Map 的键,那么当 Map 存在时,该对象也将存在。它会占用内存,并且应该不会被(垃圾回收机制)回收。

例如:

let john = { name: "John" };

let map = new Map();
map.set(john, "...");

john = null; // 覆盖引用

// john 被存储在了 map 中,
// 我们可以使用 map.keys() 来获取它

WeakMap 在这方面有着根本上的不同。它不会阻止垃圾回收机制对作为键的对象(key object)的回收。

WeakMap 和 Map 的第一个不同点就是,WeakMap 的键必须是对象

WeakMap 不支持迭代以及 keys(),values() 和 entries() 方法。所以没有办法获取 WeakMap 的所有键或值。

WeakMap 只有以下的方法:

weakMap.get(key)
weakMap.set(key, value)
weakMap.delete(key)
weakMap.has(key)

16、函数柯里化

函数柯里化是指将一个函数从可调用的 f(a, b, c) 转换为可调用的 f(a)(b)(c)
例:

function curry(func) {

  return function curried(...args) {
    if (args.length >= func.length) {
      return func.apply(this, args);
    } else {
      return function(...args2) {
        return curried.apply(this, args.concat(args2));
      }
    }
  };

}

function sum(a, b, c) {
  return a + b + c;
}

let curriedSum = curry(sum);

alert( curriedSum(1, 2, 3) ); // 6,仍然可以被正常调用
alert( curriedSum(1)(2,3) ); // 6,对第一个参数的柯里化
alert( curriedSum(1)(2)(3) ); // 6,全柯里化

17、服务端渲染

服务端渲染介绍
umiJs

18、页面渲染优化

浏览器的进程分为
主进程
GPU渲染进程
插件进程
网络进程
渲染进程

  • 防止阻塞渲染,css文件放在首部,js文件放在底部,一些不改变dom和css的js 使用 defer 和 async 属性告诉浏览器可以异步加载,不阻塞解析 。
  • 把一些纯计算的工作放到web worker 上去执行
  • 节流和防抖
  • 减少样式的修改导致的重排和重绘
  • 提高代码质量(dom和css的嵌套不要太深,js中对dom的转存,不要频繁操作dom和其样式)
  • 静态资源的缓存,雪碧图、接口分片提高首屏渲染时间

19、为什么是三次握手四次挥手

在这里插入图片描述

第一次握手:第一次握手是客户端发送同步报文到服务端,这个时候客户端是知道自己具备发送数据的能力的,但是不知道服务端是否有接收和发送数据的能力;

第二次握手:当服务端接收到同步报文后,回复确认同步报文,此时服务端是知道客户端具有发送报文的能力,并且知道自己具有接收和发送数据的能力,但是并不知道客户端是否有接收数据的能力;

第三次握手:当客户端收到服务端的确认报文后,知道服务端具备接收和发送数据的能力,但是此时服务端并不知道自己具有接收的能力,所以还需要发送一个确认报文,告知服务端自己是具有接收能力的。

当整个三次握手结束过后,客户端和服务端都知道自己和对方具备发送和接收数据的能力,随后整个连接建立就完成了,可以进行后续数据的传输了。

四次挥手
在这里插入图片描述
第一次挥手客户端发起关闭连接的请求给服务端;

第二次挥手:服务端收到关闭请求的时候可能这个时候数据还没发送完,所以服务端会先回复一个确认报文,表示自己知道客户端想要关闭连接了,但是因为数据还没传输完,所以还需要等待;

第三次挥手:当数据传输完了,服务端会主动发送一个 FIN 报文,告诉客户端,表示数据已经发送完了,服务端这边准备关闭连接了。

第四次挥手:当客户端收到服务端的 FIN 报文过后,会回复一个 ACK 报文,告诉服务端自己知道了,再等待一会就关闭连接。

疑问:
(1)、为什么握手要三次,挥手却要四次呢?那是因为握手的时候并没有数据传输,所以服务端的 SYN 和 ACK 报文可以一起发送,但是挥手的时候有数据在传输,所以 ACK 和 FIN 报文不能同时发送,需要分两步,所以会比握手多一步。
(2)、为什么客户端在第四次挥手后还会等待 2MSL?等待 2MSL 是因为保证服务端接收到了 ACK 报文,因为网络是复杂了,很有可能 ACK 报文丢失了,如果服务端没接收到 ACK 报文的话,会重新发送 FIN 报文,只有当客户端等待了 2MSL 都没有收到重发的 FIN 报文时就表示服务端是正常收到了 ACK 报文,那么这个时候客户端就可以关闭了。

20、css的引用的几种方式

  • 行内样式 即直接将css样式写在标签中的style属性里
  • 嵌入引用,即将样式规则写在页面中的
link 和 @import 的却别:
1、link是HTML标签,而@import是css提供的一种方式所有它只能挂载在css里加载css
2、加载顺序的差别,link引用的css会随页面同时加载,而@import引用会等到页面全部加载完成后再加载
3、兼容性差别,@import只有在IE 5 以上的浏览器才能支持
4、使用dom控制样式时的差别,当使用javascript控制dom去改变样式的时候,只能使用link标签,因为@import不是dom可以控制的
5、@import可以在css中再次引入其它样式表,综合来看@import url(style.css)是最优写法

21、为什么js要放在body里面而不放在head里

因为浏览器在解析html的时候是从上往下执行的,js放在头部,dom还没渲染完,所以你绑定的值就会没有,硬要加的话在代码前加document.ready()或者window.onload()

js可以分为外部的和内部的,外部的js一般放到head内。内部的js也叫本页面的JS脚本,内部的js一般放到body内,这样做的目的有很多:

  • 不阻塞页面的加载(事实上js会被缓存)。

  • 可以直接在js里操作dom,这时候dom是准备好的,即保证js运行时dom是存在的。

  • 建议的方式是放在页面底部,监听window.onload 或 readystate 来触发js。

  • 延伸:

head内的js会阻塞页面的传输和页面的渲染。head 内的 JavaScript 需要执行结束才开始渲染 body,所以尽量不要将 JS 文件放在 head 内。可以选择在 document 完成时,或者特定区块后引入和执行 JavaScript。head 内的 JavaScript 需要执行结束才开始渲染 body,所以尽量不要将 JS 文件放在 head 内。可以选择在 document 完成时,或者特定区块后引入和执行 JavaScript。所以在head内的js一般要先执行完后,才开始渲染body页面。为了避免head引入的js脚本阻塞流浪器中主解析引擎对dom的解析工作,对dom的渲染,一般原则是,样式在前面,dom文档,脚本在最后面。遵循先解析再渲染再执行script这个顺序。

也就是说一般head里面只放引入js,需要在本页面的内部js触发用的一般放在body里面的最后。

22、cookie、localStorage、sessionStorage

1)相同点是都是保存在浏览器端、且同源的

2)cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递,而sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下

3)存储大小限制也不同,cookie数据不能超过4K,同时因为每次http请求都会携带cookie、所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大

4)数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭

5)作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localstorage在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的

6)web Storage支持事件通知机制,可以将数据更新的通知发送给监听者

7)web Storage的api接口使用更方便

cookie和session的区别

1)cookie数据存放在客户的浏览器上,session数据放在服务器上

2)cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑*到安全应当使用session

3)session会在一定时间内保存在服务器上,当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie

4)单个cookie保存的数*据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie

5)建议将登录信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中

6)session保存在服务器,客户端不知道其中的信心;cookie保存在客户端,服务器能够知道其中的信息

7)session中保存的是对象,cookie中保存的是字符串

8)session不能区分路径,同一个用户在访问一个网站期间,所有的session在任何一个地方都可以访问到,而cookie中如果设置了路径参数,那么同一个网站中不同路径下的cookie互相是访问不到的。

9)COOKIE:是服务端向客户端写入的小的片段信息。cookie信息保存在服务器缓存区,不会在客户端显现。当你第一次登陆一个网站,服务器向你的机器写得片段信息。你可以在Internet选项中找到存放cookie的文件夹。如果不删除,cookie就一直在这个文件夹中。

10)session需要借助cookie才能正常工作。如果客户端完全禁止cookie,session将失效。 但是如果服务器端启用了url编码,也就是用 URLEncoder.encode()把所有的url编码了,则会在url后面出现如下类似的东西 index.jsp:jsessionid=fdsaffjdlks;jaf;lkdjsf 服务器通过这个进行session的判断.

11)Cookie支持跨域名访问,例如将domain属性设置为“.biaodianfu.com”,则以“.biaodianfu.com”为后缀的一切域名均能够访问该Cookie。跨域名Cookie如今被普遍用在网络中,例如Google、Baidu、Sina等,而Session则不会支持跨域名访问。Session仅在他所在的域名内有效。仅运用Cookie或者仅运用Session可能完成不了理想的效果。这时应该尝试一下同时运用Cookie与Session。Cookie与Session的搭配运用在实践项目中会完成很多意想不到的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值