面试题 从 JS 基础知识到 JS Wed API

常说的js(浏览器执行的js)包含两个部分:

一、js基础知识(ECMA262标准)

1、变量类型和计算
1 .1、值类型(存的是值)

var a = 100;
var b = a;
a = 200;
console.log(a);  //200
console.log(b);  //100

1.2、引用类型(存的是地址)

var a = {age: 25};
var b = a;
b.age = 100;
console.log(a.age);  //100
console.log(b.age);  //100

  • 引用类型:数组、对象、函数

引用类型:数组、对象、函数

1.3、typeof运算符(6个)

typeof undefined    //undefined
typeof 'abc'    //string
typeof 123    //number
typeof true    //boolean
typeof {}    //object
typeof []    //object
typeof null    //object
typeof console.log    //function

1.4、强制类型转换

// 字符串拼接
var a = 100 + 10  	//110
var b = 100 + '10'	//10010
 
// == 运算符
100 == '100' 		//true
0 == ''			//true
null == undefined	//true
 
// if语句
var a = true;
if (a) {
    // ...
}
var b = 100;
if (b) {
    // ...
}
var c = '';
if (c) {
    // ...
}
 
// 逻辑运算
console.log(10 && 0)  		//0
console.log('' || 'abc') 	//'abc'
console.log(!window.abc)       //true
 
// 判断一个变量会被当做true还是false
var a = 100;
console.log(!!a)           //true

1.5、js内置函数

Object
Array
Boolean
Number
String
Function
Date
RegExp
Error

1.6、何时使用 === 何时使用 ===

// 问题:何时使用===,何时使用==
if(obj.a == null) {
	// 相当于abj.a === null || abj.a === undefined的简写形式
	// 其他情况都用 ===
}

1.7、JSON

// 问题:如何理解JSON
// JSON 既是一种语法格式,还是JS对象
JSON.stringify({a:10, b: 20})
JSON.parse('{"a":10, "b": 20}')

2、原型和原型链
2.1、构造函数

function Foo(name, age) {
	this.name = name;
	this.age = age;
	this.class = 'class-1';
	// return this	//默认有这一行
}
 
var f1 = new Foo('zhangsan', 18);
var f2 = new Foo('lisi', 25);  //创建多个对象

2.2、构造函数扩展

1、var a = {} 其实是 var a = new Object(){} 的语法糖
2、var a = [] 其实是 var a = new Array(){} 的语法糖
3、function Foo(){…} 其实是 var Foo = new Function(){} 的语法糖

2.3、原型五条规则

1、所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了’null’以外)
2、所有的引用类型(数组、对象、函数),都有一个__proto__属性,属性值是一个普通对象 隐式原型
3、所有的函数,都有一个prototype属性,属性值也是一个普通对象 显式原型
4、所有的引用类型(数组、对象、函数),proto__属性指向它的构造函数的prototype属性值
5、当试图得到一个对象的某一个属性时,如果这个对象本身没有这个属性,那么会去它的__proto
(即它的构造函数的prototype)中寻找


var obj = {};
var arr = [];
function fn () {};
 
obj.a = 100;
arr.a = 100;
fn.a = 100;
 
console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fn.__proto__);
 
console.log(fn.prototype);
 
console.log(obj.__proto__ === Object.prototype);
console.log(arr.__proto__ === Array.prototype);
console.log(fn.__proto__ === Function.prototype);


// 构造函数
function Foo(name) {
	this.name =name
}
Foo.prototype.alertName = function () {
	alert(this.name)
}
// 创建实例
var f = new Foo('zhangsan')
f.printName = function () {
	console.log(this.name)
}
// 测试
f.printName();
f.alertName();

this不论是自己属性还是原型属性,都指向f

2.4、原型链

在这里插入图片描述

2.5、继承

对象冒充实现属性继承;原型链实现方法继承


function ClassA(sColor) {
    this.color = sColor;
}
 
ClassA.prototype.sayColor = function () {
    alert(this.color);
};
 
function ClassB(sColor, sName) {
    //this.newMethod = ClassA;
    //this.newMethod(color);
    //delete this.newMethod;
    ClassA.call(this, sColor);
    this.name = sName;
}
 
