Cookies学习笔记

Cookie 的格式是:

[javascript]
name=<value>[; expires=<date>][; domain=<domain>][; path=<path>][; secure]
//名称=<值>[; expires=<日期>][; domain=<域>][; path=<路径>][; 安全]
[/javascript]

// 设置cookie

[javascript]
document.cookie="key=escape(value)";
[/javascript]

//escape()函数进行编码,它能将一些特殊符号使用十六进制表示,例如空格将会编码为“20%”,从而可以存储于cookie值中,而且使用此 种方案还可以避免中文乱码的出现。在取值的时候需要unescape(value)对value再进行转码即可。

// 设置多个cookie
设置多个cookie需要多次使用这样的方法。正确的设置方法是:

[javascript]
document.cookie="key=escape(value)";
document.cookie="key1=escape(value1)"
// 而不是
document.cookie="key=escape(value);key1=escape(value1)";
[/javascript]
// 获取cookie,注意第二个开始key值前面有空格:

[javascript]
function getCookie(key){
var aCookie = document.cookie.split(";");
for (var i=0; i < aCookie.length; i++){
var aCrumb = aCookie[i].split("=");
if (key === aCrumb[0].replace(/^\s|\s$/,"")){
return unescape(aCrumb[1]);
}
}
}
[/javascript]
// 设置cookie的存活时间:

[javascript]
var liveDate = new Date();
liveDate.setTime(liveDate.getTime() + 32460601000); //设置cookie的name的存活时间为3天。
document.cookie="name=test;expires=" + liveDate.toGMTString();
[/javascript]
// 删除cookie,设置expires一个过期的时间即可

[javascript]
var liveDate = new Date();
liveDate.setTime(liveDate.getTime() - 10000);
document.cookie = "name=test;expires=" + date.toGMTString();
[/javascript]
// 拓展cookie的作用域到根目录:

[javascript]
document.cookie="key=escape(value);path=/";
[/javascript]
// 设置cookie的访问域

[javascript]
document.cookie="name=value;domain=cookieDomain";
//以Laispace为例,要实现跨主机访问,可以写为:
document.cookie="name=value;domain=.laispace.com"; //所有Laispace.com下的主机都可以访问该cookie
[/javascript]
// 设置cookie的访问权限
设置了该属性,只有使用https协议才能够访问到
注意点:
如果设置cookie时带path属性,那么在删除的时候一定要加上path属性,否则删除的是当前目录下设置的cookie值。

Javascript 闭包的学习

名词定义:包裹一些局部变量的一个函数叫做一个闭包。闭包是个函数,而它「记住了周围发生了什么」。表现为由「一个函数」体中定义了「另个函数」
实现原理:嵌套函数可以访问外部作用域中声明的变量。
组成结构:函数以及构建这个函数的环境。
使用价值:将函数与其所操作的某些数据(环境)关连起来
使用缺点:闭包会影响性能!闭包会使得函数中的变量都被保存在内存中,内存消耗很大。

  • 用途1,将数据与多个函数相关联:
    [javascript]
    function makeSizer(size) {
    return function() {
    document.body.style.fontSize = size + ‘px’;
    };
    }

    var size12 = makeSizer(12);
    var size14 = makeSizer(14);
    var size16 = makeSizer(16);

    //size12(); // 将字号调整到12px
    //size14(); // 将字号调整到14px
    //size16(); // 将字号调整到16px
    [/javascript]

  • 用途2,模拟私有方法:
    私有方法不仅仅有利于限制对代码的访问:还提供了管理全局命名空间的强大能力,避免非核心的方法弄乱了代码的公共接口部分。
    [javascript]
    // 创建一个环境为三个函数共享,减少了污染
    var Counter = (function() {
    var privateCounter = 0;
    function changeBy(val) {
    privateCounter += val;
    }
    return {
    increment: function() {

     changeBy(1);
    

    },
    decrement: function() {

     changeBy(-1);
    

    },
    value: function() {

     return privateCounter;
    

    }
    }
    })();

    alert(Counter.value()); / 提示 0 /
    Counter.increment();
    Counter.increment();
    alert(Counter.value()); / 提示 2 /
    Counter.decrement();
    alert(Counter.value()); / 提示 1 /
    [/javascript]

