JiM-W

keep Moving


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

AMD and CMD

发表于 2016-09-10 | 分类于 javascript requirejs

CMD([Common Module Definition]) AMD

SeaJS 遵循 CMD 规范,RequireJS 遵循 AMD 规范。

CMD 模块依赖声明方式:

1
2
3
4
define(function (require) {
var a = require('./a');
var b = require('./b');
})

CMD 规范的弊端

  1. 不能直接压缩:require是局部变量,意味着不能直接的通过压缩工具进行压缩,若require这个变量被替换,加载器与自动化工具将无法获取模块的依赖。
  2. 模块书写有额外约定:路径参数不能进行字符串运算,不能使用变量代替,否则加载器与自动化工具无法正确提取路径。

AMD 模块依赖声明方式:

1
2
3
define(['./a', './b'], function (a, b) {
// more code ..
})

AMD 规范的弊端

  1. 依赖提前声明在代码书写上不是那么友好
  2. 模块内部与 NodeJS 的 Modules 有一定的差异

其实无论是 CMD 还是 AMD 的异步模块,都无法与同步模块规范保持一致(NodeJS 的 Modules),
只有谁比谁更像同步模块而已。AMD 要转换为同步模块,除了去掉define函数的包裹外,
需要在头部使用require把依赖声明好,而 CMD 只需要去掉define函数的包裹即可。

require js

发表于 2016-09-10 | 分类于 javascript

1 函数调用的复杂性,在一个命名空间的概念下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//命名空间的概念下
var M = M || {};
M.m = M.m || {};//||找true运算,undefined返回false
M.m.module1 = (function(){
// some code here
return {
func1:function(){},
func2:function(){}
}
})();
M.m.module2 = (function(){
// some code here
return {
func1:function(){},
func2:function(){}
}
})();
//调用每个模块下面的方法,如果M 和 m更加长,那么调用起来是不是废了老劲了
M.m.module1.func1();
M.m.module1.func2();
M.m.module2.func1();
M.m.module2.func2();

2 导入一个公共接口,本着面向对象的思想在进行简化 对外开发一个接口 www.myexcute.com

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//导入一个接口,就像导入jQuery一样
(function($,module1){
//some code here
//jQuery的所有方法可以使用
//$.extend
//M.m.module1 接口所有的方法可以用
module1.func1();//这种调用的方式比起上面的调用是不简化了不少
module1.func2();
})(jQuery, M.m.module1);
(function($,module2){
//some code here
//jQuery的所有方法可以使用
//$.extend
//M.m.module1 接口所有的方法可以用
module2.func1();
module2.func2();
})(jQuery, M.m.module2);

虽然这个样子,代码冲突的可能性已经很小,但是代码依赖的问题,多脚本的管理、阻塞的问题,仍旧无法解决

3 此时require.js便初露头角

简单地说,有两点,一、模块作用域自成一体,不污染全局空间;二、模块指明依赖关系,并且依赖是通过参数传递的形式导入的,无需通过全局对象引用 – 依赖同样不污染全局空间。
定义模块

3.1 如何定义模块

1
define(id? , dependencies ? , factory) ; ?表示可选项

模块可以分为两种,第一种是无依赖的模块

1
2
3
4
5
6
7
8
9
//math.js
define(function(){
var add = function(a,b){
return a+b;
};
return {
add : add
}
});

第二种是有依赖的模块 dependencies是一个数组形式的参数,factory函数接受的参数是依赖模块的返回值

1
2
3
4
5
//getWidth.js文件
define(['jquery'],function($){ //jquery.js和getWidth.js在同一目录下
var width = $(window).width();
return width;
});

3.2 如何导入模块 require([‘module1’,’module2’ ],callback) 传入的依赖必须是一个数组形式存在的,callback是依赖传入完毕之后执行的逻辑;如果模块有返回值,则会直接传递给callback函数的形参,如果函数没有返回值,那么传递的callback形参的值是undefined 文件目录如下

1
2
3
4
5
6
7
8
test
- index.html
- js
- require.js
- jquery.js
- main.js //入口文件
- getWidth.js
1
2
3
4
5
//main.js require请求的是模块的路径,因为使用了data-main属性,require默认访问路径是main.js所在目录,也就是js/
require(['getWidth','jquery'],function(ret){ //这里的jquery是引入的本地文件
console.log(ret);
})
//等价于 js/getWidth.js js/jquery.js

关于requirejs的实现原理

indx.html文件中引入requirejs

1
<script src='require.js' data-main = "js/main">

加载requirejs脚本的script标签加入了data-main属性,这个属性指定的js将在加载完reuqire.js后处理,我们把require.config的配置加入到data-main后,就可以使每一个页面都使用这个配置,然后页面中就可以直接使用require来加载所有的短模块名

data-main还有一个重要的功能,当script标签指定data-main属性时,require会默认的将data-main指定的js为根路径,是什么意思呢?如上面的data-main=”js/main”设定后,我们在使用require([‘jquery’])后(不配置jquery的paths),require会自动加载js/jquery.js这个文件,而不是jquery.js,相当于默认配置了:

data-main需要给所有的脚本文件设置一个根路径。根据这个根路径,RequireJS将会去加载所有相关的模块。下面的脚本是一个使用data-main例子:

1
2
3
require.config({
baseUrl : "js"
})

3.3 如果我们导入的文件是不符合require的规范或者导入文件来自本地服务器或者CDN或者其他的网站,这个时候上面的require方法就不能起作用了,这个时候我们需要配置文件的地址

1
2
3
4
5
//配置函数require.config({})
baseUrl——用于加载模块的根路径。
paths——用于映射不存在根路径下面的模块路径。
shims——配置在脚本/模块外面并没有使用RequireJS的函数依赖并且初始化函数。假设underscore并没有使用 RequireJS定义,但是你还是想通过RequireJS来使用它,那么你就需要在配置中把它定义为一个shim。
deps——加载依赖关系数组

不符合规范 : 先来看一个简单的例子,文件目录如下

1
2
3
4
5
6
7
export
- index.html
- js
- sayhello.js
- main.js
- require.js
1
2
//index.html 加如下代码
<script src="js/require.js" data-main='js/main'></script>
1
2
3
4
//sayhello.js
function hello(){
console.log("hello handsome you");
}
1
2
3
4
5
6
7
8
9
10
11
12
//main.js
require.config({
paths : {
h : 'sayhello' //模块h的路径是js/hello.js 因为data-main属性的作用
},
shim : {
h :{ exports : 'hello'} //将hello函数暴露出去;如果少了这行代码会报错
}
})
require(['h'],function(hello){
hello();
})

上面代码 exports: ‘hello’中的 hello,是我们在 hello.js 中定义的 hello 函数。当我们使用 function hello() {} 的方式定义一个函数的时候,它就是全局可用的。如果我们选择了把它 export给requirejs,那当我们的代码依赖于 hello 模块的时候,就可以拿到这个 hello 函数的引用了。

所以: exports 可以把某个非requirejs方式的代码中的某一个全局变量暴露出去,当作该模块以引用。

3.3.1 假如我想暴露多个sayhello.js中的全局变量呢?

1
2
3
4
5
6
7
//sayhello.js
function hello(){
console.log("hello handsome you");
}
function hello1(){
console.log("hello1 handsome you");
}

这个时候main.js不能再用export了,应该使用init来初始化这些接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
require.config({
paths : {
h : 'sayhello'
},
//shim : {
// h :{ exports : 'hello'}
//}
shim : {
h :{ init: function() {
return {
h0: hello,
h1: hello1
}
}}
}
})
require(['h'],function(he){
console.log(arguments);
he.h0()
he.h1()
})

3.3.2 导入外部服务器的文件,requirejs支持跨域