ClassB.prototype = new ClassA();
 
ClassB.prototype.sayName = function () {
    alert(this.name);
};


var objA = new ClassA("blue");
var objB = new ClassB("red", "John");
objA.sayColor();	//输出 "blue"
objB.sayColor();	//输出 "red"
objB.sayName();	//输出 "John"

instance of 用于判断 引用类型 属于哪个 构造方法

使用 instanceof 判断一个函数是否是一个变量(引用类型)的构造函数

2.6、对象循环自身属性


var item;
for (item in f) {
	if (f.hasOwnProperty(item)) {
		console.log(item)
	}
}

3、作用域和闭包
3.1、函数声明和函数表达式
3.1.1、函数声明

fn()	// ok
function fn () {
    console.log("函数声明")
}

3.1.2、函数表达式

fn1()	// Uncaught TypeError: fn1 is not a function
var fn1 = function () {
    console.log("函数表达式")
}
// 等价于
console.log(a)  //a = undifined
var a = 100;
// 等价于
var a;
console.log(a)  //a = undifined
a = 100;

3.2、作用域
3.2.1、全局作用域和函数作用域

fn1()	// Uncaught TypeError: fn1 is not a function
var fn1 = function () {
    console.log("函数表达式")
}
// 等价于
console.log(a)  //a = undifined
var a = 100;
// 等价于
var a;
console.log(a)  //a = undifined
a = 100;

js没有块级作用域

3.3、执行上下文
在这里插入图片描述

3.4、this 要在执行时才能确认值,定义时无法确认
3.4.1、四种应用场景

1、作为构造函数执行
2、作为对象属性执行
3、作为普通函数执行
4、call(变量)、apply(数组)、bind

3.4.2、示例

fn1()	// Uncaught TypeError: fn1 is not a function
var fn1 = function () {
    console.log("函数表达式")
}
// 等价于
console.log(a)  //a = undifined
var a = 100;
// 等价于
var a;
console.log(a)  //a = undifined
a = 100;

3.5、作用域链

当前作用域没有定义的变量,去定义时的父级作用域查找


fn1()	// Uncaught TypeError: fn1 is not a function
var fn1 = function () {
    console.log("函数表达式")
}
// 等价于
console.log(a)  //a = undifined
var a = 100;
// 等价于
var a;
console.log(a)  //a = undifined
a = 100;

3.6、闭包
3.6.1、闭包应用场景

函数作为返回值
函数作为参数传递

3.6.2、示例

function fun(){
	var a = 100;
	return function (){
		console.log(a)
	}
}
var unf1 = fun;
var a = 200;
fun1() // 100


function fun(){
	var a = 100;
	return function (){
		console.log(a)
	}
}
var fun1= fun;
function fun2(fn){
 	var a = 200;
	 fu()
}
fun2(fun1) // 100

4、异步单线程
4.1、异步和同步区别

是否存在阻塞



// 异步
console.log(100);
setTimeout(function () {
	    console.log(200);
},1000);
console.log(300)



// 同步
console.log(100);
alert(200)
console.log(300)

4.2、异步应用场景

定时任务:setTimeout setInterval
网络请求:ajax请求,动态加载
事件绑定
示例


// ajax请求示例
console.log('start');
$.get('./data.json', function (data) {
    console.log(data)
})
console.log('end')


// 动态加载img示例
console.log('start');
var img = document.creatrElement('img')
img.onload = function () {
    console.log('loaded');
}
console.log('end')


// 事件绑定示例
console.log('start');
document.getElementById('btn').addEventListener('click', function () {
    console.log('clicked')
})
console.log('end')

4.3、异步与单线程

在这里插入图片描述

5、日期


console.log(Date.now())  // 获取当前时间毫秒数
var dt = new Date()
console.log(dt.getTime())  // 获取毫秒数
console.log(dt.getFullYear())  // 年
console.log(dt.getMonth())  // 月(0 - 11)
console.log(dt.getDate())  // 日(0 - 31)
console.log(dt.getHours())  // 小时(0 - 23)
console.log(dt.getMinutes())  // 分钟(0 - 59)
console.log(dt.getSeconds())  // 秒(0 - 59)