这种方法跟创建一个对象,并分别定义对象的三个方法相似吧?
实验结果显示,这两种方式是相同的,不过小赖觉得,以下这种更为直观一点吧:
[javascript]
// 创建一个环境为三个函数共享,减少了污染
var Counter = {
privateCounter : 0,

increment: function() {
this.privateCounter +=1;
},

 decrement: function() {
   this.privateCounter -=1;
 },

 value: function() {
   return this.privateCounter;
 }

}

alert(Counter.value()); / 提示 0 /
Counter.increment();
Counter.increment();
alert(Counter.value()); / 提示 2 /
Counter.decrement();
alert(Counter.value()); / 提示 1 /
[/javascript]

使用闭包的话,三个方法共享一个环境,而使用对象来创建明明空间,实则是通过this指向这个对象,来保证共享一个环境,也是避免了污染,有异曲同工之妙吧。

参考:
1. 闭包
2. 闭包
3. secrets_of_javascript_closures

Javascript 最佳实践

  1. 1. 编码技巧
  2. 2. 新鲜概念

// @author lxl:使用高质量JS代码对提高性能肯定是非常有帮助的,小赖对常见的好方法总结在这里,不断更新。
// @update 2013/10/04
-
使用压缩后的文件(如lxl.min.js),并开启http gzip压缩工具
-
尽量将script标签放在前,可以尝试用异步加载的方法加载js文件
-
尽量保证js代码和HTML结构的分离,不要内嵌代码到HTML中,以统一维护和缓存处理

-

  • 避免全局变量的污染

1. 使用命名空间
2. 匿名函数封装立即执行
3. 始终使用var来声明变量

  • 使用var声明(显式)的全局变量是不能被删除的
  • 未用var声明(隐式)的全局变量是可以被删除的
  • 隐式全局变量并非真正的全局变量,但却是全局对象的属性,因为属性是可以通过delete操作符删除的,而变量则不行

  • for循环中将长度缓存到变量中。

1
避免重复计算HTMLCollections的长度(操作DOM一般都是比较昂贵的,缓存长度后效率竟然是是IE7下不缓存的190倍!)
  • for循环中建议使用降序来遍历
1
向下数到0通常更快,因为和0作比较要比和数组长度或非0的东西作比较更有效率
  • for-in循环只在遍历对象属性的时候才使用,其他情况建议使用for循环就够了
1
for-in 循环枚举出的顺序是不能保证的,且若数组对象已被自定义的功能增强,就可能发生逻辑错误
  • 避免隐式类型转换,使用===或!==总是最严谨的!
1
这总能避免一些意想不到的类型转换问题,不是么?
  • 使用hasOwnProperty()方法过滤从原型链继承的属性,如:
1
2
3
4
5
for (var i in man) {
if (man.hasOwnProperty(i)) { // 过滤
console.log(i, ":", man[i]);
}
}
  • 使用单var语句声明变量
1
2
3
4
变量的声明会被被JS引擎提至函数顶部预解析(hoisting),不如直接使用单var统 一声明所有将会用到的变量,方便查询又易于管理,如:
var a = 1,
b = 2,
c = 3;
  • 避免改变或增加原型对象的方法
1
2
3
4
5
6
7
随意改变或增加原型会增加维护成本,当以后使用一个方法却发现这个方法被重定义时,就会带来问题。
除非团队认可这种做法并意识到原型已添加了方法,知道怎么使用时:
if( typeof Object.prototype.myMethod !== "function"){
Object.prototype.myMethod = function(){
// 实现新增方法
}
}
  • 避免使用eval语句
