读书笔记(javascript语言精粹)

1. 注释:

在js中,/**/为块注释,//为行注释;但块注释在有些情况下是不安全的。如:

/*
   var rm_a = /a*/.match(s);     
*/

上面的注释导致了一个语法错误。所以,建议避免使用 /**/ 注释,而用 // 注释代替它。

2. true/false:

false:false,null,undefined,空字符串" " ,数字0,数字NaN;

true:除以上外所有的值,包括 true,字符串‘false’,以及所有的对象;

3. 对象:

(1)对象属性名可以包括空字符串在内的任何字符串,若属性名是一个合法的javascript标识符且不是保留字,则不强制要求用引号括住属性名。比如:若属性名为‘first-name’,则必须用引号括住,因为标识符中不允许有“-”;

(2)hasOwnProperty:如果对象拥有独有的属性,它将返回true。且它不会检查原型链;eg:obj.hasOwnProperty('a');  //obj对象中是否含有a属性;

(3)for in语句会枚举一个对象的所有属性名(或键名);通常还需要检测Object.hasOwnProperty(variable)来确定这个属性名是该对象的成员还是来自于原型链:

for(myvar in obj){
  if(obj.hasOwnProperty(myvar)){
        ...
    }  
    ...
}    

 

使用for in遍历一个对象中的属性名,属性名出现的顺序是不确定的,因此要对任何可能出现的顺序有所准备。如果你想要确保属性以特定的顺序出现,最好的办法就是完全避免使用for in语句,而是创建一个数组,在其中以正确的顺序包含属性名。通过使用for而不是for in,可以得到我们想要的属性,而不用担心可能发掘出原型链中的属性,并且按照正确的顺序取得了它们的值。

(4)delete:delete不会触及原型链中的任何对象;

对于有被遍历需求,且值 null 被认为具有业务逻辑意义的值的对象,移除某个属性必须使用 delete 操作。

在严格模式或IE下使用 delete 时,不能被删除的属性会抛出异常,因此在不确定属性是否可以删除的情况下,建议添加 try-catch 块。

try {
    delete o.x;
}
catch (deleteError) {
    o.x = null;
}

(5)类型检测: 类型检测优先使用 typeof 。对象类型检测使用 instanceof 。null 或 undefined 的检测使用 == null 。正则表达式 typeof 结果为“object”。

// string
typeof variable === 'string'

// number
typeof variable === 'number'

// boolean
typeof variable === 'boolean'

// Function
typeof variable === 'function'

// Object
typeof variable === 'object'

// RegExp
variable instanceof RegExp

// Array
variable instanceof Array

// null
variable === null

// null or undefined
variable == null

// undefined
typeof variable === 'undefined'

 (6)返回: 一个函数总是会返回一个值。如果没有指定返回值,则返回undefined;如果函数调用时在前面加上了new前缀,且返回值不是一个对象,则返回this(该新对象);

 (7)原型/继承: var obj = Object.create(构造函数):此时新创建的对象实例将继承构造函数的所有属性方法;

//继承——部件
var
eventuality = function (that) { var registry = {}; that.fire = function (event) { var array, func, handler, i, type = typeof event === 'string' ? event : event.type; if(registry.hasownProperty(type)){ array = registry[type]; for(i = 0; i < array.length; i += 1){ handler = array[i]; func = handler.method; if(typeof func === 'string'){ func = this[func]; } func.apply(this, handler.parameters || [event]); } } return this; }; that.on = function(type, method, parameters){ var handlers = { method: method, parameters: parameters }; if (registry.hasOwnProperty[type]) { registry[type].push(handler); } else { registry[type] = [handler]; } return this; }; return that; };

 4. 数组:

 (1)数组有一个splice方法,可以删除数组的一些元素并将它们替换为其他的元素。但被删除属性后面的每个属性必须被移除,并且以一个新的键值重新插入,对于大型数组来说,可能导致效率不高;

 (2)判断一个对象为数组的更好的方式:

var is_array = function(value){
  return Object.prototype.toString.apply(value) === '[object Array]';  
}

 (3)Object.create方法用在数组是没有意义的,因为它产生一个对象,而不是一个数组。产生的对象将继承这个数组的值和方法,但它没有那个特殊的length属性;

5.方法: 

(1)数组:

array.splice(start, deleteCount, item...):它返回一个包含被移除元素的数组;

splice还可以如下这样实现:

Array.method('splice', function (start, deleteCount) {
    var max = Math.max,
        min = Math.min,
        delta,
        element,
        insertCount = max(arguments.length - 2, 0),
        k = 0,
        len = this.length,
        new_len,
        result = [],
        shift_count;
    start = start || [];
    if (start < 0) {
        start += len;
    }
    start = max(min(start, len), 0);
    deleteCount = max(min(typeof deleteCount === 'number' ?
        deleteCount : 
        len, len - start), 0);
    delta = insertCount - deleteCount;
    new_len = len + delta;
    while (k < deleteCount) {
        element = this[start + k];
        if(element !== undefined){
            result[k] = element;
        }
        k += 1;
    }

    shift_count = len - start - deleteCount;
    if (delta < 0) {
        k = start + insertCount;
        while (shift_count) {
            this[k] = this[k - delta];
            k += 1;
            shift_count -= 1;
        }
        this.length = new_len;
    } else if (delta > 0) {
        k = 1;
        while (shift_count) {
            this[new_len - k] = this[len - k];
            k += 1;
            shift_count -= 1;
        }
        this.length = new_len;
    }

    for (k = 0; k < insertCount; k += 1) {
        this[start + k] = arguments[k + 2];
    }

    return result;
});

 

array.unshift(item...):它返回array的新的length;

(2)Number: 

number.toExponential(fractionDigits):把这个number转换成一个指数形式的字符串;

number.toFixed(fractionDigits):把这个number转换成一个十进制数形式的字符串;

number.toPrecision(precision):把这个number转换成一个十进制形式的字符串;

(3)RegExp:

regexp.exec(string):exec是使用正则表达式最强大(和最慢)的方法;

regexp.test(string):test方法是使用正则表达式的最简单(和最快)的方法;

 6. 一些糟粕:

(1)parseInt:把字符串转化为整数。

如果该字符串第1个字符是0,那么该字符串会基于八进制而不是十进制来求值。这个错误会导致程序解析日期和时间时出现问题。幸运的是,parseInt可以接受一个基数作为参数,如此一来,parseInt(“08”,10)结果为8。建议总是加上这个基数参数。

 (2)+:

如果其中一个运算数是一个空字符串,它会把另一个运算数转换为字符串并返回。如果两个运算数都是数字,它返回两者之和。否则,它把两个运算数都转换为字符串并连接起来。这个是bug的常见来源:如果打算用+作加法运算,要确保两个运算数都是整数。

(3)浮点数:

二进制的浮点数不能正确的处理十进制的小数,因此0.1 + 0.2 不等于0.3,但浮点数的整数运算都是精确的,所以小数表现出来的错误可以通过指定精度来避免。

举例来说,美元可以通过乘以100而全部转为美分,然后就可以准确的将美分相加。它们的和可以再除以100转换为美元。

(4)eval:降低了应用程序的安全性,且降低了性能,应避免使用;

浏览器提供的 setTimeout 和 setInterval 函数,它们能接受字符串参数或函数传参。当传递的是字符串传参时, setTimeout 和 setInterval 会像eval那样去处理。同样也应当避免使用字符串参数形式。

(5)continue语句:

continue语句跳到循环的顶部。当移除 continue 语句后,性能都会得到改善。

(6)类型的包装对象: 

不要使用 new Bollean()、new Number()、new String();也要避免使用 new Object() 、new Array(),可使用 { } 和 [ ] 来代替。

 

附: 关于 typeOf 正则表达式及let/const 变量及 document.all

 

posted @ 2017-07-27 15:39  沐子馨  阅读(221)  评论(0编辑  收藏  举报