6、Math

console.log(Math.random())

7、数组API


var arr = [1, 2, 3, 6, 5, 4];
// forEach遍历所有元素
arr.forEach(function(item,index){
    console.log('item: ' + item)
    console.log('index: ' + index)
})
// every判断所有元素是否都符合条件
var result = arr.every(function(item,index){
    if(item < 4) {
	return true
    }
})
console.log(result)
// some判断是否有至少一个元素符合条件
var result = arr.some(function(item,index){
    if(item < 4) {
	return true
    }
})
console.log(result)
// sort排序
var arr2 = arr.sort(function(a,b){
    return a - b 
})
console.log(arr2)
// map对元素从新组装,生成新数组
var arr2 = arr.map(function(item,index){
    return item + 100
})
console.log(arr2)
// filter过滤符合条件的元素
var arr2 = arr.filter(function(item,index){
    if(item > 4){
	return true
    }
})
console.log(arr2)

8、对象API(for…in)

在这里插入图片描述

二、js-Web-API(W3C标准)

W3C标准没有规定任何js基础相关的东西(变量、原型、作用域、异步);定义了用于浏览器中js操作页面的API和全局变量

1、DOM
1.1、DOM本质

DOM可理解为:浏览器把拿到的html代码,结构化一个浏览器能识别并且js可操作的一个模型

1.2、DOM节点操作


var div1 = document.getElementById('div1');  // 元素
var div2 = document.getElementsByTagName('div2');  //集合
var div3 = document.getElementsByClassName('div3');  //集合
var div4 = document.querySelectorAll('div4');  //集合

1.3、DOM结构操作


var div1 = document.getElementById('div1');
// 新增节点
var p1 = document.creatrElement('p');
p1.innerHTML = 'this is p1';
div1.appendChild(p1);  // 增加新创建的元素  
// 移动已有节点
var p2 = document.getElementById('p2');
div1.appendChild(p2);
// 获取父节点
var parent = div1.parentElement;
// 获取子节点
var childs = div1.childNodes;
// 删除节点
div1.removeChild(childs[0])

1.4、DOM属性(待完善)

Attribute和property区别?

Attribute 是对html标签属性的修改
property 是对js对象属性的修改

2、BOM
2.1、navigator
Navigator 对象
Navigator 对象包含有关浏览器的信息。

注释:没有应用于 navigator 对象的公开标准,不过所有浏览器都支持该对象。

Navigator 对象集合
集合描述
plugins[]返回对文档中所有嵌入式对象的引用。
该集合是一个 Plugin 对象的数组,其中的元素代表浏览器已经安装的插件。Plug-in 对象提供的是有关插件的信息,其中包括它所支持的 MIME 类型的列表。
虽然 plugins[] 数组是由 IE 4 定义的,但是在 IE 4 中它却总是空的,因为 IE 4 不支持插件和 Plugin 对象。
Navigator 对象属性
属性描述
appCodeName返回浏览器的代码名。
appCodeName返回浏览器的代码名。
appMinorVersion返回浏览器的次级版本。
appName返回浏览器的名称。
appVersion返回浏览器的平台和版本信息。
browserLanguage返回当前浏览器的语言。
cookieEnabled返回指明浏览器中是否启用 cookie 的布尔值。
cpuClass返回浏览器系统的 CPU 等级。
onLine返回指明系统是否处于脱机模式的布尔值。
platform返回运行浏览器的操作系统平台。
systemLanguage返回 OS 使用的默认语言。
userAgent返回由客户机发送服务器的 user-agent 头部的值。
userLanguage返回 OS 的自然语言设置。
2.2、screen
Navigator 对象方法
方法描述
javaEnabled()规定浏览器是否启用 Java。
taintEnabled()规定浏览器是否启用数据污点 (data tainting)。
Navigator 对象描述

Navigator 对象包含的属性描述了正在使用的浏览器。可以使用这些属性进行平台专用的配置。