1
2
3
4
5
6
7
8
9
10
11
12
13
require.config({
paths : {
"jq" : ["http://libs.baidu.com/jquery/2.0.3/jquery"],
"a" : "js/a"
}
})
//配置完之后,下面可以引用jquery模块
require(["jq","a"],function(){
//在这里面可以直接使用jquery的所有API
$(function(){
alert("load finished");
})
})

3.4 如何引入第三方不不符合AMD规范的模块呢?这个时候需要进行配置

1
2
3
4
5
6
7
8
9
10
11
require.config({
shim:{
'underscore':{
exports:"_";
}
}
});
//配置之后,我们就可以在其他模块中引入underscore模块了
require('underscore',function(_){
_.each([1,2,3], alert);
});

3.5 如何引入第三方不符合AMD规范的插件

1
2
3
4
5
6
7
8
9
10
11
require.config({
shim: {
"underscore" : {
exports : "_";
},
"jquery.form" : {
deps : ["jquery"]
}
}
});
//

4 requirejs优势

4.1并行加载

我们知道,`<script></script>` 标签会阻塞页面,加载 a.js 时,后面的所有文件都得等它加载完成并执行结束后才能开始加载、执行。而 require.js 的模块可以并行下载,没有依赖关系的模块还可以并行执行,大大加快页面访问速度。

4.2 不愁依赖

在我们定义模块的时候,我们就已经决定好模块的依赖 – c 依赖 b,b 又依赖 a。当我想用 c 模块的功能时,我只要在 require函数的依赖里指定 c:

require(['c'], function(c) {...});

至于 c 依赖的模块,c 依赖的模块的依赖模块… 等等,require.js 会帮我们打理

4.3 减少全局冲突

通过 define 的方式,我们大量减少了全局变量,这样代码冲突的概率就极小极小 – JavaScript 界有句话说,全局变量是魔鬼,想想,我们能减少魔鬼的数量,我想是件好事。

关于全局变量

有一点需要说明的是,require.js 环境中并不是只有 define 和 require 几个全局变量。许多库都会向全局环境中暴露变量,以 jQuery 为例,1.7版本后,它虽然注册自己为 AMD 模块,但同时也向全局环境中暴露了 jQuery 与 $。所以以下代码中,虽然我们没有向回调函数传入一份引用,jQuery/$ 同样是存在的:

http status

发表于 2016-09-01 | 分类于 http status

HTTP状态码大全

