javascript模式之一——基本的模式

说明

刚读完javascript模式一书,以下是本人总结的知识点,作为读书笔记,同时也为广大爱好者提供参考。

了解模式——什么是模式

广义上模式是指“重现事件或者对象的主题…它是一个可以用来产生其他事物的模板或者模型”。
在软件开发过程中,模式是指一个通用问题的解决方案。一个模式不仅仅是一个可以用来赋值粘贴的代码解决方案,更多地市提供了一个更好的实践经验,有用的抽象化表示和解决一类问题的模板。

变量篇

尽量少用全局变量

大量的创建全局变量,总有可能发生命名冲突。javascript总是在不知不觉中就出人意料地创建了全局变量,原因在于javascript的两个特性。

1.javascript有个暗示全局变量的概念,即任何变量,如未经声明,就为全局对象所有。

让我们来看一个示例

function sum(x,y){
//反模式
result = x + y;
return result;
}

在这个例子中,result未经声明就使用了。代码虽然在一般情况下可以正常工作,但如果在调用该函数后,在全局命名空间使用了另外的result变量,就会出现问题。

2.另外一种创建隐式全局变量的反模式是带有var声明的链式赋值。在下面的代码片断中,a是局部变量,b是全局变量。

function foo(){
//反模式,不要使用
var a = b = 0;
//b为全局,内部var a = (b = 0);
return result;
}

如果对链式赋值的所有变量都进行了声明,就不会创建出不期望的全局变量。例如:

function foo(){
var a, b;
//...
 a = b = 0;//均为局部变量
}
  • 使用var 定义的全局变量不可以删除;
  • 不使用var的全局变量可以删除;

说明:使用var 定义就是一个变量, 不使用var定义就是一个对象的属性。

var a = 1;
b = 2;//反模式
(function(){
    c = 3;//反模式
})();
//企图删除
delete a; // false;
delete b; // true;
delete c; // true
//测试删除情况
typeof a; // number
typeof b; // undefined
typeof c; // undefined

在ES5 strict模式下,为未声明的变量赋值会抛出错误。

单一var模式

在函数顶部对所有变量通过一个 var 进行声明。好处如下:

  • 提供一个单一的地址以找到函数所需的所有局部变量
  • 防止出现变量在定义前就被使用的逻辑错误
  • 帮助牢记要声明变量,以尽可能少地使用全局变量。
  • 更少的编码

单一var模式如下:

function func(){
    var a = 1,
        b = 2,
        sum = a + b,
        myobject = {},
        i,
        j;
    console.log(sum)
    // 函数体
}
func()

使用逗号操作符可以在一条语句中执行多个操作。多用于声明多个变量,但还可以用于赋值,总会返回表达式的最后一项。

(1) 逗号表达式的运算过程为:从左往右逐个计算表达式。

(2) 逗号表达式作为一个整体,它的值为最后一个表达式的值。var num = (5,4,1,0); // num 为 0。

(3) 逗号运算符的优先级别在所有运算符中最低。

代码处理上分为两个阶段

  1. 这是个阶段创建变量、函数声明及形式参数。这是解析和进入上、下文阶段。
  2. 第二个阶段是代码运行时执行过程,创建函数表达式和不合格标识符(未定义变量)。

for循环

for循环主要用于两种情况,遍历 数组 和 类数组对象(HTML容器对象)的。
数组就是Array对象, var arr = [1, 2, 3, 4]; 这就是一个数组。
HTML容器对象是DOM方法返回的对象,如:
document.getElementByName()
document.getElementsByClassName()
document.getElementsByTagName()
都是 dom方法返回的HTML容器对象。
还有很多其他HTML容器,他们在DOM标准以前就引入了,并一直使用至今。包括:
document.images        //页面上所有的IMG元素
documents.forms         //所有的Forms
document.links          //所有的A标签元素
document.forms[0].elements    //页面上第一个from内的所有字段
麻烦在于他们都在document下是活动的查询。每次访问任何容器的长度时,也就是在查询活动的DOM,非常耗时。

这就是为什么好的for循环模式是将已经遍历过的数组(或容器)的长度缓存起来。如:

for (var i = 0; i < myArray.length; i++) {
     // 对myArray进行操作  
}

在所有浏览器中,通过将HTML容器上需要遍历的次数缓存起来会大大提高速度。在safari3中会提高两倍,而IE7中会提高170倍。

for模式中的两个变量引出了一些操作,原因是:

  • 使用最少的变量
  • 逐步减至0,这样通常更快,因为同0比较比非同0数组比较更有效率。

修改后的模式:

//第一个
var i, myarray = [];
for (i = myArray.length; i--;) {
     // 对myArray进行操作  
}
//第二个用while
var myarray = [];
    i = myarray.length;
    while(i--){
    // 对myArray进行操作  
    }

for-in

刚刚提到,for循环主要是用于遍历数组和类数组对象的(统统与数组有关),而for-in循环主要是用于遍历一个普通对象的属性的(与数组无关)。

当遍历对象属性来过滤遇到原型链的属性时,使用hasOwnProperty()方法是非常重要的,原形链式活动的,有时候我们并不需要枚举出新方法。

for(var key in object) {
   if(object.hasOwnproperty(key)) {
      console.log(key, ":", object[key]);
      }
  }
  //另外一种模式
  var key,
      hasOWN = object.prototype.hasOwnproperty;
  for(key in object) {
   if(hasOwn.call(object,key)) {
      console.log(key, ":", object[key]);
      }
  }

避免使用隐式类型转换

使用 === 或 !== 进行比较。增强代码可阅读性,避免猜测。

避免使用eval()

其实这个还是很好理解的,因为大多数时候,我们很少见到使用eval()方法的情况。

并且记住:eval()是一个魔鬼

为什么? 因为eval()可以将任意字符串当作一个JavaScript代码来执行。

new Functin() 与 eval()的不同:

第一点:
new Function()中的代码将在局部函数空间运行,因此代码中任何采用var定义的变量不会自动成为全局变量(即在函数内)。
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); // 打印出 "1"

jsstring = "var deux = 2; console.log(deux);";
new Function(jsstring)(); // 打印出 "2"

jsstring = "var trois = 3; console.log(trois);";
(function () {
    eval(jsstring);
}()); // 打印出 "3"

console.log(typeof un); // "number"
console.log(typeof deux); // "undefined"
console.log(typeof trois); // "undefined"

第二点:
eval()会影响到作用域链,而Function则像一个沙盒,无论在哪里执行Function,它都仅能看到全局作用域链。因此对局部变量的影响比较小。

(function () {
    var local = 1;
    eval("local = 3; console.log(local)"); // 打印出 3
    console.log(local); // 打印出 3
}());

(function () {
    var local = 1;
    Function("console.log(typeof local);")(); // 打印出 undefined
}());

使用parseInt()进行数字转换

ECMAScript3中以0为前缀的字符串会被当作八进制数处理,这一点在ES5中已经有了改变。为了避免转换类型不一致而导致的意外结果,应当总是指定第二个参数:

var month = "06",
    year = "09";
    month = parseInt(month, 10);
	year = parseInt(year, 10);

字符串转换为数字还有两种方法:

+"08" // 结果为8,隐式调用Number()
Number("08") // 结果为8

这两种方法要比parseInt()更快一些,因为顾名思义parseInt()是一种“解析”而不是简单的“转换”。但当你期望将“08 hello”这类字符串转换为数字,则必须使用parseInt(),其他方法都会返回NaN。

下一章 函数篇

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值