虽然这个对象的名称显而易见的是 Netscape 的 Navigator 浏览器,但其他实现了 JavaScript 的浏览器也支持这个对象。

Navigator 对象的实例是唯一的,可以用 Window 对象的 navigator 属性来引用它。

2.3、location
Location 对象
Location 对象

Location 对象包含有关当前 URL 的信息。
Location 对象是 Window 对象的一个部分,可通过 window.location 属性来访问。
######Location 对象属性

属性描述
hash设置或返回从井号 (#) 开始的 URL(锚)。
host设置或返回主机名和当前 URL 的端口号。
hostname设置或返回当前 URL 的主机名。
href设置或返回完整的 URL。
pathname设置或返回当前 URL 的路径部分。
port设置或返回当前 URL 的端口号。
protocol设置或返回当前 URL 的协议。
search设置或返回从问号 (?) 开始的 URL(查询部分)。
Location 对象方法
属性描述
assign()加载新的文档。
reload()重新加载当前文档。
replace()用新的文档替换当前文档。

Location 对象存储在 Window 对象的 Location 属性中,表示那个窗口中当前显示的文档的 Web 地址。它的 href 属性存放的是文档的完整 URL,其他属性则分别描述了 URL 的各个部分。这些属性与 Anchor 对象(或 Area 对象)的 URL 属性非常相似。当一个 Location 对象被转换成字符串,href 属性的值被返回。这意味着你可以使用表达式 location 来替代 location.href。

不过 Anchor 对象表示的是文档中的超链接,Location 对象表示的却是浏览器当前显示的文档的 URL(或位置)。但是 Location 对象所能做的远远不止这些,它还能控制浏览器显示的文档的位置。如果把一个含有 URL 的字符串赋予 Location 对象或它的 href 属性,浏览器就会把新的 URL 所指的文档装载进来,并显示出来。

除了设置 location 或 location.href 用完整的 URL 替换当前的 URL 之外,还可以修改部分 URL,只需要给 Location 对象的其他属性赋值即可。这样做就会创建新的 URL,其中的一部分与原来的 URL 不同,浏览器会将它装载并显示出来。例如,假设设置了Location对象的 hash 属性,那么浏览器就会转移到当前文档中的一个指定的位置。同样,如果设置了 search 属性,那么浏览器就会重新装载附加了新的查询字符串的 URL。

除了 URL 属性外,Location 对象的 reload() 方法可以重新装载当前文档,replace() 可以装载一个新文档而无须为它创建一个新的历史记录,也就是说,在浏览器的历史列表中,新文档将替换当前文档。

2.4、history
History 对象
History 对象

History 对象包含用户(在浏览器窗口中)访问过的 URL。

History 对象是 window 对象的一部分,可通过 window.history 属性对其进行访问。

注释:没有应用于 History 对象的公开标准,不过所有浏览器都支持该对象。

History 对象属性
属性描述
length返回浏览器历史列表中的 URL 数量。
History 对象方法
方法描述
back()加载 history 列表中的前一个 URL。
forward()加载 history 列表中的下一个 URL。
go()加载 history 列表中的某个具体页面。
History 对象描述

History 对象最初设计来表示窗口的浏览历史。但出于隐私方面的原因,History 对象不再允许脚本访问已经访问过的实际 URL。唯一保持使用的功能只有 back()、forward() 和 go() 方法。

例子

下面一行代码执行的操作与单击后退按钮执行的操作一样:


history.back()

下面一行代码执行的操作与单击两次后退按钮执行的操作一样:


history.go(-2)

3、事件
3.1、通用事件绑定

Array.prototype.indexOf = function( obj ){
    var result = -1 , length = this.length , i=length - 1;
    for ( ; i>=0 ; i-- ) {
        if ( this[i] == obj ) {
            result = i;
            break;
        }
    }
    return result;
}
Array.prototype.contains = function( obj ) {
    return ( this.indexOf( obj ) >=0 )
}
Array.prototype.append = function( obj , nodup ) {
    if ( !(nodup && this.contains( obj )) ) {
        this[this.length] = obj;
    }
}
Array.prototype.remove = function( obj ) {
    var index = this.indexOf( obj );
    if ( !index ) return ;
    return this.splice( index , 1);
};
function addEvent(element , type , fun){
    if (!element.events) element.events = {};
    var handlers = element.events[type];
    if (!handlers) {
        handlers = element.events[type] = [];
        if(element['on' + type]) {
            handlers[0] = element['on' + type];
        }
    }
    handlers.append( fun , true)
    element['on' + type] = handleEvent;
}
function removeEvent(element , type , fun) {
    if (element.events && element.events[type]) {
        element.events[type].remove(fun);
    }
}
function handleEvent(event) {
    var returnValue = true , i=0;
    event = event || fixEvent(window.event);
    var handlers = this.events[event.type] , length = handlers.length;
    for ( ; i < length ; i++) {
        if ( handlers[i].call( this , event) === false ){
            returnValue = false;
        }
    }
    return returnValue;
}
function fixEvent(event) {
    event.preventDefault = fixEvent.preventDefault;
    event.stopPropagation = fixEvent.stopPropagation;
    return event;
}
fixEvent.preventDefault = function() {
    this.returnValue = false;
};
fixEvent.stopPropagation = function() {
    this.cancelBubble = true;
};

3.2、事件冒泡
什么是冒泡与捕获

以click点击事件为例。假如我们有一个多层结构标签。如下图,是4个div嵌套。每个div都有点击的监听事件,分别输出1234。当我们点击最里面的div时,点击事件开始传递,传递的全过程是1-2-3-4-4-3-2-1。

前半部分,事件从最外面的父div依次传递到最里面的后代div,1-2-3-4这部分我们叫捕获过程。
之后事件又从最里层的后代div逐层传出,4-3-2-1这部分我们叫冒泡过程。

如果我把捕获监听器和冒泡监听器都加上,如下图这样。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

添加两种监听的方法

在不使用任何框架的情况下,我们在js中通过addEventListener方法给Dom添加事件监听。这个方法有三个参数可以传递addEventListener(event,fn,useCapture)。event是事件类型click,focus,blur等;fn是事件触发时将执行的函数方法(function);第三个参数可以不传,默认是false,这个参数控制是否捕获触发。所以我们只穿两个参数时,这个事件是冒泡传递触发的,当第三个参数存在且为true时,事件是捕获传递触发的。

使用框架时可使用对应的框架提供的方法。如上面我使用了Vue框架,通过事件装饰来区分捕获与冒泡。

阻止传递

在不使用任何框架的情况下,我们在js中通过stopPropagation方法阻止事件继续传递。
使用框架时可使用对应的框架提供的方法。接下来我将了Vue框架的stop修饰符来阻止事件传递。

我们可以在传递过程中阻止事件继续传递,防止触发不需要的事件。
在这里插入图片描述
如图我在第三层捕获后阻止事件继续传递,那么后面的log方法不会继续执行。最终只输出1-2-3。

在这里插入图片描述

应用场景举例

我们在使用中多数情况下只使用冒泡监听。例如一条购物车信息,在这条信息中,右下角有一个删除按钮。点击这条消息可查看详情,点击删除按钮可将此商品移除。我们会分别给信息的div和删除button添加一个冒泡的click事件监听。如果不做阻止传递,点击删除button后,会显示商品详情。显然这不是我们想看到的。这时我们给button一个阻止事件传递的功能,点击删除按钮后,事件就会结束,就不再显示商品详情。

4、ajax
AJAX是创建交互式网页应用的网页开发技术的一种。

》Ajax = 异步 JavaScript 和 XML 或者是 HTML(标准通用标记语言的子集)。可以用于创建快速动态网页的技术。在无需重新加载整个网页的情况下,能够更新部分网页的技术。通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页页面。
在这里插入图片描述

扩展资料

Ajax 开发与传统的 B/S开发有很大的不同。这些不同引入了新的编程问题,最大的问题在于易用性。由于 Ajax 依赖浏览器的 JavaScript 和XML,浏览器的兼容性和支持的标准也变得和 JavaScript 的运行时性能一样重要了。

综合各种变化的技术和强耦合的客户服务端环境,Ajax 提出了一种新的开发方式。Ajax 开发人员必须理解传统的 MVC 架构,这限制了应用层次之间的边界。同时,开发人员还需要考虑 B/S 环境的外部和使用 Ajax 技术来重定型 MVC 边界。

最重要的是,Ajax 开发人员必须禁止以页面集合的方式来考虑 Web 应用而需要将其认为是单个页面。一旦 UI 设计与服务架构之间的范围被严格区分开来后,开发人员就需要更新和变化的技术集合了。

5、存储
5.1、cookie
1. 前言

朋友问我cookie是什么,用来干什么的,可是我居然无法清楚明白简短地向其阐述cookie,这不禁让我陷入了沉思:为什么我无法解释清楚,我对学习的方法产生了怀疑!在知乎上看到有人推荐使用费尔曼学习技巧,于是在重新学习cookie的过程中使用了该技巧来试验,效果有待验证!

在学习一个新的知识点前,我们应该明白自己的学习目标,要带着疑问去学习,该小节须要了解:

1.什么是cookie,cookie的作用
2.cookie的工作机制,即cookie是运作流程
3.cookie的基本属性(4个)以及我们如何使用cookie

2. 什么是cookie

HTTP协议本身是无状态的。什么是无状态呢,即服务器无法判断用户身份。Cookie实际上是一小段的文本信息(key-value格式)。客户端向服务器发起请求,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。

打个比方,我们去银行办理储蓄业务,第一次给你办了张银行卡,里面存放了身份证、密码、手机等个人信息。当你下次再来这个银行时,银行机器能识别你的卡,从而能够直接办理业务。

3. cookie机制

当用户第一次访问并登陆一个网站的时候,cookie的设置以及发送会经历以下4个步骤:

客户端发送一个请求到服务器 --》 服务器发送一个HttpResponse响应到客户端,其中包含Set-Cookie的头部 --》 客户端保存cookie,之后向服务器发送请求时,HttpRequest请求中会包含一个Cookie的头部 --》服务器返回响应数据

在这里插入图片描述
为了探究这个过程,写了代码进行测试,如下:
我在doGet方法中,new了一个Cookie对象并将其加入到了HttpResponse对象中

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      Cookie cookie = new Cookie("mcrwayfun",System.currentTimeMillis()+"");
      // 设置生命周期为MAX_VALUE
      cookie.setMaxAge(Integer.MAX_VALUE);
      resp.addCookie(cookie);
}