完整的 HTTP 1.1规范说明书来自于RFC 2616,你可以在http://www.talentdigger.cn/home/link.php?url=d3d3LnJmYy1lZGl0b3Iub3JnLw%3D%3D在线查阅。HTTP 1.1的状态码被标记为新特性,因为许多浏览器只支持 HTTP 1.0。你应只把状态码发送给支持 HTTP 1.1的客户端,支持协议版本可以通过调用request.getRequestProtocol来检查。
本部分余下的内容会详细地介绍 HTTP 1.1中的状态码。这些状态码被分为五大类:
100-199 用于指定客户端应相应的某些动作。
200-299 用于表示请求成功。
300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。
400-499 用于指出客户端的错误。
500-599 用于支持服务器错误。
HttpServletResponse中的常量代表关联不同标准消息的状态码。在servlet程序中,你会更多地用到这些常量的标识来使用状态码。例如:你一般会使用response.setStatus(response.SC_NO_CONTENT)而不是 response.setStatus(204),因为后者不易理解而且容易导致错误。但是,你应当注意到服务器允许对消息轻微的改变,而客户端只注意状态码的数字值。所以服务器可能只返回 HTTP/1.1 200 而不是 HTTP/1.1 200 OK。
100 (Continue/继续)
如果服务器收到头信息中带有100-continue的请求,这是指客户端询问是否可以在后续的请求中发送附件。在这种情况下,服务器用100(SC_CONTINUE)允许客户端继续或用417 (Expectation Failed)告诉客户端不同意接受附件。这个状态码是 HTTP 1.1中新加入的。
101 (Switching Protocols/转换协议)
101 (SC_SWITCHING_PROTOCOLS)状态码是指服务器将按照其上的头信息变为一个不同的协议。这是 HTTP 1.1中新加入的。
200 (OK/正常)
200 (SC_OK)的意思是一切正常。一般用于相应GET和POST请求。这个状态码对servlet是缺省的;如果没有调用setStatus方法的话,就会得到200。
201 (Created/已创建)
201 (SC_CREATED)表示服务器在请求的响应中建立了新文档;应在定位头信息中给出它的URL。
202 (Accepted/接受)
202 (SC_ACCEPTED)告诉客户端请求正在被执行,但还没有处理完。
203 (Non-Authoritative Information/非官方信息)
状态码203 (SC_NON_AUTHORITATIVE_INFORMATION)是表示文档被正常的返回,但是由于正在使用的是文档副本所以某些响应头信息可能不正确。这是 HTTP 1.1中新加入的。
204 (No Content/无内容)
在并没有新文档的情况下,204 (SC_NO_CONTENT)确保浏览器继续显示先前的文档。这各状态码对于用户周期性的重载某一页非常有用,并且你可以确定先前的页面是否已经更新。例如,某个servlet可能作如下操作:
int pageVersion =Integer.parseInt(request.getParameter(“pageVersion”));
if (pageVersion >;= currentVersion) {
response.setStatus(response.SC_NO_CONTENT);
} else {
// Create regular page
}
但是,这种方法对通过刷新响应头信息或等价的HTML标记自动重载的页面起作用,因为它会返回一个204状态码停止以后的重载。但基于JavaScript脚本的自动重载在这种情况下仍然需要能够起作用。可以阅读本书7.2 ( HTTP 1.1 Response Headers and Their Meaning/HTTP 1.1响应头信息以及他们的意义)部分的详细讨论。
205 (Reset Content/重置内容)
重置内容205 (SC_RESET_CONTENT)的意思是虽然没有新文档但浏览器要重置文档显示。这个状态码用于强迫浏览器清除表单域。这是 HTTP 1.1中新加入的。
206 (Partial Content/局部内容)
206 (SC_PARTIAL_CONTENT)是在服务器完成了一个包含Range头信息的局部请求时被发送的。这是 HTTP 1.1中新加入的。
300 (Multiple Choices/多重选择)
300 (SC_MULTIPLE_CHOICES)表示被请求的文档可以在多个地方找到,并将在返回的文档中列出来。如果服务器有首选设置,首选项将会被列于定位响应头信息中。
301 (Moved Permanently)
301 (SC_MOVED_PERMANENTLY)状态是指所请求的文档在别的地方;文档新的URL会在定位响应头信息中给出。浏览器会自动连接到新的URL。
302 (Found/找到)
与301有些类似,只是定位头信息中所给的URL应被理解为临时交换地址而不是永久的。注意:在 HTTP 1.0中,消息是临时移动(Moved Temporarily)的而不是被找到,因此HttpServletResponse中的常量是SC_MOVED_TEMPORARILY不是我们以为的SC_FOUND。
注意
代表状态码302的常量是SC_MOVED_TEMPORARILY而不是SC_FOUND。
状态码302是非常有用的因为浏览器自动连接在定为响应头信息中给出的新URL。这非常有用,而且为此有一个专门的方法——sendRedirect。使用response.sendRedirect(url)比调用response.setStatus(response.SC_MOVED_TEMPORARILY)和response.setHeader(“Location”, url)多几个好处。首先,response.sendRedirect(url)方法明显要简单和容易。第二,servlet自动建立一页保存这一连接以提供给那些不能自动转向的浏览器显示。最后,在servlet 2.2版本(J2EE中的版本)中,sendRedirect能够处理相对路径,自动转换为绝对路径。但是你只能在2.1版本中使用绝对路径。
如果你将用户转向到站点的另一页中,你要用 HttpServletResponse 中的 encodeURL 方法传送URL。这么做可预防不断使用基于URL重写的会话跟踪的情况。URL重写是一种在你的网站跟踪不使用 cookies 的用户的方法。这是通过在每一个URL尾部附加路径信息实现的,但是 servlet 会话跟踪API会自动的注意这些细节。会话跟踪在第九章讨论,并且养成使用 encodeURL 的习惯会使以后添加会话跟踪的功能更容易很多。
核心技巧
如果你将用户转向到你的站点的其他页面,用 response.sendRedirect(response.encodeURL(url)) 的方式事先计划好会话跟踪(session tracking)要比只是调用 response.sendRedirect(url) 好的多。
这个状态码有时可以与301交换使用。例如,如果你错误的访问了http://www.talentdigger.cn/home/link.php?url=aG9zdC9%2BdXNlcg%3D%3D(路径信息不完整),有些服务器就会回复301状态码而有些则回复302。从技术上说,如果最初的请求是GET浏览器只是被假定自动转向。如果想了解更多细节,请看状态码307的讨论。
303 (See Other/参见其他信息)
这个状态码和 301、302 相似,只是如果最初的请求是 POST,那么新文档(在定位头信息中给出)药用 GET 找回。这个状态码是新加入 HTTP 1.1中的。
304 (Not Modified/为修正)
当客户端有一个缓存的文档,通过提供一个 If-Modified-Since 头信息可指出客户端只希望文档在指定日期之后有所修改时才会重载此文档,用这种方式可以进行有条件的请求。304 (SC_NOT_MODIFIED)是指缓冲的版本已经被更新并且客户端应刷新文档。另外,服务器将返回请求的文档及状态码 200。servlet一般情况下不会直接设置这个状态码。它们会实现getLastModified方法并根据修正日期让默认服务方法处理有条件的请求。这个方法的例程已在2.8部分(An Example Using Servlet Initialization and Page Modification Dates/一个使用servlet初始化和页面修正日期的例子)给出。
305 (Use Proxy/使用代理)
305 (SC_USE_PROXY)表示所请求的文档要通过定位头信息中的代理服务器获得。这个状态码是新加入 HTTP 1.1中的。
307 (Temporary Redirect/临时重定向)
浏览器处理307状态的规则与302相同。307状态被加入到 HTTP 1.1中是由于许多浏览器在收到302响应时即使是原始消息为POST的情况下仍然执行了错误的转向。只有在收到303响应时才假定浏览器会在POST请求时重定向。添加这个新的状态码的目的很明确:在响应为303时按照GET和POST请求转向;而在307响应时则按照GET请求转向而不是POST请求。注意:由于某些原因在HttpServletResponse中还没有与这个状态对应的常量。该状态码是新加入HTTP 1.1中的。
注意
在 HttpServletResponse 中没有 SC_TEMPORARY_REDIRECT 常量,所以你只能显示的使用307状态码。
400 (Bad Request/错误请求)
400 (SC_BAD_REQUEST)指出客户端请求中的语法错误。
401 (Unauthorized/未授权)
401 (SC_UNAUTHORIZED)表示客户端在授权头信息中没有有效的身份信息时访问受到密码保护的页面。这个响应必须包含一个WWW-Authenticate的授权信息头。例如,在本书4.5部分中的“Restricting Access to Web Pages./限制访问Web页。”
403 (Forbidden/禁止)
403 (SC_FORBIDDEN)的意思是除非拥有授权否则服务器拒绝提供所请求的资源。这个状态经常会由于服务器上的损坏文件或目录许可而引起。
404 (Not Found/未找到)
404 (SC_NOT_FOUND)状态每个网络程序员可能都遇到过,他告诉客户端所给的地址无法找到任何资源。它是表示“没有所访问页面”的标准方式。这个状态码是常用的响应并且在HttpServletResponse类中有专门的方法实现它:sendError(“message”)。相对于setStatus使用sendError得好处是:服务器会自动生成一个错误页来显示错误信息。但是,Internet Explorer 5浏览器却默认忽略你发挥的错误页面并显示其自定义的错误提示页面,虽然微软这么做违反了 HTTP 规范。要关闭此功能,在工具菜单里,选择Internet选项,进入高级标签页,并确认“显示友好的 HTTP 错误信息”选项(在我的浏览器中是倒数第8各选项)没有被选。但是很少有用户知道此选项,因此这个特性被IE5隐藏了起来使用户无法看到你所返回给用户的信息。而其他主流浏览器及IE4都完全的显示服务器生成的错误提示页面。可以参考图6-3及6-4中的例子。
核心警告
默认情况下,IE5忽略服务端生成的错误提示页面。
405 (Method Not Allowed/方法未允许)
405 (SC_METHOD_NOT_ALLOWED)指出请求方法(GET, POST, HEAD, PUT, DELETE, 等)对某些特定的资源不允许使用。该状态码是新加入 HTTP 1.1中的。
406 (Not Acceptable/无法访问)
406 (SC_NOT_ACCEPTABLE)表示请求资源的MIME类型与客户端中Accept头信息中指定的类型不一致。见本书7.2部分中的表7.1(HTTP 1.1 Response Headers and Their Meaning/HTTP 1.1响应头信息以及他们的意义)中对MIME类型的介绍。406是新加入 HTTP 1.1中的。
407 (Proxy Authentication Required/代理服务器认证要求)
407 (SC_PROXY_AUTHENTICATION_REQUIRED)与401状态有些相似,只是这个状态用于代理服务器。该状态指出客户端必须通过代理服务器的认证。代理服务器返回一个Proxy-Authenticate响应头信息给客户端,这会引起客户端使用带有Proxy-Authorization请求的头信息重新连接。该状态码是新加入 HTTP 1.1中的。
408 (Request Timeout/请求超时)
408 (SC_REQUEST_TIMEOUT)是指服务端等待客户端发送请求的时间过长。该状态码是新加入 HTTP 1.1中的。
409 (Conflict/冲突)
该状态通常与PUT请求一同使用,409 (SC_CONFLICT)状态常被用于试图上传版本不正确的文件时。该状态码是新加入 HTTP 1.1中的。
410 (Gone/已经不存在)
410 (SC_GONE)告诉客户端所请求的文档已经不存在并且没有更新的地址。410状态不同于404,410是在指导文档已被移走的情况下使用,而404则用于未知原因的无法访问。该状态码是新加入 HTTP 1.1中的。
411 (Length Required/需要数据长度)
411 (SC_LENGTH_REQUIRED)表示服务器不能处理请求(假设为带有附件的POST请求),除非客户端发送Content-Length头信息指出发送给服务器的数据的大小。该状态是新加入 HTTP 1.1的。
412 (Precondition Failed/先决条件错误)
412 (SC_PRECONDITION_FAILED)状态指出请求头信息中的某些先决条件是错误的。该状态是新加入 HTTP 1.1的。
413 (Request Entity Too Large/请求实体过大)
413 (SC_REQUEST_ENTITY_TOO_LARGE)告诉客户端现在所请求的文档比服务器现在想要处理的要大。如果服务器认为能够过一段时间处理,则会包含一个Retry-After的响应头信息。该状态是新加入 HTTP 1.1的。
414 (Request URI Too Long/请求URI过长)
414 (SC_REQUEST_URI_TOO_LONG)状态用于在URI过长的情况时。这里所指的“URI”是指URL中主机、域名及端口号之后的内容。例如:在URL–http://www.y2k-disaster.com:8080/we/look/silly/now/中URI是指/we/look/silly/now/。该状态是新加入 HTTP 1.1的。
415 (Unsupported Media Type/不支持的媒体格式)
415 (SC_UNSUPPORTED_MEDIA_TYPE)意味着请求所带的附件的格式类型服务器不知道如何处理。该状态是新加入 HTTP 1.1的。
416 (Requested Range Not Satisfiable/请求范围无法满足)
416表示客户端包含了一个服务器无法满足的Range头信息的请求。该状态是新加入 HTTP 1.1的。奇怪的是,在servlet 2.1版本API的HttpServletResponse中并没有相应的常量代表该状态。
注意
在servlet 2.1的规范中,类HttpServletResponse并没有SC_REQUESTED_RANGE_NOT_SATISFIABLE 这样的常量,所以你只能直接使用416。在servlet 2.2版本之后都包含了此常量。
417 (Expectation Failed/期望失败)
如果服务器得到一个带有100-continue值的Expect请求头信息,这是指客户端正在询问是否可以在后面的请求中发送附件。在这种情况下,服务器也会用该状态(417)告诉浏览器服务器不接收该附件或用100 (SC_CONTINUE)状态告诉客户端可以继续发送附件。该状态是新加入 HTTP 1.1的。
500 (Internal Server Error/内部服务器错误)
500 (SC_INTERNAL_SERVER_ERROR) 是常用的“服务器错误”状态。该状态经常由CGI程序引起也可能(但愿不会如此!)由无法正常运行的或返回头信息格式不正确的servlet引起。
501 (Not Implemented/未实现)
501 (SC_NOT_IMPLEMENTED)状态告诉客户端服务器不支持请求中要求的功能。例如,客户端执行了如PUT这样的服务器并不支持的命令。
502 (Bad Gateway/错误的网关)
502 (SC_BAD_GATEWAY)被用于充当代理或网关的服务器;该状态指出接收服务器接收到远端服务器的错误响应。
503 (Service Unavailable/服务无法获得)
状态码503 (SC_SERVICE_UNAVAILABLE)表示服务器由于在维护或已经超载而无法响应。例如,如果某些线程或数据库连接池已经没有空闲则servlet会返回这个头信息。服务器可提供一个Retry-After头信息告诉客户端什么时候可以在试一次。
504 (Gateway Timeout/网关超时)
该状态也用于充当代理或网关的服务器;它指出接收服务器没有从远端服务器得到及时的响应。该状态是新加入 HTTP 1.1的。
505 (HTTP Version Not Supported/不支持的 HTTP 版本)
505 (SC_HTTP_VERSION_NOT_SUPPORTED)状态码是说服务器并不支持在请求中所标明 HTTP 版本。该状态是新加入 HTTP 1.1的。

