第一章
1.全局变量就是在任何函数外面声明的或是未声明直接简单使用的,全局对象有个附加属性叫做window,指向该全局对象本身
myglobal = "hello"; // 不推荐写法
console.log(myglobal); // "hello"
console.log(window.myglobal); // "hello"
console.log(window["myglobal"]); // "hello"
console.log(this.myglobal); // "hello"
2.全局变量的问题
两个不同部分定义同名但不同作用的全局变量,会命名冲突
不声明的任何变量都会成为一个全局对象属性
function sum(x, y) {
// 不推荐写法: 隐式全局变量
result = x + y;
return result;
}
使用var声明变量成为本地变量
function sum(x, y) {
var result = x + y;
return result;
}
任务链进行部分var声明,会生成全局对象
// 反例,勿使用
function foo() {
var a = b = 0;
// ...
}
链分配较好的做法
function foo() {
var a, b;
// ... a = b = 0; // 两个均局部变量
}
3.var的副作用
隐式全局变量和明确定义的全局变量的差异
・通过var创建的全局变量(任何函数之外的程序中创建),是不能被删除的
・无var创建的隐式全局变量(无视是否在函数中创建)是能被删除的
在技术上,隐式全局变量是全局对象(window)的属性,属性是可以通过delete操作符删除的
// 定义三个全局变量
var global_var = 1;
global_novar = 2; // 反面教材
(function () {
global_fromfunc = 3; // 反面教材
}());
// 试图删除
delete global_var; // false
delete global_novar; // true
delete global_fromfunc; // true
// 测试该删除
console.log(typeof global_var); // "number"
console.log(typeof global_novar); // "undefined"
console.log(typeof global_fromfunc); // "undefined"
4.访问全局对象
var global = (function () {
return this;
}());
console.log(global);
5.单var形式(Single var Pattern)
函数顶部使用单var语句
・一览函数功能所需要的所有局部变量
・防止变量在定义之前使用
・少代码(类型啊传值啊单线完成)
单var形式例子,(推荐)使用一个var语句声明多个变量,并以逗号分隔
function func() {
var a = 1,
b = 2,
sum = a + b,
myobject = {},
i,
j;
// function body...
}
6.预解析:var散布的问题(Hoisting: A Problem with Scattered vars)
变量在同一函数中,它都被当做是声明的,即使是它在var声明前使用
// 反例
myname = "global"; // 全局变量
function func() {
alert(myname); // "undefined"
var myname = "local";
alert(myname); // "local"
}
func();
代码处理分两个阶段,第一阶段是变量,函数声明,以及正常格式的参数创建;
第二个阶段是代码执行,函数表达式和不合格的标识符(为声明的变量)被创建。
7.for循环(for Loops)
缓存数组(或集合)的长度是比较好的形式
for (var i = 0, max = myarray.length; i < max; i++) {
// 使用myarray[i]做点什么
}
把变量从循环中提出来
function looper() {
var i = 0,
max,
myarray = [];
// ...
for (i = 0, max = myarray.length; i < max; i++) {
// 使用myarray[i]做点什么
}
}
形式改进,只体现在性能上
・少一个变量(无max)
・向下数到0,通常更快
//第一种变化的形式:
var i, myarray = [];
for (i = myarray.length; i–-;) {
// 使用myarray[i]做点什么
}
//第二种使用while循环:
var myarray = [],
i = myarray.length;
while (i–-) {
// 使用myarray[i]做点什么
}
8.for-in循环(for-in Loops)
遍历对象属性,hasOwnProperty()方法过滤掉从原型链上下来的属性
// 对象
var man = {
hands: 2,
legs: 2,
heads: 1
};
// 在代码的某个地方
// 一个方法添加给了所有对象
if (typeof Object.prototype.clone === "undefined") {
Object.prototype.clone = function () {};
}
// for-in 循环,过滤
for (var i in man) {
if (man.hasOwnProperty(i)) { // 过滤
console.log(i, ":", man[i]);
}
}
/* 控制台显示结果
hands : 2
legs : 2
heads : 1*/
9.(不)扩展内置原型
不扩增构造函数的prototype属性原因
・降低可维护性,代码变得难以预测
・属性添加到原型中,可能会导致不使用hasOwnProperty属性时在循环中显示出来
10.switch模式(switch Pattern)
switch语句增强可读性和健壮性
var inspect_me = 0,
result = '';
switch (inspect_me) {
case 0:
result = "zero";
break;//避免贯穿
case 1:
result = "one";
break;
default:
result = "unknown";
}
11.避免隐式类型转换
JavaScript的变量在比较的时候会隐式类型转换
var zero = 0;
if (zero === false) {
// 不执行,因为zero为0, 而不是false
}
// 反面示例
if (zero == false) {
// 执行了...
}
所以,比较值和表达式类型的时候始终使用===和!==操作符
12.避免(Avoiding)eval()
访问动态属性
// 反面示例
var property = "name";
alert(eval("obj." + property));
// 更好的
var property = "name";
alert(obj[property]);
setInterval(), setTimeout()和Function()构造函数传递字符串
/ 反面示例
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);
// 更好的
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);
防止全局变量污染命名空间
・使用新的Function()构造就类似于eval()
・封装eval()调用到一个即时函数中
console.log(typeof un); // "undefined"
console.log(typeof deux); // "undefined"
console.log(typeof trois); // "undefined"
var jsstring = "var un = 1; console.log(un);";
eval(jsstring); // logs "1"
jsstring = "var deux = 2; console.log(deux);";
new Function(jsstring)(); // logs "2"
jsstring = "var trois = 3; console.log(trois);";
(function () {
eval(jsstring);
}()); // logs "3"
console.log(typeof un); // number
console.log(typeof deux); // "undefined"
console.log(typeof trois); // "undefined"
eval()可以访问和修改它外部作用域中的变量,function不能
(function () {
var local = 1;
eval("local = 3; console.log(local)"); // logs "3"
console.log(local); // logs "3"
}());
(function () {
var local = 1;
Function("console.log(typeof local);")(); // logs undefined
}());
13.parseInt()下的数值转换
避免矛盾和意外的结果,总是指定基数参数
var month = "06",
year = "09";
month = parseInt(month, 10);//10进制
year = parseInt(year, 10);//10进制
替换方法是将字符串转换成数字
Number("08") // 8
14.编码规范
缩进
花括号{}
左花括号的位置
空格
15.命名规范
以大写字母写构造函数:
var adam = new Person();
分隔单词:
构造函数时,驼峰:大驼峰MyConstructor(),小驼峰myFunction()
变量时,小驼峰,单词小写以下划线连接(first_name)
其它命名形式:
var person = {
getName: function () {
return this._getFirst() + ' ' + this._getLast();
},
_getFirst: function () {
// ...
},
_getLast: function () {
// ...
}
};
getName()就表示公共方法,部分稳定的API,
_getFirst()和_getLast()则表明了私有,下一个版本中时不能保证工作的
注释:
注释你的代码,清楚的知道这个代码是干嘛用
网友评论