AJAX  

用法

AJAX不是JavaScript的规范,它只是一个哥们“发明”的缩写:Asynchronous JavaScript and XML,意思就是用JavaScript执行异步网络请求
在现代浏览器上写AJAX主要依靠XMLHttpRequest对象:

  1. 'use strict';
  2. function success(text){
  3. var textarea = document.getElementById('test-response-text');
  4. textarea.value = text;
  5. }
  6. function fail(code){
  7. var textarea = document.getElementById('test-response-text');
  8. textarea.value ='Error code: '+ code;
  9. }
  10. var request =newXMLHttpRequest();// 新建XMLHttpRequest对象
  11. request.onreadystatechange =function(){// 状态发生变化时,函数被回调
  12. if(request.readyState ===4){// 成功完成
  13. // 判断响应结果:
  14. if(request.status ===200){
  15. // 成功,通过responseText拿到响应的文本:
  16. return success(request.responseText);
  17. }else{
  18. // 失败,根据响应码判断失败原因:
  19. return fail(request.status);
  20. }
  21. }else{
  22. // HTTP请求还在继续...
  23. }
  24. }
  25. // 发送请求:
  26. request.open('GET','/api/categories');
  27. request.send();
  28. alert('请求已发送,请等待响应...');

对于低版本的IE,需要换一个ActiveXObject对象:

  1. 'use strict';
  2. function success(text){
  3. var textarea = document.getElementById('test-ie-response-text');
  4. textarea.value = text;
  5. }
  6. function fail(code){
  7. var textarea = document.getElementById('test-ie-response-text');
  8. textarea.value ='Error code: '+ code;
  9. }
  10. var request =newActiveXObject('Microsoft.XMLHTTP');// 新建Microsoft.XMLHTTP对象
  11. request.onreadystatechange =function(){// 状态发生变化时,函数被回调
  12. if(request.readyState ===4){// 成功完成
  13. // 判断响应结果:
  14. if(request.status ===200){
  15. // 成功,通过responseText拿到响应的文本:
  16. return success(request.responseText);
  17. }else{
  18. // 失败,根据响应码判断失败原因:
  19. return fail(request.status);
  20. }
  21. }else{
  22. // HTTP请求还在继续...
  23. }
  24. }
  25. // 发送请求:
  26. request.open('GET','/api/categories');
  27. request.send();
  28. alert('请求已发送,请等待响应...');

如果你想把标准写法和IE写法混在一起,可以这么写:

  1. var request;
  2. if(window.XMLHttpRequest){
  3. request =newXMLHttpRequest();
  4. }else{
  5. request =newActiveXObject('Microsoft.XMLHTTP');
  6. }

通过检测window对象是否有XMLHttpRequest属性来确定浏览器是否支持标准的XMLHttpRequest。注意,不要根据浏览器的navigator.userAgent来检测浏览器是否支持某个JavaScript特性,一是因为这个字符串本身可以伪造,二是通过IE版本判断JavaScript特性将非常复杂。

当创建了XMLHttpRequest对象后,要先设置onreadystatechange的回调函数。在回调函数中,通常我们只需通过readyState === 4判断请求是否完成,如果已完成,再根据status === 200判断是否是一个成功的响应。

XMLHttpRequest对象的open()方法有3个参数,第一个参数指定是GET还是POST,第二个参数指定URL地址,第三个参数指定是否使用异步,默认是true,所以不用写。

注意,千万不要把第三个参数指定为false,否则浏览器将停止响应,直到AJAX请求完成。如果这个请求耗时10秒,那么10秒内你会发现浏览器处于“假死”状态。

最后调用send()方法才真正发送请求。GET请求不需要参数,POST请求需要把body部分以字符串或者FormData对象传进去。


安全限制

上面代码的URL使用的是相对路径。如果你把它改为'http://www.sina.com.cn/',再运行,肯定报错。在Chrome的控制台里,还可以看到错误信息。

这是因为浏览器的同源策略导致的。默认情况下,JavaScript在发送AJAX请求时,URL的域名必须和当前页面完全一致。

完全一致的意思是,域名要相同(www.example.com和example.com不同),协议要相同(http和https不同),端口号要相同(默认是:80端口,它和:8080就不同)。有的浏览器口子松一点,允许端口不同,大多数浏览器都会严格遵守这个限制。

那是不是用JavaScript无法请求外域(就是其他网站)的URL了呢?方法还是有的,大概有这么几种:

一是通过Flash插件发送HTTP请求,这种方式可以绕过浏览器的安全限制,但必须安装Flash,并且跟Flash交互。不过Flash用起来麻烦,而且现在用得也越来越少了。

二是通过在同源域名下架设一个代理服务器来转发,JavaScript负责把请求发送到代理服务器:

'/proxy?url=http://www.sina.com.cn'

代理服务器再把结果返回,这样就遵守了浏览器的同源策略。这种方式麻烦之处在于需要服务器端额外做开发。


JSONP

第三种方式称为JSONP,它有个限制,只能用GET请求,并且要求返回JavaScript。这种方式跨域实际上是利用了浏览器允许跨域引用JavaScript资源:

  1. <html>
  2. <head>
  3. <scriptsrc="http://example.com/abc.js"></script>
  4. ...
  5. </head>
  6. <body>
  7. ...
  8. </body>
  9. </html>

JSONP通常以函数调用的形式返回,例如,返回JavaScript内容如下:

  1. foo('data');

这样一来,我们如果在页面中先准备好foo()函数,然后给页面动态加一个<script>节点,相当于动态读取外域的JavaScript资源,最后就等着接收回调了。

以163的股票查询URL为例,对于URL:http://api.money.126.net/data/feed/0000001,1399001?callback=refreshPrice,你将得到如下返回:

refreshPrice({"0000001":{"code": "0000001", … });

因此我们需要首先在页面中准备好回调函数:

  1. function refreshPrice(data){
  2. var p = document.getElementById('test-jsonp');
  3. p.innerHTML ='当前价格:'+
  4. data['0000001'].name +': '+
  5. data['0000001'].price +';'+
  6. data['1399001'].name +': '+
  7. data['1399001'].price;
  8. }

最后用getPrice()函数触发:

  1. function getPrice(){
  2. var
  3. js = document.createElement('script'),
  4. head = document.getElementsByTagName('head')[0];
  5. js.src ='http://api.money.126.net/data/feed/0000001,1399001?callback=refreshPrice';
  6. head.appendChild(js);
  7. }

就完成了跨域加载数据。


CORS

如果浏览器支持HTML5,那么就可以一劳永逸地使用新的跨域策略:CORS了。

CORS全称Cross-Origin Resource Sharing,是HTML5规范定义的如何跨域访问资源。

了解CORS前,我们先搞明白概念:

Origin表示本域,也就是浏览器当前页面的域。当JavaScript向外域(如sina.com)发起请求后,浏览器收到响应后,首先检查Access-Control-Allow-Origin是否包含本域,如果是,则此次跨域请求成功,如果不是,则请求失败,JavaScript将无法获取到响应的任何数据。

用一个图来表示就是:

假设本域是my.com,外域是sina.com,只要响应头Access-Control-Allow-Origin为http://my.com,或者是*,本次请求就可以成功。

可见,跨域能否成功,取决于对方服务器是否愿意给你设置一个正确的Access-Control-Allow-Origin,决定权始终在对方手中。

上面这种跨域请求,称之为“简单请求”。简单请求包括GET、HEAD和POST(POST的Content-Type类型
仅限application/x-www-form-urlencoded、multipart/form-data和text/plain),并且不能出现任何自定义头(例如,X-Custom: 12345),通常能满足90%的需求。

无论你是否需要用JavaScript通过CORS跨域请求资源,你都要了解CORS的原理。最新的浏览器全面支持HTML5。在引用外域资源时,除了JavaScript和CSS外,都要验证CORS。例如,当你引用了某个第三方CDN上的字体文件时:

  1. /* CSS */
  2. @font-face {
  3. font-family:'FontAwesome';
  4. src: url('http://cdn.com/fonts/fontawesome.ttf') format('truetype');
  5. }

如果该CDN服务商未正确设置Access-Control-Allow-Origin,那么浏览器无法加载字体资源。

对于PUT、DELETE以及其他类型如application/json的POST请求,在发送AJAX请求之前,浏览器会先发送一个OPTIONS请求(称为preflighted请求)到这个URL上,询问目标服务器是否接受:

  1. OPTIONS /path/to/resource HTTP/1.1
  2. Host: bar.com
  3. Origin: http://my.com
  4. Access-Control-Request-Method: POST

服务器必须响应并明确指出允许的Method:

  1. HTTP/1.1 200 OK
  2. Access-Control-Allow-Origin: http://my.com
  3. Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS
  4. Access-Control-Max-Age: 86400

浏览器确认服务器响应的Access-Control-Allow-Methods头确实包含将要发送的AJAX请求的Method,才会继续发送AJAX,否则,抛出一个错误。

由于以POST、PUT方式传送JSON格式的数据在REST中很常见,所以要跨域正确处理POST和PUT请求,服务器端必须正确响应OPTIONS请求。


面向对象编程

创建对象

JavaScript对每个创建的对象都会设置一个原型,指向它的原型对象。

当我们用obj.xxx访问一个对象的属性时,JavaScript引擎先在当前对象上查找该属性,如果没有找到,就到其原型对象上找,如果还没有找到,就一直上溯到Object.prototype对象,最后,如果还没有找到,就只能返回undefined。

例如,创建一个Array对象:

  1. var arr =[1,2,3];

其原型链是:

arr —-> Array.prototype —-> Object.prototype —-> null

Array.prototype定义了indexOf()、shift()等方法,因此你可以在所有的Array对象上直接调用这些方法。
当我们创建一个函数时:

  1. function foo(){
  2. return0;
  3. }

函数也是一个对象,它的原型链是:

foo —-> Function.prototype —-> Object.prototype —-> null

由于Function.prototype定义了apply()等方法,因此,所有函数都可以调用apply()方法。

很容易想到,如果原型链很长,那么访问一个对象的属性就会因为花更多的时间查找而变得更慢,因此要注意不要把原型链搞得太长。


构造函数

除了直接用{ … }创建一个对象外,JavaScript还可以用一种构造函数的方法来创建对象。它的用法是,先定义一个构造函数:

  1. functionStudent(name){
  2. this.name = name;
  3. this.hello =function(){
  4. alert('Hello, '+this.name +'!');
  5. }
  6. }

你会问,咦,这不是一个普通函数吗?

这确实是一个普通函数,但是在JavaScript中,可以用关键字new来调用这个函数,并返回一个对象:

  1. var xiaoming =newStudent('小明');
  2. xiaoming.name;// '小明'
  3. xiaoming.hello();// Hello, 小明!

注意,如果不写new,这就是一个普通函数,它返回undefined。但是,如果写了new,它就变成了一个构造函数,它绑定的this指向新创建的对象,并默认返回this,也就是说,不需要在最后写return this;。

新创建的xiaoming的原型链是:

xiaoming —-> Student.prototype —-> Object.prototype —-> null

也就是说,xiaoming的原型指向函数Student的原型。如果你又创建了xiaohong、xiaojun,那么这些对象的原型与xiaoming是一样的:

  1. xiaoming ↘
  2. xiaohong -→ Student.prototype ----> Object.prototype ----> null
  3. xiaojun ↗

new Student()创建的对象还从原型上获得了一个constructor属性,它指向函数Student本身:

  1. xiaoming.constructor ===Student.prototype.constructor;// true
  2. Student.prototype.constructor ===Student;// true
  3. Object.getPrototypeOf(xiaoming)===Student.prototype;// true
  4. xiaoming instanceof Student;// true

看晕了吧?用一张图来表示这些乱七八糟的关系就是:

红色箭头是原型链。注意,Student.prototype指向的对象就是xiaoming、xiaohong的原型对象,这个原型对象自己还有个属性constructor,指向Student函数本身。

另外,函数Student恰好有个属性prototype指向xiaoming、xiaohong的原型对象,但是xiaoming、xiaohong这些对象可没有prototype这个属性,不过可以用__proto__这个非标准用法来查看。

现在我们就认为xiaoming、xiaohong这些对象“继承”自Student。

不过还有一个小问题,注意观察:

  1. xiaoming.name;// '小明'
  2. xiaohong.name;// '小红'
  3. xiaoming.hello;// function: Student.hello()
  4. xiaohong.hello;// function: Student.hello()
  5. xiaoming.hello === xiaohong.hello;// false

xiaoming和xiaohong各自的name不同,这是对的,否则我们无法区分谁是谁了。

xiaoming和xiaohong各自的hello是一个函数,但它们是两个不同的函数,虽然函数名称和代码都是相同的!

如果我们通过new Student()创建了很多对象,这些对象的hello函数实际上只需要共享同一个函数就可以了,这样可以节省很多内存。

要让创建的对象共享一个hello函数,根据对象的属性查找原则,我们只要把hello函数移动到xiaoming、xiaohong这些对象共同的原型上就可以了,也就是Student.prototype:

修改代码如下:

  1. functionStudent(name){
  2. this.name = name;
  3. }
  4. Student.prototype.hello =function(){
  5. alert('Hello, '+this.name +'!');
  6. };

用new创建基于原型的JavaScript的对象就是这么简单!

  • 忘记写new怎么办
    如果一个函数被定义为用于创建对象的构造函数,但是调用时忘记了写new怎么办?

在strict模式下,this.name = name将报错,因为this绑定为undefined,在非strict模式下,this.name = name不报错,因为this绑定为window,于是无意间创建了全局变量name,并且返回undefined,这个结果更糟糕。

所以,调用构造函数千万不要忘记写new。为了区分普通函数和构造函数,按照约定,构造函数首字母应当大写,而普通函数首字母应当小写,这样,一些语法检查工具如jslint将可以帮你检测到漏写的new。
最后,我们还可以编写一个createStudent()函数,在内部封装所有的new操作。一个常用的编程模式像这样:

  1. functionStudent(props){
  2. this.name = props.name ||'匿名';// 默认值为'匿名'
  3. this.grade = props.grade ||1;// 默认值为1
  4. }
  5. Student.prototype.hello =function(){
  6. alert('Hello, '+this.name +'!');
  7. };
  8. function createStudent(props){
  9. returnnewStudent(props ||{})
  10. }

这个createStudent()函数有几个巨大的优点:一是不需要new来调用,二是参数非常灵活,可以不传,也可以这么传:

  1. var xiaoming = createStudent({
  2. name:'小明'
  3. });
  4. xiaoming.grade;// 1

如果创建的对象有很多属性,我们只需要传递需要的某些属性,剩下的属性可以用默认值。由于参数是一个Object,我们无需记忆参数的顺序。如果恰好从JSON拿到了一个对象,就可以直接创建出xiaoming。


原型继承

在传统的基于Class的语言如Java、C++中,继承的本质是扩展一个已有的Class,并生成新的Subclass。

由于这类语言严格区分类和实例,继承实际上是类型的扩展。但是,JavaScript由于采用原型继承,我们无法直接扩展一个Class,因为根本不存在Class这种类型。

但是办法还是有的。我们先回顾Student构造函数:
···javascript
function Student(props) {
this.name = props.name || 'Unnamed';
}

Student.prototype.hello = function () {
alert('Hello, ' + this.name + '!');
}

  1. 以及Student的原型链:
  2. ![](http://www.liaoxuefeng.com/files/attachments/001439872136313496e60e07ed143bda40a0200b12d8cc3000/l)
  3. 现在,我们要基于Student扩展出PrimaryStudent,可以先定义出PrimaryStudent:
  4. ```javascript
  5. function PrimaryStudent(props) {
  6. // 调用Student构造函数,绑定this变量:
  7. Student.call(this, props);
  8. this.grade = props.grade || 1;
  9. }

但是,调用了Student构造函数不等于继承了Student,PrimaryStudent创建的对象的原型是:

new PrimaryStudent() —-> PrimaryStudent.prototype —-> Object.prototype —-> null

必须想办法把原型链修改为:

new PrimaryStudent() —-> PrimaryStudent.prototype —-> Student.prototype —-> Object.prototype —-> null

这样,原型链对了,继承关系就对了。新的基于PrimaryStudent创建的对象不但能调用PrimaryStudent.prototype定义的方法,也可以调用Student.prototype定义的方法。

如果你想用最简单粗暴的方法这么干:

  1. PrimaryStudent.prototype =Student.prototype;

是不行的!如果这样的话,PrimaryStudent和Student共享一个原型对象,那还要定义PrimaryStudent干啥?

我们必须借助一个中间对象来实现正确的原型链,这个中间对象的原型要指向Student.prototype。为了实现这一点,参考道爷(就是发明JSON的那个道格拉斯)的代码,中间对象可以用一个空函数F来实现:

  1. // PrimaryStudent构造函数:
  2. functionPrimaryStudent(props){
  3. Student.call(this, props);
  4. this.grade = props.grade ||1;
  5. }
  6. // 空函数F:
  7. function F(){
  8. }
  9. // 把F的原型指向Student.prototype:
  10. F.prototype =Student.prototype;
  11. // 把PrimaryStudent的原型指向一个新的F对象,F对象的原型正好指向Student.prototype:
  12. PrimaryStudent.prototype =new F();
  13. // 把PrimaryStudent原型的构造函数修复为PrimaryStudent:
  14. PrimaryStudent.prototype.constructor =PrimaryStudent;
  15. // 继续在PrimaryStudent原型(就是new F()对象)上定义方法:
  16. PrimaryStudent.prototype.getGrade =function(){
  17. returnthis.grade;
  18. };
  19. // 创建xiaoming:
  20. var xiaoming =newPrimaryStudent({
  21. name:'小明',
  22. grade:2
  23. });
  24. xiaoming.name;// '小明'
  25. xiaoming.grade;// 2
  26. // 验证原型:
  27. xiaoming.__proto__ ===PrimaryStudent.prototype;// true
  28. xiaoming.__proto__.__proto__ ===Student.prototype;// true
  29. // 验证继承关系:
  30. xiaoming instanceof PrimaryStudent;// true
  31. xiaoming instanceof Student;// true

用一张图来表示新的原型链:

注意,函数F仅用于桥接,我们仅创建了一个new F()实例,而且,没有改变原有的Student定义的原型链。

如果把继承这个动作用一个inherits()函数封装起来,还可以隐藏F的定义,并简化代码:

  1. function inherits(Child,Parent){
  2. var F =function(){};
  3. F.prototype =Parent.prototype;
  4. Child.prototype =new F();
  5. Child.prototype.constructor =Child;
  6. }

这个inherits()函数可以复用:

  1. functionStudent(props){
  2. this.name = props.name ||'Unnamed';
  3. }
  4. Student.prototype.hello =function(){
  5. alert('Hello, '+this.name +'!');
  6. }
  7. functionPrimaryStudent(props){
  8. Student.call(this, props);
  9. this.grade = props.grade ||1;
  10. }
  11. // 实现原型继承链:
  12. inherits(PrimaryStudent,Student);
  13. // 绑定其他方法到PrimaryStudent原型:
  14. PrimaryStudent.prototype.getGrade =function(){
  15. returnthis.grade;
  16. };

class继承

在上面的章节中我们看到了JavaScript的对象模型是基于原型实现的,特点是简单,缺点是理解起来比传统的类-实例模型要困难,最大的缺点是继承的实现需要编写大量代码,并且需要正确实现原型链。

有没有更简单的写法?有!

新的关键字class从ES6开始正式被引入到JavaScript中。class的目的就是让定义类更简单。

我们先回顾用函数实现Student的方法:

  1. functionStudent(name){
  2. this.name = name;
  3. }
  4. Student.prototype.hello =function(){
  5. alert('Hello, '+this.name +'!');
  6. }

如果用新的class关键字来编写Student,可以这样写:

  1. classStudent{
  2. constructor(name){
  3. this.name = name;
  4. }
  5. hello(){
  6. alert('Hello, '+this.name +'!');
  7. }
  8. }

比较一下就可以发现,class的定义包含了构造函数constructor和定义在原型对象上的函数hello()(注意没有function关键字),这样就避免了Student.prototype.hello = function () {…}这样分散的代码。

最后,创建一个Student对象代码和前面章节完全一样:

  1. var xiaoming =newStudent('小明');
  2. xiaoming.hello();
  • class继承
    用class定义对象的另一个巨大的好处是继承更方便了。想一想我们从Student派生一个PrimaryStudent需要编写的代码量。现在,原型继承的中间对象,原型对象的构造函数等等都不需要考虑了,直接通过extends来实现:
  1. classPrimaryStudent extends Student{
  2. constructor(name, grade){
  3. super(name);// 记得用super调用父类的构造方法!
  4. this.grade = grade;
  5. }
  6. myGrade(){
  7. alert('I am at grade '+this.grade);
  8. }
  9. }

注意PrimaryStudent的定义也是class关键字实现的,而extends则表示原型链对象来自Student。子类的构造函数可能会与父类不太相同,例如,PrimaryStudent需要name和grade两个参数,并且需要通过super(name)来调用父类的构造函数,否则父类的name属性无法正常初始化。

PrimaryStudent已经自动获得了父类Student的hello方法,我们又在子类中定义了新的myGrade方法。

ES6引入的class和原有的JavaScript原型继承有什么区别呢?实际上它们没有任何区别,class的作用就是让JavaScript引擎去实现原来需要我们自己编写的原型链代码。简而言之,用class的好处就是极大地简化了原型链代码。

你一定会问,class这么好用,能不能现在就用上?

现在用还早了点,因为不是所有的主流浏览器都支持ES6的class。如果一定要现在就用上,就需要一个工具把class代码转换为传统的prototype代码,可以试试Babel这个工具。  

摘抄来源:http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000


js学习笔记知识点的更多相关文章

  1. 一点感悟:《Node.js学习笔记》star数突破1000+

    写作背景 笔者前年开始撰写的<Node.js学习笔记> github star 数突破了1000,算是个里程碑吧. 从第一次提交(2016.11.03)到现在,1年半过去了.突然有些感慨, ...

  2. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  3. Vue.js学习笔记(2)vue-router

    vue中vue-router的使用:

  4. JS 学习笔记--9---变量-作用域-内存相关

    JS 中变量和其它语言中变量最大的区别就是,JS 是松散型语言,决定了它只是在某一个特定时间保存某一特定的值的一个名字而已.由于在定义变量的时候不需要显示规定必须保存某种类型的值,故变量的值以及保存的 ...

  5. WebGL three.js学习笔记 使用粒子系统模拟时空隧道(虫洞)

    WebGL three.js学习笔记 使用粒子系统模拟时空隧道 本例的运行结果如图: 时空隧道demo演示 Demo地址:https://nsytsqdtn.github.io/demo/sprite ...

  6. WebGL three.js学习笔记 法向量网格材质MeshNormalMaterial的介绍和创建360度全景天空盒的方法

    WebGL学习----Three.js学习笔记(5) 点击查看demo演示 Demo地址:https://nsytsqdtn.github.io/demo/360/360 简单网格材质 MeshNor ...

  7. WebGL three.js学习笔记 创建three.js代码的基本框架

    WebGL学习----Three.js学习笔记(1) webgl介绍 WebGL是一种3D绘图协议,它把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的 ...

  8. vue.js 学习笔记3——TypeScript

    目录 vue.js 学习笔记3--TypeScript 工具 基础类型 数组 元组 枚举 字面量 接口 类类型 类类型要素 函数 函数参数 this对象和类型 重载 迭代器 Symbol.iterat ...

  9. 2019-4-29 js学习笔记

    js学习笔记一:js数据类型   1:基本数据类型       number类型(整数,小数)      String类型          boolean类型        NaN类型其实是一个nu ...

随机推荐

  1. codeforces570D Tree Requests

    题目链接:codeforces570D 正解:$dsu$ $on$ $tree$ 解题报告: 考虑这又是一类子树内的不带修改统计问题,直接上$dsu$ $on$ $tree$好咯. 直接按上一道题的做 ...

  2. ELK 6.x 部署

    Elasticsearch版本:6.3.2 Kibana版本:6.3.2 1.es安装 按照官方提示操作即可. 通过yum安装或者下载tar包解压. 安装完成之后,需要修改一些配置 ①修改文件 /et ...

  3. Codeforces gym 100971 D. Laying Cables 单调栈

    D. Laying Cables time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  4. poj 2229 Sumsets 完全背包求方案总数

    Sumsets Description Farmer John commanded his cows to search for different sets of numbers that sum ...

  5. Linux安装jdk、删除Open jdk

    1.将jdk解压安装完成后,在bin目录下查看当前jdk的版本号 命令: ./java -version 2.编辑修改配置 1. 修改profile文件 进入命令:   vi  /etc/profil ...

  6. 常见HTTP状态(304,)

    一.1XX(临时响应) 表示临时响应并需要请求者继续执行操作的状态码. 100(继续) 请求者应当继续提出请求.服务器返回此代码表示:已经收到请求的第一部分,正在等待其余部分. 101(切换协议) 请 ...

  7. SPA(单页面web应用程序)

    单页web应用(single page web application,SPA),就是只有一张web页面的应用,是加载单个HTML页面并在用户与应用程序交互时动态更新该页面的web应用程序. 浏览器一 ...

  8. winform无边框窗体点击任务栏最小化

    protected override CreateParams CreateParams { get { const int WS_MINIMIZEBOX = 0x00020000; // Winus ...

  9. ECMAScript 5中对Array中新增了9个方法

    ECMAScript 5中对Array中新增了9个方法: 5个迭代方法(循环操作数组中的各个项):forEach(),map(),filter(),every()和some() 2个归并方法(迭代数组 ...

  10. Neutron三层网络服务实现原理

    Neutron 对虚拟三层网络的实现是通过其 L3 Agent (neutron-l3-agent).该 Agent 利用 Linux IP 栈.route 和 iptables 来实现内网内不同网络 ...