内置对象源码角度理解

发表于 2016-09-01 | 分类于 javascript

从源代码的角度理解内置对象(构造函数)

  • 本地对象: Object Function Array String Boolean Number Date 这些是基本的类(引用类型);使用这些引用类型的时候需要进行实例化;归根到底:这些只不过就是内置的构造函数而已,仅此而已 you can do , we all can do
  • Math对象不需要new就可以直接使用,而其他对象的方法需要new才能调用它们的方法
  • 所有的构造函数—->Function构造函数—–>Object构造函数
  • function (小写) 用来声明函数 ; 就像用 var 声明 一个变量是一样的

Function 内置对象源代码 : Function是所有函数的构造函数,包括下面的内置对象

1
2
3
4
5
6
7
8
9
10
Arguments.prototype.callee = 0;
Arguments.prototype.caller = 0;
Arguments.prototype = new Array();
Arguments = {};
Function.prototype.arguments = 0;
Function.prototype.arity = 0;
Function.prototype.apply = function(thisArg,argArray) {};//apply传入数值数组
Function.prototype.call = function(thisArg,args) {};//call传入数值,单个数值传入
Function = {};//声明Function是一个对象
//ES5后有新增bind

所有的函数都是继承了Function的原型

Math内置对象源代码如下: Math对象本身就是一个对象,不需要声明就可以直接调用其方法,将Math作为对象,然后调用其方法就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Math.E = 0;
Math.LN10 = 0;
Math.LN2 = 0;
Math.LOG10E = 0;
Math.LOG2E = 0;
Math.PI = 0;
Math.SQRT1_2 = 0;
Math.SQRT2 = 0;
Math.abs = function(x) {};
Math.acos = function(x) {};
Math.asin = function(x) {};
Math.atan = function(x) {};
Math.atan2 = function(x,y) {};
Math.ceil = function(x) {};
Math.cos = function(x) {};
Math.exp = function(x) {};
Math.floor = function(x) {};
Math.log = function(x) {};
Math.max = function(x) {};
Math.min = function(x) {};
Math.pow = function(x,y) {};
Math.random = function() {};
Math.round = function(x) {};
Math.sin = function(x) {};
Math.sqrt = function(x) {};
Math.tan = function(x) {};
Math = {}; //声明Math对象,以上所有的方法都是可以直接用的,无需newMath,因为Math在底层就不是构造函数

Array 内置对象(构造函数)源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Array.isArray = function(obj) {};//判断一个对象是不是数组,返回布尔类型
function Array(args) {} //声明Array函数,所以需要new才可以调用Array的方法
Array.prototype.concat = function(items) {};
Array.prototype.join = function(separator) {};
Array.prototype.push = function(items) {};
Array.prototype.slice = function(start,end) {};
Array.prototype.sort = function(compareFn) {};
Array.prototype.splice = function(start,deleteCount,items) {};
Array.prototype.unshift = function(items) {};
Array.prototype.valueOf = function() {};
Array.prototype.pop = function() {};
Array.prototype.shift = function() {};
Array.prototype.reverse = function() {};
//从源代码分析来看,可以得到哪些方法需要传入参数,哪些方法不需要传入参数

数组的定义

  • var arr = [ ]; var arr = new Array() ;
  • var arr = new Array(size) ; 表示定义个数组长度为size ,length为size
  • var arr = new Array(item1,item2,····),表示定义了具体的一个数组,length为item的个数

1 arrObject.shift() : 改变原数组 删除数组的第一个 元素,返回所删除的元素;

arrObject.pop( ) : 改变原数组 删除数组的最后一个 元素,返回所删除的元素;

注意如果要操作的数组为空,那么该方法不改变数组,注意返回值是undefined 不需要传参

2 arrObject.unshift( item1,item2,···· ) : 改变原数组 向原数组中头部添加一个或多个元素,返回添加后的数组的长度;

arr.Object.push ( item1,,iten2,···· ) :改变原数组 向原数组中最后添加一个或多个元素,返回添加后数组的长度;

需要传一个参数,可以传入基本数据类型,也可以是复杂数据类型,比如向数组中添加一个对象

3 arrObject.slice(start,end) :不改变原数组 ,返回一个新的数组,会重新开辟一块内存,存储返回的数组,start必须,表示从哪个位置(索引处)开始截取数组,end可选,如果没有设定,则表示从start开始到最后所有的元素,包括start索引出的元素,不包括end索引处的元素

4 arrObject.splice(index,howmany,item1,item2,····) 改变原数组,返回含有被删除元素的数组,会重新开辟一块内存,存储返回的数组 index表示开始删除元素的索引值,howmany表示要删除的元素的个数(可以为0 ,表示不删除元素,如果未规定这个数字,那么表示删除从index索引出开始到结束所有的元素),itemx 表示要添加的元素

5 arrObject.sort( sortby) 改变原数组 如果不传参数,默认按照字符编码 顺序进行排序;如果传入一个函数,按照函数规定的规则排序;

5 arrObject.concat(arr1,arr2····) ,不改变原数组,返回一个新的数组,会重新开辟一块内存,存储返回的数组 可以添加元素,也可以添加数组;

6 arrObject.join(seperator) ,不改变原数组 该方法把数组中的所有元素中间加一个分隔符,组成一个字符串返回

