Javascript语言精粹

检索

检索一个并不存在的成员属性的值,将返回undefined

flight.status  //undefined

  || 运算符可以用来填充默认值

var status = flight.status || "unknown";

  尝试从undefined的成员属性中取值,将会报错TypeError。这时可以通过&&运算符来避免错误

flight.equipment  //undefined
flight.equipment.model  //Throw "TypeError"
flight.equipment && flight.equipment.model  //undefined

  

引用

对象通过引用来传递。他们永远不会被复制。

var a = {}, b = {}, c = {}; //a,b,c每个都引用一个不同的空对象
var a = b = c = {};  //a,b,c都引用同一个空对象

  

原型

如果我们尝试去获取对象的某个属性值,但该对象并没有此属性名,那么Javascript会试着从原型对象中获取属性值。

如果哪个原型对象也没有该属性,那么再从它的原型中查找。以此类推,直到最后到达终点 Object.prototype

如果想要的属性完全不存在于原型链中,那么结果就是undefined值。

这个过程称为委托

 

反射

//反射机制指的是程序在运行时能够获取自身的信息。
//如:一个对象能够在运行时知道自己有哪些方法和属性。

检查对象并确定对象有什么属性是很容易的事情。

typeof操作符对确定属性的类型很有帮助:

typeof flight.number //'number'
typeof flight.status  //'string'
typeof flight.manifest  //'undefined'

  注意原型链中的任意属性都会产生值:

typeof flight.toString  //'function'
typeof flight.constructor  //'function'

有两种方法去处理这些不需要的属性:

第一个是检查并丢弃值为函数的属性。

第二种是使用hasOwnProperty方法:

如果对象拥有独有的属性,它将返回true,hasOwnProperty方法不会检查原型链。

flight.hasOwnProperty('number');  //true
flight.hasOwnProperty('constructor');  //false

 

枚举

for in 语句可以枚举所有的属性——包括函数和原型中的属性。最好用for代替之。

以特定顺序枚举对象的属性:

var i;
var properties = [
    'first-name',
    'middle-name',
    'last-name',
    'profession'
];
for(i=0; i<properties.length; i++){
    document.writeln(properties[i] + ":" + 
                     another_stooge[properties[i]]);
}

  

函数的调用 

调用一个函数会暂停当前函数的执行,传递控制权和参数给新函数。

函数总会附加两个参数:this 和 arguments。

this的值取决于调用模式:

  • 方法调用模式
  • 函数调用模式
  • 构造器调用模式
  • apply调用模式

当实际参数的个数和形式参数的个数不匹配时:

如果实际参数值过少,缺失的值会被替换为undefined。

方法调用模式

当一个函数被保存为对象的一个属性时,我们称它为一个方法。此时,this被绑定到该对象。

函数调用模式

当一个函数并非对象的属性时,那么它就是被当做一个函数来调用。此时,this被绑定到全局对象。(这是语言设计上的一个错误)

解决方案:使用that

构造器调用模式

如果一个前面带上new来调用,那么背地里将会创建一个连接到该函数的prototype成员的新对象。同时,this被绑定到新对象上。

var myQuo = new Quo("confused");

按照约定,它们保存在以大写命名的变量里。(我们不推荐这种调用方式)

apply调用模式

函数可以拥有方法。

apply方法接收两个参数:1个是要绑定给this的值。第2个是一个参数数组。

var arr = [3, 4];
var sum = add.apply(null, arr);

var statusObject = {
    status: "A-OK"
};
// 我们可以在statusObject对象上调用get_status方法
// 尽管statusObject对象并没有该方法
var status = Quo.prototype.get_status.apply(statusObject);

  

 

参数

函数被调用时,会得到一个免费的参数——arguments数组。

但arguments并不是一个真正的数组,它拥有一个length属性,但没有任何数组方法。

 

 

返回

当一个函数被调用时,它从第一个语句开始执行,并在遇到 } 时结束。

然后把控制权交还给调用该函数的程序。

return 可以使函数提前返回,不再执行余下语句。

一个函数总会返回一个值,如果没有指定返回值,则返回undefined。

如果函数调用时,在前面加上了new前缀,且返回值不是一个对象,则返回该新对象(this)

 

 

扩充类型的功能

我们可以通过Object.prototype添加方法。同样,可以对函数,数组,字符串,数字,正则表达式,布尔值添加。

举例来说,可以通过给 Function.prototype 增加方法来使得该方法对所有函数可用。

Function.prototype.method = function(name, func){
    this.prototype[name] = func;
    return this;
};

给Function.prototype增加一个method方法,我们下次给对象添加方法的时候,就不必键入prototype这几个字符了。

javascript中没有专门的整数类型,但有事我们需要提取数字中的整数部分。

Number.method('integer', function(){
    // 根据正负来使用Math.ceil或者Math.floor
    return Math[this < 0 ? 'ceil' : 'floor'](this);
});

  

基本类型的原型是公用结构,所以在类库混用时务必小心。

保险做法是在确定没有该方法时才添加它。

Function.prototype.method = function(name, func){
    if(!this.prototype[name]){
        this.prototype[name] = func;
    }
    
    return this;
};

  

 

posted @ 2015-06-12 11:19  GallenHu  阅读(361)  评论(0)    收藏  举报