浏览器输入地址进行访问,结果如图所示:
在这里插入图片描述
可见Response Headers中包含Set-Cookie头部,而Request Headers中包含了Cookie头部。name和value正是上述设置的。

4. cookie属性项
属性项属性项介绍
NAME=VALUE键值对,可以设置要保存的 Key/Value,注意这里的 NAME 不能和其他属性项的名字一样
Expires过期时间,在设置的某个时间点后该 Cookie 就会失效
Domain生成该 Cookie 的域名,如 domain=“www.baidu.com”
Path该 Cookie 是在当前的哪个路径下生成的,如 path=/wp-admin/
Secure如果设置了这个属性,那么只会在 SSH 连接时才会回传该 Cookie
Expires

该属性用来设置Cookie的有效期。Cookie中的maxAge用来表示该属性,单位为秒。Cookie中通过getMaxAge()和setMaxAge(int maxAge)来读写该属性。maxAge有3种值,分别为正数,负数和0。

如果maxAge属性为正数,则表示该Cookie会在maxAge秒之后自动失效。浏览器会将maxAge为正数的Cookie持久化,即写到对应的Cookie文件中(每个浏览器存储的位置不一致)。无论客户关闭了浏览器还是电脑,只要还在maxAge秒之前,登录网站时该Cookie仍然有效。下面代码中的Cookie信息将永远有效。


 Cookie cookie = new Cookie("mcrwayfun",System.currentTimeMillis()+"");
 // 设置生命周期为MAX_VALUE,永久有效
 cookie.setMaxAge(Integer.MAX_VALUE);
 resp.addCookie(cookie);

当maxAge属性为负数,则表示该Cookie只是一个临时Cookie,不会被持久化,仅在本浏览器窗口或者本窗口打开的子窗口中有效,关闭浏览器后该Cookie立即失效。


Cookie cookie = new Cookie("mcrwayfun",System.currentTimeMillis()+"");
// MaxAge为负数,是一个临时Cookie,不会持久化
cookie.setMaxAge(-1);
resp.addCookie(cookie);

可以看到,当MaxAge为-1时,时间已经过期
在这里插入图片描述
当maxAge为0时,表示立即删除Cookie


Cookie[] cookies = req.getCookies();
Cookie cookie = null;
// get Cookie
for (Cookie ck : cookies) {
    if ("mcrwayfun".equals(ck.getName())) {
        cookie = ck;
        break;
     }
}

 if (null != cookie) {
     // 删除一个cookie
     cookie.setMaxAge(0);
     resp.addCookie(cookie);
}

那么maxAge设置为负值和0到底有什么区别呢?

maxAge设置为0表示立即删除该Cookie,如果在debug的模式下,执行上述方法,可以看见cookie立即被删除了。
在这里插入图片描述
maxAge设置为负数,能看到Expires属性改变了,但Cookie仍然会存在一段时间直到关闭浏览器或者重新打开浏览器。
在这里插入图片描述

修改或者删除Cookie

HttpServletResponse提供的Cookie操作只有一个addCookie(Cookie cookie),所以想要修改Cookie只能使用一个同名的Cookie来覆盖原先的Cookie。如果要删除某个Cookie,则只需要新建一个同名的Cookie,并将maxAge设置为0,并覆盖原来的Cookie即可。

新建的Cookie,除了value、maxAge之外的属性,比如name、path、domain都必须与原来的一致才能达到修改或者删除的效果。否则,浏览器将视为两个不同的Cookie不予覆盖。

值得注意的是,从客户端读取Cookie时,包括maxAge在内的其他属性都是不可读的,也不会被提交。浏览器提交Cookie时只会提交name和value属性,maxAge属性只被浏览器用来判断Cookie是否过期,而不能用服务端来判断。

在这里插入图片描述

我们无法在服务端通过cookie.getMaxAge()来判断该cookie是否过期,maxAge只是一个只读属性,值永远为-1。当cookie过期时,浏览器在与后台交互时会自动筛选过期cookie,过期了的cookie就不会被携带了。

Cookie的域名

Cookie是不可以跨域名的,隐私安全机制禁止网站非法获取其他网站的Cookie。

正常情况下,同一个一级域名下的两个二级域名也不能交互使用Cookie,比如test1.mcrwayfun.com和test2.mcrwayfun.com,因为二者的域名不完全相同。如果想要mcrwayfun.com名下的二级域名都可以使用该Cookie,需要设置Cookie的domain参数为.mcrwayfun.com,这样使用test1.mcrwayfun.com和test2.mcrwayfun.com就能访问同一个cookie

一级域名又称为顶级域名,一般由字符串+后缀组成。熟悉的一级域名有baidu.com,qq.com。com,cn,net等均是常见的后缀。
二级域名是在一级域名下衍生的,比如有个一级域名为mcrfun.com,则blog.mcrfun.com和www.mcrfun.com均是其衍生出来的二级域名。

5.1.1、使用

在这里插入图片描述

5.1.2、缺点

在这里插入图片描述

5.2、localStorage(手动清除)

// 增加一条localStorage
localStorage.setItem('myCat', 'Tom');
// 获取localStorage的一条数据
var cat = localStorage.getItem("myCat");
// 移除localStorage的一条数据
localStorage.removeItem("myCat");

建议使用try catch封装

5.3、sessionStorage(浏览器关闭自动清除)
// 增加一条sessionStorage
sessionStorage.setItem('myCat', 'Tom');
// 获取sessionStorage的一条数据
var cat = sessionStorage.getItem("myCat");
// 移除sessionStorage的一条数据
sessionStorage.removeItem("myCat");

建议使用try catch封装

5.4、区别

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值