7 arrObject.toString() ; 不改变原数组 返回值与没有参数的 join() 方法返回的字符串相同。其实就是应用了join方法;

8 arrObject.reverse() ; 改变原数组 返回颠倒后的数组的引用;

9 arrObject.forEach( funtion(item,index) { } ) ; 这个是遍历数组的新的方法,第一个参数是数组中的每一个元素,第二个参数index代表每个元素的索引;function函数里面的this指向是window;

4 既然数组在new之后是一个对象,var arr = new Array() 或者通过字面量声明一个数组 var arr = [1,2,3],那么数组就可以作为对象进行操作,然后给数组添加属性

1
2
arr.name = "little arr";
arr[len] = "three";

Object 内置对象(构造函数)源代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Object.isExtensible = function(object) {};
Object.preventExtensions = function(obj) {};
Object.getOwnPropertyDescriptor = function(obj,prop) {};
Object.defineProperty = function(obj,prop,desc) {};
Object.defineProperties = function(obj,props) {};
Object.keys = function(obj) {};
Object.getOwnPropertyNames = function(obj) {};
Object.create = function(proto,props) {};
Object.getPrototypeOf = function(obj) {};
Object.seal = function(obj) {};
Object.isSealed = function(obj) {};
Object.freeze = function(obj) {};
Object.isFrozen = function(obj) {};
//以上方法不需要实例化对象即可通过Object对象直接调用
Object.prototype.constructor = 0;
Object.prototype.length = 0;
Object.prototype.prototype = 0;
function Object(value) {} //声明Object函数
Object.prototype.toLocaleString = function() {};
Object.prototype.hasOwnProperty = function(propertyName) {};
Object.prototype.isPrototypeOf = function(o) {};
Object.prototype.propertyIsEnumerable = function(propertyName) {};
Object.prototype.toString = function() {};
Object.prototype.valueOf = function() {};

Date内置对象(构造函数)的源代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Date.UTC = function(year,month,date,hours,minutes,seconds,milliseconds) {};
Date.parse = function(dateString) {};//这两个方法不需要new Date 就可以使用
function Date(args) {} //声明Date函数 以下方法必须new date对象才能用
Date.prototype.getDate = function() {};
Date.prototype.getDay = function() {};
Date.prototype.getMonth = function() {};
Date.prototype.getFullYear = function() {};
Date.prototype.getHours = function() {};
Date.prototype.getMilliseconds = function() {};
Date.prototype.getMinutes = function() {};
Date.prototype.getSeconds = function() {};
Date.prototype.getTime = function() {};
Date.prototype.getTimezoneOffset = function() {};
Date.prototype.getUTCDate = function() {};
Date.prototype.getUTCDay = function() {};
Date.prototype.getUTCFullYear = function() {};
Date.prototype.getUTCHours = function() {};
Date.prototype.getUTCMilliseconds = function() {};
Date.prototype.getUTCMinutes = function() {};
Date.prototype.getUTCMonth = function() {};
Date.prototype.getUTCSeconds = function() {};
Date.prototype.getYear = function() {};
Date.prototype.setDate = function(date) {};
Date.prototype.setFullYear = function(year,month,day) {};
Date.prototype.setHours = function(hour,min,sec,ms) {};
Date.prototype.setMilliseconds = function(ms) {};
Date.prototype.setMinutes = function(min,sec,ms) {};
Date.prototype.setMonth = function(month,day) {};
Date.prototype.setSeconds = function(sec,ms) {};
Date.prototype.setTime = function(time) {};
Date.prototype.setUTCDate = function(date) {};
Date.prototype.setUTCFullYear = function(year,month,day) {};
Date.prototype.setUTCHours = function(hour,min,sec,ms) {};
Date.prototype.setUTCMilliseconds = function(ms) {};
Date.prototype.setUTCMinutes = function(min,sec,ms) {};
Date.prototype.setUTCMonth = function(month,day) {};
Date.prototype.setUTCSeconds = function(sec,ms) {};
Date.prototype.setYear = function(value) {};
Date.prototype.toDateString = function() {};
Date.prototype.toISOString = function() {};
Date.prototype.toLocaleDateString = function() {};
Date.prototype.toLocaleString = function() {};
Date.prototype.toLocaleTimeString = function() {};
Date.prototype.toTimeString = function() {};
Date.prototype.toUTCString = function() {};

RegExp正则对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
RegExp.leftContext = null;
RegExp.input = null;
RegExp.lastParen = null;
RegExp.lastMatch = null;
RegExp.rightContext = null;
RegExp.$1 = null;
RegExp.$2 = null;
RegExp.$3 = null;
RegExp.$4 = null;
RegExp.$5 = null;
RegExp.prototype.global = 0;
RegExp.prototype.ignoreCase = 0;
RegExp.prototype.lastIndex = 0;
RegExp.prototype.multiline = 0;
RegExp.prototype.source = null;
function RegExp(pattern,options) {}
RegExp.prototype.exec = function(String) {};
RegExp.prototype.test = function(String) {};

创建正则对象的方法:

1
2
3
4
5
6
1 字面量 var patt1 = / pattern / attribute
2 构造函数声明 var patt2 = new RegExp('pattern','attribute')
var patt1 = /d\d/g;
var patt2 = new RegExp('d\\d','g');
var patt3 = new RegExp('d\d','g');
//注意区分patt2 和patt3 \ 是转义字符

正则对象的属性

1
2
3
4
5
6
7
8
9
10
11
var patt1 = /d\d/g;
console.log(patt1.source);//d\d
console.log(patt1.global);//true
console.log(patt1.ignoreCase);//false
console.log(patt1.multiline );//fa;se
console.log(patt1.lastIndex);//该属性存放一个整数,它声明的是上一次匹配文本之后的第一个字符的位置。
//source :返回字符串形式 返回正则表达式匹配的原文本 pattern,该文本不包括正则表达式直接量使用的定界符,也不包括标志 g、i、m。
//global ignoreCase multiline 返回true 或者false ,用来判断正则对象是否声明了 g i m
//lastIndex:
/*上次匹配的结果是由方法 RegExp.exec() 和 RegExp.test() 找到的,它们都以 lastIndex 属性所指的位置作为下次检索的起始点。这样,就可以通过反复调用这两个方法来遍历一个字符串中的所有匹配文本。
该属性是可读可写的。只要目标字符串的下一次搜索开始,就可以对它进行设置。当方法 exec() 或 test() 再也找不到可以匹配的文本时,它们会自动把 lastIndex 属性重置为 0。*/

正则对象的方法

1
2
RegExpObject.test(str) 用来检测str字符串中是否有该正则对象,返回值是true或者false;
RegExpObject.exec(str) 返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。

###JS包装对象如下

Boolean 内置对象(构造函数)的源代码如下

1
2
function Boolean(value) {} //声明Boolean函数
Boolean.prototype.valueOf = function() {};

Number内置对象(构造函数)的源代码如下

1
2
3
4
5
6
7
8
9
10
11
Number.MAX_VALUE = 0;
Number.MIN_VALUE = 0;
Number.NaN = 0;
Number.NEGATIVE_INFINITY = 0;
Number.POSITIVE_INFINITY = 0;//上面这几个Number方法不需要 new Number便可以直接使用
function Number(value) {} //声明Number函数
Number.prototype.toExponential = function(fractionalDigits) {};
Number.prototype.toFixed = function(fractionalDigits) {};
Number.prototype.toPrecision = function(precision) {};
Number.prototype.toString = function(radix) {};
Number.prototype.valueOf = function() {};

1 numberObject.toString() 可以传入基数,表达将数字按照那个进制转化为字符串

2 numberObject.valueOf() 得到number对象的原始值;

3 numberObject.toFixed(n) 返回的是具有指定位数小数的数字的字符串表示

String 内置对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
String.fromCharCode = function(chars) {};
function String(value) {}
String.prototype.anchor = function(nameAttribute) {};
String.prototype.big = function() {};
String.prototype.blink = function() {};
String.prototype.bold = function() {};
String.prototype.charAt = function(pos) {};
String.prototype.charCodeAt = function(index) {};
String.prototype.concat = function(strings) {};
String.prototype.fixed = function() {};
String.prototype.fontcolor = function(color) {};
String.prototype.fontsize = function(size) {};
String.prototype.indexOf = function(searchString,position) {};
String.prototype.italics = function() {};
String.prototype.lastIndexOf = function(searchString,position) {};
String.prototype.link = function(href) {};
String.prototype.localeCompare = function(that) {};
String.prototype.match = function(regexp) {};
String.prototype.replace = function(searchValue,replaceValue) {};
String.prototype.search = function(regexp) {};
String.prototype.slice = function(start,end) {};
String.prototype.small = function() {};
String.prototype.split = function(separator,limit) {};
String.prototype.strike = function() {};
String.prototype.sub = function() {};
String.prototype.substr = function(start,length) {};
String.prototype.substring = function(start,end) {};
String.prototype.sup = function() {};
String.prototype.toLowerCase = function() {};
String.prototype.toLocaleLowerCase = function() {};
String.prototype.toLocaleUpperCase = function() {};
String.prototype.toUpperCase = function() {};
String.prototype.valueOf = function() {};

Function Review

发表于 2016-09-01 | 分类于 javascript

函数专题 函数域函数式编程

1 函数声明:function fn(){ }

2 函数表达式:应用场景 var fn = function(){ }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
在构造函数中添加方法
function Person(name) {
this.name = name;
this.age = age;
// 在构造函数内部中添加方法
this.getAge = function() {
return this.age;
}
}
// 给原型添加方法
Person.prototype.getName = function() {
return this.name;
}
// 在对象中添加方法
var a = {
m: 20,
getM: function() {
return this.m;
}
}

3 匿名函数:应用场景,自执行以及作为参数传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 使用函数自执行的方式创建模块
(function(window, undefined) {
// 声明jQuery构造函数
var jQuery = function(name) {
// 主动在构造函数中,返回一个jQuery实例
return new jQuery.fn.init(name);
}
// 添加原型方法
jQuery.prototype = jQuery.fn = {
constructor: jQuery, //jQuery构造函数的prototype属性上有一个constructor属性,上面一行代码的操作会将prototype指向一个新的对象,所以需要加上这行代码,添加其constructor属性
init:function(name) { ... },//实现选择器功能
css: function() { ... return this} //每次链式编程结束之后都返回实例化对象
}
jQuery.fn.init.prototype = jQuery.fn;//这行代码是jQuery实现链式编程的关键,返回的init构造函数的实例指向了函数jQuery的原型prototype,该原型上有jQuery上封装的API
// 将jQuery改名为$,并将引用保存在window上,形成闭包,对外开发jQuery构造函数,这样我们就可以访问所有挂载在jQuery原型上的方法了
window.jQuery = window.$ = jQuery;//赋值运算,从右至左,返回等号右边的运算数
//window对象多了两个属性,一个是$ 一个是jQuery 都被赋值为jQuery函数,指向jQuer函数地址
})(window);
// 在使用时,我们直接执行了构造函数,因为在jQuery的构造函数中通过一些手段,返回的是jQuery的实例,所以我们就不用再每次用的时候在自己new了
$('#div1');//$(name) 执行的时候,得到返回的 new jQuery.fn.init(name)对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//函数自执行的方式
(function(){
console.log("func is excuted");
})();
(function(){
console.log("func is excuted");
}());
~function(){
console.log("func is excuted");
}();
+function(){
console.log("func is excuted");
}();

4 函数的形参,传入的实参赋值给形参;形参作为变量名成为该函数作用域内的变量;如果实参个数小于形参个数,未被定义的将默认值为undefined

函数的参数是按值传递的,即会将传递的值复制一份到函数的局部变量中;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//----------------------------------------------------------------------------
//先看一下这个栗子
var a = 10 ;
var obj = {name:"Jhon"};
function fn(a,obj){
a = a + 1 ;
obj.name = "JiM";
console.log(a);
}
fn(a,obj);
console.log(a);
console.log(obj.name);
//-----------------------------------------------------------------------------
//对比理解对象作为参数的传递
var person = {
name: 'Nicholas',
age: 20
}
function setName(obj) { // 传入一个引用
obj = {}; // 将传入的引用指向另外一个空的对象
obj.name = 'Greg'; // 给这个空的对象添加属性
}
setName(person);//类似于 obj = person ;然后回去执行函数,又将obj指向一个空的对象
console.log(person.name); // Nicholas 未被改变
//--------------------------------------------------------
var person = {
name: 'Nicholas',
age: 20
}
function setName(obj) { // 传入一个引用
obj.name = 'Greg'; // 修改引用的name属性
}
setName(person);//将obj指向person 类似于 obj = person;
console.log(person.name); // Greg
//对比以上两种情况,对于基本数据类型,是按值传递的,对于复杂数据类型,也是按值传递的,传递的是复杂数据类型对应的地址值;
//----------------------------------------------------------------------
var c= 5;
//----------------------函数的形参是局部变量
function fn(a,b){ //a = 4 , b = 3 这两个是函数作用域内的变量
d = 6; //这个将会添加给全局作用域
console.log(a+b);
}
fn(4,3);
//----------------------------------------------------------------------------
//传入的实参个数少于形参的个数,未被赋值的形参默认值为undefined
function fn2 (a,b){
console.log(a);//1
console.log(b);//undefined
}
fn2(1);
//-----------------------------------------------------------------------------

5 函数的调用方式:

作为函数体直接执行 作为构造函数调用 作为对象的方法调用 ;

这些都是函数的执行,函数内部的代码都会一行行的执行;

1
2
3
4
5
6
7
function f1(){
console.log(this);
var tmp = 1;
this.x = 3;
console.log(tmp);    //A
console.log(this.x);     //B
}

5.1 函数直接执行

1
console.log(f1());//undefined f1()函数执行后没有返回值,此时默认返回undefined

控制台输出

1
2
3
4
window
1
3
undefined

作为构造函数调用,此时内部的this指向new出来的对象

1
 console.log(new f1());

控制台输出

1
2
3
4
f1{} //这个其实就是new操作符创建的一个空的对象
1
3
f1{x:3}

6 函数简写

7 prototype属性和constructor属性

  • 每个函数都自动拥有一个prototype属性,该属性是一个对象,
  • 函数的prototype属性,包含一个不可枚举的属性constructor ;constructor属性指向该函数
  • 类似形成了一个闭环
1
2
3
4
5
6
7
8
9
10
11
12
function fn (a,b){
fn.age = 19 ;
console.log(a);//1
console.log(b);//undefined
}
console.log(fn.prototype.constructor === fn);//true
var f = new fn();
console.dir(f);
console.log(f.__proto__ === fn.prototype );//true
console.log(f.__proto__.constructor == fn);//true

8 函数的name属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var func1 = function () {};
// ES5
func1.name // ""
// ES6
func1.name // "func1"
//上面代码中,变量func1等于一个匿名函数, ES5 和 ES6 的name属性返回的值不一样。
//如果将一个具名函数赋值给一个变量,则 ES5 和 ES6 的name属性都返回这个具名函数原本的名字。
const bar = function baz() {};
// ES5
bar.name // "baz"
// ES6
bar.name // "baz"
//Function构造函数返回的函数实例,name属性的值为 “anonymous” 。
(new Function).name // "anonymous"
//bind返回的函数,name属性值会加上 “bound ” 前缀。
function foo() {};
foo.bind({}).name // "bound foo"
(function(){}).bind({}).name // "bound "