1
2
3
4
5
6
7
8
9
10
eval是魔鬼,除非知道它执行的代码本身会有什么问题。
eval里的代码被恶意篡改的话,就会带来严重的安全问题。
若绝对需要使用eval,实则可以
1.new Function()替代,因为它有局部函数作用域,其中的var变量不会变成全局 的,可以避免一些问题.
2.将eval语句封装到即时的匿名函数中,与1有相同效果。
注意,setIntervalsetTimeout中传递字符串跟eval()是一样的,要注意避免直接 传递字符串:
setTimeout(myFunc, 1000); // 正确
setTimeout(function () { // 正确
myFunc(1, 2, 3);
}, 1000);
  • parseInt() 数制转换,不要忽略第二个参数指定基数
1
EC3中以字母o开头的字符串被当做八进制处理,而在EC5中已经改变,为了避免意外,应 该总是指定基数参数,尽管默认是10
  • 团队里使用同一套缩进方案,tab或space缩进
1
比起纠结于具体的规范,团队里总是执行同一套方案更有价值!
  • 总是使用花括号{},尽管只有一行代码
1
2
花括号开始的位置,是同一行还是换行,这也是团队规范的问题了:统一就好,不必 纠结。
为了避免下一条谈到js引擎自动补全分好的问题,建议花括号开始于同一行,可终端JS分 号的自动补全。
  • 总是使用分号结束代码
1
因为JS引擎自动补全分号的机制,不小心的换行可能会中断代码逻辑,如return语句块 换到了下一行。
  • 命名规范,多种,选择一套喜欢的呗
    1. 构造函数首字母大写,如Person(){}
    2. 构造函数驼峰命名分割单词,如MyFunc(){}
    3. 变量名用下划线分割单词,如 my_name,这可以喝ECMAScript默认属性和方法的Camel标记法相区分
    4. 常量用全大写和下划线书写,如 MAX_WIDTH
    5. 全局变量名全部大写,如GLOBAL,并使用它来定义明明空间,如GLOBAL.name = “xiaolai”;GLOBAL.myMethod = function(){};
    6. 私有属性或方法用下划线前缀来表示,如 _index
    -

编码技巧

  • 访问全局对象
1
2
3
4
全局对象一般直接通过window属性来访问,但特殊情况下(如定义了名为window的局部 变量覆盖了全局的window)可使用匿名函数内的this来获得全局对象:
var global = (function(){
return this;
})();

新鲜概念

  • HTMLCollections对象
1
2
3
4
5
6
7
document.getElementsByName();
document.getElementsByClassName();
document.getElementsByTagName();
document.images; // 页面上所有的图片元素
document.links; // 所有a标签
document.forms; // 所有表单
document.forms[0].elements; // 页面上第一个表单中的所有域

Javascript 异步加载

异步编程,即非阻塞地执行代码,其实可以用来加载一些附属功能的代码,比如分享按钮代码、GA分析代码等。
建议将script标签放置在就是为了不让JS代码阻塞DOM的渲染,不会在JS执行期间,网页一片空白卡顿的糟糕体验。
今天学习到GA的异步加载代码:
[javascript]
(function() {
var ga = document.createElement(‘script’); ga.type = ‘text/javascript’; ga.async = true;
ga.src = (‘https:’ == document.location.protocol ? ‘https://ssl‘ : ‘http://www‘) + ‘.google-analytics.com/ga.js’;
var s = document.getElementsByTagName(‘script’)[0]; s.parentNode.insertBefore(ga, s);
})();
[/javascript]
动态生成script标签并利用HTML5才新增的async属性设置为异步(可不写,但最好加上),加上用匿名函数封装,避免了内部变量泄露到外部污染全局。
这份代码可以兼容不支持HTML5中async属性的浏览器,而如果只考虑现代浏览器的话,其实可以偷懒,直接给要异步加载的script一个async属性即可实现上述异步加载的效果了: