HTTP
-
HTTP 报文结构是怎样的?
-
HTTP有哪些请求方法?
-
GET 和 POST 有什么区别?
-
如何理解 URI?
-
如何理解 HTTP 状态码?
-
简要概括一下 HTTP 的特点?HTTP 有哪些缺点?
-
对 Accept 系列字段了解多少?
-
对于定长和不定长的数据,HTTP 是怎么传输的?
-
HTTP 如何处理大文件的传输?
-
HTTP 中如何处理表单数据的提交?
-
HTTP1.1 如何解决 HTTP 的队头阻塞问题?
-
对 Cookie 了解多少?
-
如何理解 HTTP 代理?
-
如何理解 HTTP 缓存及缓存代理?
-
为什么产生代理缓存?
-
源服务器的缓存控制
-
客户端的缓存控制
-
什么是跨域?浏览器如何拦截响应?如何解决?
改变this指向
var obj1={
name: ‘dada’
};
var obj2={
name: ‘da’
};
window.name = ‘window’;
var getName = function(){
console.log ( this.name );
};
getName(); // 输出: window
getName.call( obj1 );// 输出: dada
getName.call(obj2 ); // 输出: da
document.getElementById( ‘div1’ ).onclick = function(){
console.log( this.id );// 输出: div1
var func = function(){
console.log ( this.id );// 输出: undefined
}
func();
};
//修正后
document.getElementById( ‘div1’ ).onclick = function(){
var func = function(){
console.log ( this.id );// 输出: div1
}
func.call(this);
};
工厂模式,创建方式
function createPerson(name,age,job){
var o = new Object();
o.name=name;
o.age=age;
o.job=job;
o.sayName = function(){
alert(this.name);
}
}
var person1 = createPerson(“da”,1,“it”);
var person2 = createPerson(“dada”,2,“it”);
构造函数模式
function Person(name,age,ob){
this.name=name;
this.age=age;
this.job=job;
this.sayName = function(){
alert(this.name);
}
var person1 = new Person(“dada”,1,“web”);
var person2 = new Person(“dada”,2,“web”);
}
使用原型模式:
function Person(){
}
Person.prototype.name = “da”;
Person.prototype.age = 1;
Person.prototype.job = “web”;
Person.prototype.sayName = function(){
alert(this.name);
}
var person1 = new Person();
person1.sayName(); //“dada”
var person2 = new Person();
person2.sayName(); //“dada”
alert(person1.sayName == person2.sayName); //true
组合使用构造函数模式和原型模式
function Person(name,age){
this.name = name;
this.age = age;
this.friends = [“da”,“dada”];
}
Person.prototype = {
constructor:Person,
sayName:function(){
alert(this.name);
}
}
var person1 = new Person(“da1”,1);
var person2 = new Person(“da2”,2);
person1.friends.push(“dadada”);
console.log(person1.friends); //[“da”,“dada”,“dadada”]
console.log(person2.friends); //[“da”,“dada”]
console.log(person1.friends === person2.friends); //false
console.log(person1.sayName === person2.sayName); //true
动态原型模式
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
if(typeof this.sayName!=“function”){
Person.prototype.sayName=function(){
alert(this.name);
};
}
}
JavaScript对象的创建方式,1,Object构造函数式,2,对象字面量式,3,工厂模式,4,安全工厂模式,5,构造函数模式,6,原型模式,7,混合构造函数和原型模式,8,动态原型模式,9,寄生构造函数模式,10,稳妥构造函数模式。
学习使用异步很重要,在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应,最好的例子是ajax操作。
简单的promise对象的构造函数的结构:
var Promise = function() {
this.callbacks = []; // 用于管理回调函数
}
Promise.prototype = {
construct: Promise,
resolve: function(result) { // 请求成功时执行的方法
},
reject: function(result) { // 请求失败时执行的方法
},
complete: function(type, result) { // 执行回调
},
then: function(successHandler, failedHandler) { // 绑定回调函数
}
}
对于回调函数,好处是简单,容易理解,但是缺点在于代码的阅读和维护,各个部分之间高度耦合,流程也会很乱,每个任务只能指定一个回调函数,称之为:回调地狱。
// 同步操作变成异步操作
f1();
f2();
function f1(callback) {
setTimeout(function() {
callback();
},1000);
}
f1(f2);
事件监听(采用事件驱动模式,任务的执行不取决于代码的顺序,而取决于某个事件是否发生)示例如下:
$(‘#clickBtn’).on(‘click’,function(e){console.log(‘xxx’);}
f1.on(‘dada’, f2);
function f1() {
setTimeout(function() {
f1.trigger(‘dada’);
},1000);
}
// f1.trigger(‘dada’)表示执行完成后,立即触发dada事件,然后开始执行f2
对于事件监听,可绑定多个事件,而且每个事件可以指定多个回调函数,可以“去耦合”,有利于实现模块化,缺点就是整个程序都要编程事件驱动型,运行流程会变得很不清晰。
对于采用发布,订阅方式,和“事件监听”类似。(发布/订阅)
对于使用Promise对象实现,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。
同源策略的目的是为了防止某个文档或脚本从多个不同源装载,同源策略是指,协议,域名,端口相同。同源策略是一种安全协议,指一段脚本只能读取来自同一来源的窗口和文档的属性。
有同源限制可以放置黑客盗取信息。
函数是第一类对象:
这些函数可以作为参数传递给其他函数,作为其他函数的值返回,分配给变量,也可以存储在数据结构中。
如果公民分等级,一等公民什么都可以做,次等公民这不能做那不能做。JavaScript的函数也是对象,可以有属性,可以赋值给一个变量,可以放在数组里作为元素,可以作为其他对象的属性,什么都可以做,别的对象能做的它能做,别的对象不能做的它也能做。这不就是一等公民的地位嘛。
函数声明:
foo(); // 在函数声明之后调用 foo,可以正常调用。因为 foo 被提前到最前面定义了。
function foo() {
return true;
}
调用:
函数名(参数)
函数名.call(函数名,参数)
函数名.apply(函数名,[参数])
new 函数名(参数)
定时器
把函数声明变成函数表达式再调用
ES6里的模版字符串
函数表达式:
foo(); // 在函数表达式之前调用函数,报错。因为这时候还没有 foo 这个变量。
var foo = function() {
return foo;
};
调用
函数名(参数)
函数名.call(函数名,参数)
函数名.apply(函数名,[参数])
new 函数名(参数)
直接在后面加上一对小括号
定时器
ES6里的模版字符串
以被赋值的形式出现(根据具体形式调用)
在向执行环境中加载数据时,解析器对函数声明和函数表达式不一样的,解析器首先读取读取函数声明,并使它在执行任何代码之前可用,对于函数表达式,就需要等到解析器执行到它所在的代码行。
JavaScript解释器中存在一种变量声明被提升的机制,也就是说函数声明会被提升到作用域的最前面,即使写代码的时候是写在最后面,也还是会被提升至最前面。
var getName // 变量被提升,此时为undefined
getName() // dada 函数被提升
var getName = function() {
console.log(‘da’)
}
// 函数表达式此时才开始覆盖函数声明的定义
getName() // da
function getName() {
console.log(‘dada’)
}
getName() // da
在JavaScript中定义一个函数有四种方式
-
函数声明
-
函数表达式
-
ES6里箭头函数
-
new Function()
-
ES5 规定,函数只能在顶级作用域和函数作用域中声明,否则是不合法的。
-
ES6 引入了块级作用域的概念,这种定义方法就被允许了。
代码如下:
document.cookie = ‘user=jeskson;expires=’+new Date(0);
一个英文字符 占用一个字节,一个中文 字符占用两个字节
function byte(str) {
var bytes = str.length;
for(var i=0; i<bytes; i++) {
if(str.charCodeAt(i)>255) {
bytes++;
}
}
return bytes
}
console.log(byte(‘dada’));
attribute是dom元素在文档中作为HTML标签拥有的属性,property就是dom元素在JavaScript中作为对象拥有的属性。
attribute特性,property属性。
默认情况下,在页面加载期间,HTML 代码的解析将暂停,知道脚本停止执行。如果服务器速度较慢或者脚本特别沉重,会导致网页延迟,在使用Deferred时,脚本会延迟执行直到HTML解析器运行。这减少了网页加载时间,并且它们的显示速度更快。
function outer() {
var a = ‘变量1’
var inner = function() {
console.info(a);
}
return inner; // inner就是一个闭包函数,因为它能访问到outer函数的作用域
}
在JavaScript中的一大特点就是闭包,很多高级应用都要依靠闭包来实现。由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大的,所以不要乱滥用闭包,否则会导致页面的性能问题,在IE中可能会导致内存泄漏,所以可以在退回函数前,将不使用的局部变量全部删除。
-
instanceof关键字,判断一个对象是否是类的实例化对象
-
constructor属性,判断一个对象是否是类的构造函数
27. 你知道有个函数,执行直接对象查找时,它始终不会查找原型,这是什么函数
hasOwnProperty
28. document.write和innerHTML的区别
-
document.write会重绘整个页面
-
innerHTML可以重绘页面的一部分
效果动态图:
按鈕
按钮
读取服务器中的文件内容
function readAjaxFile(url) {
// 创建xhr
var xhr = new XMLHttpRequest();
// 监听状态
xhr.onreadystatechange = function() {
// 监听状态值
if(xhr.readyState === 1 && xhr.status === 200) {
console.log(xhr.responseTest)
}
}
// 打开请求
xhr.open(‘GET’, url, true)
// 发送数据
xhr.send(null)
}
读取本地计算机中的内容
function readInputFile(id) {
var file = document.getElementById(id).files[0];
// 实例化
var reader = new FileReader();
// 读取文件
reader.readAsText(file)
// 监听返回
reader.onload = function(data) {
console.log(data, this.result);
}
}
document.form.action = ‘submit’;
-
不要在同一行声明多个变量
-
使用对象字面量替代new Array这种形式
-
不要使用全局函数
-
switch语句必须带有default分支
-
函数不应该有时有返回值,有时没有返回值
-
for循环必须使用大括号括起来
-
if语句必须使用大括号括起来
-
写注释
-
命名规则,构造器函数首字母大写
eval的功能是把对应的字符串解析成JavaScript代码并运行。但是应该避免使用eval,使用它可能会造成程序不安全,影响性能因要一次解析成JavaScript语句,一次执行。
[“1”,“2”,“3”].map(parseInt)
1
[1,NaN,NaN]
因parseInt需要两个参数val,radix,其中radix表示解析时用的基数,map传递了3个参数item, index, array,对应的radix不合法导致解析失败。
this指的是调用函数的那个对象,一般情况下,this是全局对象Global,可以作为方法调用。this随着函数的使用场合的不同,this的值会发生变化。
this是谁调用就指向谁,在全局环境里,指向的是window对象。
var name = ‘jeskson’;
function person() {
return this.name;
}
console.log(this.name); // jeskson
console.log(window.name); // jeskson
console.log(person()); // jeskson
12345678
局部环境:
var name = “jeskson”;
function person() {
console.log(this.name);
}
person(); // jeskson
var obj = {
name: “dada”,
person: function() {
console.log(this.name);
}
}
obj.person(); // dada
构造函数内使用this
function Person(name) {
this.name = name;
return name;
}
console.log(new Person(‘jeskson’).name); // jeskson
12345
使用apply和call函数改变this的指向
function person() {
return this.name;
}
var obj = {
name: ‘jeskson’
}
console.log(person.call(obj)); // jeskson
console.log(person.apply(obj)); // jeskson
对象函数调用,哪个对象调用就指向哪个对象
使用new实例化对象,在构造函数中的this指向实例化对象
var show = function() {
this.myName=“jeskson”; /// this指向的是obj对象
}
var obj = new show();
35. 在JavaScript中什么是类(伪)数组,如何将类(伪)数组转换为标准数组
-
典型的类(伪)数组是函数的argument参数,在调用
getElementsByTagName
和document.childNodes
方法时,它们返回的NodeList
对象都属于伪数组。 -
可以使用
Array.prototype.slice.call(fakeArray)
将数组转化为真正的Array对象。
什么是伪数组,是能通过Array.prototype.slice
转换为真正的数组的带有length
属性的对象。
// 标准的有伪数组对象
var da = { 0: ‘a’, 1: ‘b’, length: 2};
var dada = Array.prototype.slice.call(da);
console.log(da[0]); // a
var dadada = [].slice.call(dada);
console.log(da[0]); // a
伪数组:就是无法使用数组的方法和api,但任然可以使用便利数组的方式遍历他们。
一个伪数组Array.prototype.slice.call()
进行转换为一个真正的数组
36. JavaScript中的callee和caller的作用是什么
-
caller返回一个关于函数的引用,该函数调用了当前函数
-
callee返回正在执行的函数,也就是指定的function对象的正文
caller是JavaScript函数类型的一个属性,它引用调用当前函数的函数; callee则不是函数对象的属性,它是函数上下文中arguments对象的属性。
aaaabbbccccddhgddada
function dealStr(str) {
var obj = {};
for(var i = 0; i<str.length; i++){
var v = str.charAt(i);
if(obj[v] && obj[v].value === v) {
++obj[v].count
}else{
obj[v] = {
count: 1,
value: v
}
}
}
return obj;
}
var obj = dealStr(str);
for(key in obj) {
console.log(obj[key].value+‘=’+obj[key].count);
}
function trim(str) {
if (str && typeof str === “string”) {
return str.replace(/(^\s*)|(\s*)$/g,“”); //去除前后空白符
}
}
12345
for循环数组
var arr3 = [];
// 遍历arr1
for (var i = 0; i < arr1.length; i++) {
arr3.push(arr1[i]);
}
// 遍历arr2
for (var j = 0; j < arr2.length; j++) {
arr3.push(arr2[j]);
}
console.log(arr3); // [1,2,3,4,5,6]
concat()方法:concat()方法,作用是连接两个或更多的数组,并返回一个新的数组。
var arr3 = arr1.concat(arr2);
console.log(arr3); // [1,2,3,4,5,6]
apply()方法
arr1.push.apply(arr1, arr2);
-
&&
运算符 -
||
运算符 -
!
运算符
事件代理,又称为事件委托,就是把原本需要绑定的事件委托给父元素,让父元素负责事件监听,事件代理的原理是DOM元素的事件冒泡,使用事件代理的好处是提高性能。
- 未声明的变量出现中不存在且未声明的变量。如果程序尝试读取未声明变量的值,则会遇到运行时错误。
xxx is not defined
- 未定义的变量是在程序中声明但尚未给出任何值的变量。如果程序尝试读取未定义变量的值,则返回未定义的值。
已经通过var指令声明,但是没有赋值,没有定义类型,所以会打印undefined
未定义
43. 什么是全局变量,这些变量如何声明,使用全局变量有哪些问题
全家变量是整个代码中都可用的变量,这些变量没有任何作用域。var关键字用于声明局部变量或对象,如果省略var关键字,则声明一个全局变量。
使用全局变量所面临的问题是局部变量和全局变量名称的冲突,很难调试和测试依赖于全局变量的代码。
-
setTimeout(function,delay)
函数用于启动在所属延迟之后调用特定功能的定时器。 -
setInterval(function,delay)
函数用于在提到的延迟中重复执行给定的功能,只有在取消时才停止。 -
clearInterval(id)
函数指示定时器停止。
45. 说说ViewState和SessionState有什么区别
-
ViewState用于会话中的页面
-
SessionState用于Web应用程序中的所有页面上访问的用户特定数据
===为严格等式运算符,只有当两个操作数具有相同的值和类型时,,才会返回
true
for, while, do…while, for_in, for of (es6新增)
while(条件表达式语句)
{
执行语句块;
}
do
{
执行语句块;
}
while(条件表达式语句);
for(初始化表达式;循环条件表达式;循环后的操作表达式)
{
执行语句块;
}
- null 用于表示无值或无对象,表示没有对象或空字符串,没有有效的布尔值,没有数值和数组对象。
- delete操作符用于删除对象中的某个属性,但是不能删除变量,函数等。
var obj = {
name: ‘jeskson’
}
console.log(obj.name);//‘jeskson’
delete obj.name;
console.log(obj.name);//undefined
alert, confirm, prompt
其作用是用于防止页面刷新,并在调用时传递参数“0”;用于调用另一种方法而不刷新页面
cookie是一些数据,存储你电脑上的文本文件中,当web服务器向浏览器发送web页面时,在连接关闭后,服务端不会记录用户的信息。
Cookie的形式,Cookie是由name=value形式成对存在的,Cookie字符串必须以分号作为结束符,Cookie除了name属性之外还存在其他4个相关属性。
设置Cookie的语法如下: set-Cookie:name=value;[expires=date];[path=dir];[domain=domainn];[secure]
pop()
方法将最后一个元素从给定的数组中取出并返回
var da = [ 1, 2, 3];
da.pop();
// da: [1,2]
54. 在JavaScript中,datatypes的两个基本组是什么
datatypes
的两个基本组是 原始类型和引用类型。
typeof是一个运算符,用于返回变量类型的字符串描述。
push方法是将一个或多个元素添加或附加到数组的末尾。
57. 在JavaScript中,unshift方法的作用是什么
unshift方法是将一个或多个元素添加到数组的开头。
为对象添加属性的方法,常用两种:
-
中括号语法
-
点语法
59. 说说window.onload和onDocumentReady
在将页面加载到浏览器中时,这两个功能都可以用来执行任务,但是它们在执行方式和执行时间方面存在细微的差异。
当浏览器加载DOM树和所有其他资源(例如图像,对象等)时,“ window.onload
”将执行代码。
onDocumentReady
在构建DOM树时执行,而无需等待其他资源加载。这样可以使用onDocumentReady
更快地针对DOM执行代码。
另一个区别是window.onload
与跨浏览器不兼容,而使用类似jQuery的document.ready()
则可以在所有浏览器上很好地工作。
用于循环对象的属性:
for (var item in object
被声明为没有任何命名标识符的函数,一般来说,匿名函数在声明后无法访问。
var da = function() {
console.log(‘dadaqianduan.cn’)
}
da();
单击子级的处理程序,父级的处理程序也将执行同样的工作。
对事件冒泡机制的理解?
事件流的执行顺序,捕获阶段-》目标阶段-》冒泡阶段。冒泡从里到外的执行。<div><span>点我</span></div>,
在div上定义的事件,点击span的时候会触发span上面绑定的事件
,之后也会触发外面div上面的事件,这就是冒泡。
冒泡阶段是从目标到window
对象的过程。事件默认是冒泡的,当父元素添加监听事件,点击子元素后,父元素上的事件会被触发,这就是典型的冒泡。
63. JavaScript里函数参数arguments是数组吗
它只是一个类数组对象,并没有数组的方法。
构造函数是用来创建对象时初始化对象,与new一起试用,创建对象的语句中构造函数的名称必须与类名完全相同。
-
构造函数只能由new关键字调用
-
构造函数可以创建实例化对象
-
构造函数是类的标志
-
split()
方法是用来切割成数组的形式 -
join()
方法是将数组转换成字符串
“abcdef”.split(“”) // [“a”, “b”, “c”, “d”, “e”, “f”]
“abcdef”.split() // [“abcdef”]
“2:3:4:5”.split(“:”,3) // [“2”, “3”, “4”]
[1,2,3,4,5].join() // “1,2,3,4,5”
[1,2,3,4,5].join(‘:’) // “1:2:3:4:5”
123456
JavaScript
的每个对象都继承另一个父级对象,父级对象称为原型(prototype)
对象。
原型链几乎是前端面试的必问题目
每一个实例对象都有一个私有属性__proto__
指向其构造函数的原型对象prototype
,该原型对象也会作为实例对象有一个私有属性__proto__
,层层向上直到一个对象的原型对象值为null
。
当访问一个对象的属性或方法时,js
引擎会先查找该对象本身是否包含,如果没有,会去该对象的__proto__
属性所指向的原型对象上找,如果没有,会继续向上一层找,直到某个对象的__proto__
值为null
,这就是原型链。
在js中,每个构造函数都有一个prototype属性,指向另外一个对象,说明整个对象所有的属性和方法都会被构造函数所拥有。
function Person (name, age) {
this.name = name
this.age = age
}
console.log(Person.prototype)
Person.prototype.type = ‘it’
Person.prototype.sayName = function () {
console.log(this.name)
}
var p1 = new Person(‘jeskson’, 18);
var p2 = new Person(‘dada’, 18);
console.log(p1.sayName === p2.sayName) // => true
构造函数Person:
function Person() {}
–> 原型属性(prototype) 神秘的对象Person.prototype
–> 由构造函数创建 Person实例 --> proto 原型对象 --> 神秘对象
任何一个构造函数都有一个prototype
属性,该属性是一个objec
t对象。
构造函数的prototype对象都有一个默认的constructor
属性,指向prototype
对象所在函数。
通过构造函数得到的实例对象内部会包含一个指向构造函数的 prototype
对象的指针 __proto__
console.log(obj.proto);
console.log(obj.prototype);
console.log(obj.proto === Object.prototype);
-
构造函数(prototype)指向原型
-
构造函数,New实例化(实例对象),实例对象中(.constructor)指向构造函数
-
实例对象
(.__proto__)
指向原型 -
实例对象.proto===原型
-
原型.constructor===构造函数
-
构造函数.prototype===原型
typeof 是一个一元运算,它返回值是一个字符串,该字符串说明运算数的类型。
instanceof,判断该对象是谁的实例
instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的prototype属性,instanceof只能用来判断对象和函数,不能用来判断字符串和数字
function getDataType(obj) {
if (obj === null) {
return “null”;
} else if (typeof obj === “object”) {
if (obj instanceof Array) {
return “array”;
} else {
return “object”;
}
} else {
return typeof obj;
}
}
事件流是指从 页面中接收事件的顺序。
指不太具体的元素更早地接收到事件,而最具体的节点最后接收到事件。
它就是一个通过函数指针调用的函数。
自执行函数是指声明的一个匿名函数,可以立即调用整个匿名函数,一般用于框架,插件等场景,好处在于避免各种JavaScript库的冲突,隔离作用域,避免污染。
事件委托是利用冒泡的原理,把事件加到父级上,触发执行效果。好处在于,减少事件数量,提高性能,避免内存外泄。
在 JavaScript 中,数据类型的转换有:隐式类型转换和强制类型转换(也叫显式类型转换)两种方式。
隐式类型转换:
== 只做值的判断,实际隐式转换了类型,然后才进行的比较
强制类型转换:
parseInt() 将字符串强类型制转换为数字整数类型
parseFloat() 将字符串类型转换为浮点类型
Number() 只能将纯数字的字符转换为数字
74. NaN是什么,它的类型是什么,如何可靠地判断一个值是否等于NaN
NaN
表示“不是数字”,但是它的类型是Number
,NaN和任何内容比较,甚至是自己,结果都是false.
广义跨域就是指跨域访问,简单来说就是 A 网站的 javascript 代码试图访问 B 网站,包括提交容和获取内容容。由于安全原因,跨域访问是被各大浏览器所默认禁止的。
跨域是指不同域名之间的相互访问。
76. 以YYYY-MM-DD的方式,输出当天的日期,比如当天是2020年1月1日,则输出2020-01-01
var d = new Date();
var year = d.getFullYear();
var month = d.getMonth() + 1;
month = month < 10 ? “0” + month : month;
var day = d.getDate();
daty = day<10? “0”+day : day;
console.log(year+‘-’+month+‘-’+day);
77. 用JavaScript随机选取10到100之间的10个数字,把它们存入一个数组中并排序
var isArray = [];
function getRandom(start, end) {
return Math.floor(Math.random() * (end-start+1) + start)
}
for(var i = 0; i<10; i++){
isArray.push(getRandom(10,100))
}
isArray.sort()
console.log(isArray)
78. 为了实现一个函数clonoe,可以对JavaScript中5种主要的数据类型(Number,String,Object,Array,Boolean)进行值(深)复制。
function clone(obj) {
var buf;
if(obj instanceof Array) {
var i = obj.lenght;
buf = [];
while(i–) {
buf[i] = clone(obj[i])
}
return buf;
}else if(obj instanceof Object) {
buf = {};
for(var i in obj) {
buf[i] = clone(obj[i])
}
return buf;
}else{
return buf = obj;
}
}
function noRepeat(arr) {
var i = 0,
len = arr.length,
obj = {},
HTTP
-
HTTP 报文结构是怎样的?
-
HTTP有哪些请求方法?
-
GET 和 POST 有什么区别?
-
如何理解 URI?
-
如何理解 HTTP 状态码?
-
简要概括一下 HTTP 的特点?HTTP 有哪些缺点?
-
对 Accept 系列字段了解多少?
-
对于定长和不定长的数据,HTTP 是怎么传输的?
-
HTTP 如何处理大文件的传输?
-
HTTP 中如何处理表单数据的提交?
-
HTTP1.1 如何解决 HTTP 的队头阻塞问题?
-
对 Cookie 了解多少?
-
如何理解 HTTP 代理?
-
如何理解 HTTP 缓存及缓存代理?
-
为什么产生代理缓存?
-
源服务器的缓存控制
-
客户端的缓存控制
-
什么是跨域?浏览器如何拦截响应?如何解决?