图片居中的N中方式

发表于 2016-08-22 | 分类于 html

图片居中的N中方式:以下面的代码为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
div{
height: 200px;
width: 300px;
background-color: pink;
margin: 100px auto;
}
</style>
</head>
<body>
<div>
<img src="img/01.jpg" alt="" width="100px" height="100px"/>
</div>
</body>
</html>

水平居中

第一种方法:给img的父盒子 设置 text-align:center,可以使文本或者图片水平居中

1
2
3
4
5
6
7
div{
height: 200px;
width: 300px;
background-color: pink;
margin: 100px auto;
text-align:center
}

第二种方法:计算父盒子剩余宽度 给img添加margin

1
2
3
img {
margin :0 100px ; (父盒子宽度-img宽度)/2 (300-100)/2
}

第三种方法: 由于margin: 0 auto 的居中只能给块级元素设置才有效果,所以将img转化为块级元素

1
2
3
4
img {
display :block ;
margin :0 auto ;
}

第四种方法:给父盒子开启弹性布局,注意图片会被拉伸,因为默认开启弹性布局之后,align-self:strench

1
2
3
4
5
6
7
8
9
div{
height: 200px;
width: 300px;
background-color: pink;
margin: 100px auto;
display: flex;
justify-content: space-around;
}

第五种方法 :利用margin auto 的流体特性

1
2
3
4
5
6
7
8
9
div{
position:relative;
}
img{
position:absolute;
left:0;
right:0;
margin:0 atuo ;
}

垂直居中

第一种方法:计算父盒子剩余高度给img添加margin

1
2
3
img{
margin:50px 100px ;
}

第二种方法,给父盒子开启弹性布局,同时给img设置 align-self:center

1
2
3
4
5
6
7
8
9
10
11
12
div{
height: 200px;
width: 300px;
background-color: pink;
margin: 100px auto;
display: flex;
justify-content: space-around;
}
img {
align-self:center
}

第三种方法 : 利用margin auto 的流体特性

1
2
3
4
5
6
7
8
9
div{
position:relative;
}
img{
position:absolute;
top:0;
bottom:0;
margin:auto 0 ;
}

jQuery中和DOM中 offset系列的不同

发表于 2016-08-17 | 分类于 css

jQuery中和DOM中 offset系列的不同;

一 、jQuery中offset( ) 方法获取元素距离边界的值,该方法返回两个整形数值,一个代表left,一个代表top,其始终是获取的当前jquery对象相对于文档的边界的距离;

不写参数:jqueryObj.offset().left jqueryObj.offset().top 可以获取相应值

传入键值对参数:jQueryObj.offset({left:30,left:50});可以将匹配的元素设置距离边界的距离。

DOM中的offsetLeft offsetTop 获取元素距离边界值,

1)如果父元素有定位,那么DOM子元素是相对于父元素的border内边界的距离;

2)如果父元素没有定位,那么子元素是相对于文档边界的距离;

3)offsetLeft offsetTop 只能获取值,不能设置值,是一个只读属性;

二,事件对象参数的offsetX offsetY clientX clientY pageX pageY screenX screenY的区别

先总结下区别:(注意这些值都是整形的数值,代表事件源距离不同边界的以px计 的距离)

event.clientX、event.clientY

鼠标相对于浏览器窗口可视区域的X,Y坐标(窗口坐标),可视区域不包括工具栏和滚动条。IE事件和标准事件都定义了这2个属性

event.pageX、event.pageY

类似于event.clientX、event.clientY,但它们使用的是文档坐标而非窗口坐标。这2个属性不是标准属性,但得到了广泛支持。IE事件中没有这2个属性。

event.offsetX、event.offsetY

鼠标相对于事件源元素(srcElement)的X,Y坐标,只有IE事件有这2个属性,标准事件没有对应的属性。

offsetX offsetY(偏移) 获取鼠标点击事件源相对于元素(content+padding)的左上角的坐标值,如果点击在border边界上的话,那么值为负数;

event.screenX、event.screenY

鼠标相对于用户显示器屏幕左上角的X,Y坐标。标准事件和IE事件都定义了这2个属性

图xy2  :执行完rotateZ(90deg)

如何实现不同标签页之间的通信

发表于 2016-08-15 | 分类于 cookies storage

1 通过cookie进行通信

cookie简单理解就是一种可以让服务器在客户端的硬盘或者内存里面存储少量数据,或者说从客户端硬盘读取数据的技术.

1.1 cookie可以是同域之间的不同标签页进行通信

假设在域名www.myvirtual1.com有以下文件

01 cookies.html

1
2
3
4
5
6
7
<script>
document.cookie = "name1=Jhon";
var d = new Date();
d.setDate(d.getDate()+5);
var expires = d.toUTCString();
document.cookie = "name2=Jim;expires="+expires;
</script>

02 cookies.html

1
2
3
4
<script>
console.log(document.cookie);
//02cookies.html:9 name1=Jhon; name2=Jim; _ga=GA1.1.648196503.1489976857
</script>

1.2 不同域之间的标签页如何通过cookies进行通信呢?由于同源策略的影响,这个时候需要跨域来实现,这个时候需要设置cookie的domain属性

2 通过localStorage进行通信

假设在域名www.myvirtual1.com有以下文件

01localStorage.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="button" value="set localStorage" id="btn"/>
<script>
function sendMsg(text) {
window.localStorage.setItem('msg',text);
}
document.getElementById("btn").onclick = function(){
sendMsg ('message1');
};
</script>
</body>
</html>

02localStorage.html

1
2
3
4
5
6
7
<script>
//localstorage的增删改查的监听事件事件会监听
window.addEventListener('storage', function (evt) {
if(evt.key==='msg')
console.log(evt.newValue);
});
</script>

storageEvent事件对象参数有以下常用属性

1
2
3
key 属性用来表示storage存储的键值对属性的键
oldValue 属性用来表示storage存储的原来的属性值
newValue 属性用来表示storage存储的原来的属性值

cookie

发表于 2016-08-13 | 分类于 http cookies

本地存储cookies篇

1 HTTP cookie,通常直接叫做cookie,是客户端用来存储数据的一种选项,它既可以在客户端设置也可以在服务器端设置。cookie会跟随任意HTTP请求一起发送。

优点:兼容性好

缺点:一是增加了网络流量;二则是它的数据容量有限,最多只能存储4KB的数据,浏览器之间各有不同;三是不安全。

2.cookie的用途及工作原理

那cookie具体能干什么呢?

cookie 将信息存储于用户硬盘,因此可以作为全局变量,这是它最大的一个优点。它最根本的用途是 Cookie 能够帮助 Web 站点 保存有关访问者的信息 ,以下列举cookie的几种小用途。

① 保存用户登录信息。这应该是最常用的了。当您访问一个需要登录的界面,例如微博、百度及一些论坛,在登录过后一般都会有类似”下次自动登录”的选项,勾选过后下次就不需要重复验证。这种就可以通过cookie保存用户的id。

② 创建购物车。购物网站通常把已选物品保存在cookie中,这样可以实现 不同页面 之间 数据的同步 (同一个域名下是可以共享cookie的),同时在提交订单的时候又会把这些cookie传到后台。

③ 跟踪用户行为。例如百度联盟会通过cookie记录用户的偏好信息,然后向用户推荐个性化推广信息,所以浏览其他网页的时候经常会发现旁边的小广告都是自己最近百度搜过的东西。这是可以禁用的,这也是cookie的缺点之一。

那么,cookie是怎么起作用的呢?

在上一节中我们知道 cookie 是存在用户硬盘中,用户每次访问站点时,Web应用程序都可以读取 Cookie 包含的信息。当用户再次访问这个站点时,浏览器就会在本地硬盘上 查找 与该 URL 相关联的 Cookie 。如果该 Cookie 存在,浏览器就将它添加到 request header的Cookie字段中,与 http请求`一起发送到该站点。

在开发者工具network可以看到,如果有关该URL的cookie会被添加到请求上

要注意的是,添加到 request header 中是 浏览器的行为 ,存储在cookie的数据 每次 都会被浏览器 自动 放在http请求中。因此,如果这些数据不是每次都要发给服务器的话,这样做无疑会增加网络流量,这也是cookie的缺点之一。为了避免这点,我们必须考虑什么样的数据才应该放在cookie中,而不是滥用cookie。每次请求都需要携带的信息,最典型的就是 身份验证了,其他的大多信息都不适合放在cookie中。

cookie流程

  1. 用户在浏览器输入url,发送请求,服务器接受请求
  2. 服务器在响应报文中生成一个Set-Cookie报头,发给客户端
  3. 浏览器取出响应中Set-Cookie中内容,以cookie.txt形式保存在客户端
  4. 如果浏览器继续发送请求,浏览器会在硬盘中找到cookie文件,产生Cookie报头,与HTTP请求一起发送.
  5. 服务器接受含Cookie报头的请求,处理其中的cookie信息,找到对应资源给客户端.
  6. 浏览器每一次请求都会包含已有的cookie.

3 cookie属性

name、value 是 cookie 的名和值。domian 、Path 、 Expires/max-age 、Size 、Http 、 Secure等均属cookie的属性。

domain 和 path

这两个选项共同决定了cookie能被哪些页面共享。

domain 参数是用来控制 cookie对「哪个域」有效,默认为设置 cookie的那个域。这个值可以包含子域,也可以不包含它。如上图的例子,Domain选项中,可以是”.google.com.hk"(不包含子域,表示它对google.com.hk的所有子域都有效),也可以是"www.google.com.hk”(包含子域)。

path用来控制cookie发送的指定域的「路径」,默认为”/“,表示指定域下的所有路径都能访问。它是在域名的基础下,指定可以访问的路径。例如cookie设置为”domain=.google.com.hk; path=/webhp“,那么只有”.google.com.hk/webhp“及”/webhp“下的任一子目录如”/webhp/aaa“或”/webhp/bbb“会发送cookie信息,而”.google.com.hk“就不会发送,即使它们来自同一个域。

expries/max-age失效时间

expries 和 max-age 是用来决定cookie的生命周期的,也就是cookie何时会被删除。

expries 表示的是失效时间,准确讲是「时刻」,max-age表示的是生效的「时间段」,以「秒」为单位。

若 max-age 为正值,则表示 cookie 会在 max-age 秒后失效。如例四中设置”max-age=10800;”,也就是生效时间是3个小时,那么 cookie 将在三小时后失效。

若 max-age 为负值,则cookie将在浏览器会话结束后失效,即 session,max-age的默认值为-1。若 max-age 为0,则表示删除cookie。

secure

默认情况为空,不指定 secure 选项,即不论是 http 请求还是 https 请求,均会发送cookie。

是 cookie 的安全标志,是cookie中唯一的一个非键值对儿的部分。指定后,cookie只有在使用SSL连接(如HTTPS请求或其他安全协议请求的)时才会发送到服务器。

httponly(即http)

httponly属性是用来限制客户端脚本对cookie的访问。将 cookie 设置成 httponly 可以减轻xss(跨站脚本攻击 Cross Site Scripting)攻击的危害,

防止cookie被窃取,以增强cookie的安全性。(由于cookie中可能存放身份验证信息,放在cookie中容易泄露)

默认情况是不指定 httponly,即可以通过 js 去访问。

###4、如何利用以上属性去设置cookie?

服务器端设置

服务器通过发送一个名为 Set-Cookie 的HTTP头来创建一个cookie,作为 Response Headers 的一部分。如下图所示,每个Set-Cookie 表示一个 cookie(如果有多个cookie,需写多个Set-Cookie),每个属性也是以名/值对的形式(除了secure),属性间以分号加空格隔开。格式如下:

Set-Cookie: name=value[; expires=GMTDate][; domain=domain][; path=path][; secure]

只有cookie的名字和值是必需的。

  客户端设置

客户端设置cookie的格式和Set-Cookie头中使用的格式一样。如下:

document.cookie = “name=value[; expires=GMTDate][; domain=domain][; path=path][; secure]”

若想要添加多个cookie,只能重复执行 document.cookie(如上)。这可能和平时写的 js 不太一样,一般重复赋值是会覆盖的,

但对于cookie,重复执行 document.cookie 并「不覆盖」,而是「添加」(针对「不同名」的)。

5、cookie的缺点

安全性:由于cookie在http中是明文传递的,其中包含的数据都可以被他人访问,可能会被篡改、盗用。

大小限制:cookie的大小限制在4kb左右,不适合大量存储。

增加流量:cookie每次请求都会被自动添加到Request Header中,无形中增加了流量。cookie信息越大,对服务器请求的时间越长

js touch 事件对象参数

发表于 2016-08-13 | 分类于 javascript event

移动端 touch事件以及事件对象参数解析

一 :理解touch事件对象参数,其实就是事件对象参数新增了额外的几个参数,其中包括:

TouchEvent :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- changedTouches 所有改变的触摸点的集合
- targetTouches 目标元素上方的触摸点的
- touches 改变的触摸点
- 这三个对象里面的
changdTouches:TouchList:
[0]:Touch
{clientX:202.43899536132812
clientY:56.097999572753906
force:1
identifier:0
pageX:202.43899536132812
pageY:56.097999572753906
radiusX:14.02439022064209
radiusY:14.02439022064209
rotationAngle:0
screenX:348
screenY:
}
属性值都是一样的

每个事件对象参数可能包含以下两个属性[0] :包含触摸点的信息,length:包含触摸点的数量

二 : 触摸事件的绑定方法

走个demo看下效果,注意看控制台的输出:以下列出了一部分TouchEvent的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
<style>
.box {
width: 200px;
height: 200px;
background-color: skyblue;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
window.onload = function(){
var box = document.querySelector(".box");
box.addEventListener("touchstart",function(e){
console.log("触发了touchstart");
console.log(e);
console.log(e.changedTouches[0]);
});
box.addEventListener("touchmove",function(e){
// console.log("触发了touchmove");
console.log(e);
})
box.addEventListener("touchend",function(e){
console.log("触发了touchend");
console.log(e);
})
}
</script>
</body>
</html>
  1. TouchEvent

    1. altKey:false

    2. bubbles:true

    3. cancelBubble:false

    4. cancelable:true

    5. changedTouches:TouchList

      1. 0:Touch

        1. clientX:88
        2. clientY:157
        3. force:1
        4. identifier:0
        5. pageX:88
        6. pageY:157
        7. radiusX:15.333333015441895
        8. radiusY:15.333333015441895
        9. rotationAngle:0
        10. screenX:258
        11. screenY:275
        12. target:div.box
        13. proto:Touch
      2. length:1

    6. 二 Touch事件:每一个Touch事件都对应一个TouchEvent, 只不过可能事件对象参数中的某些数值可能会不一样

    7. touchstart touchmove(move过程持续触发) touchend

    8. touchstart touchmove 包含changedTouches targetTouches touches 这三个事件参数,且length不为0

    9. 但是 touchend 包含changedTouches 的length不为0 ,targetTouches touches的length为0

1…121314…20
JiM-W

JiM-W

keep fighting!

195 日志
52 分类
90 标签
© 2017 JiM-W
由 Hexo 强力驱动
主题 - NexT.Pisces