JavaScript对象及函数机制

    看Angular.js时候感觉JavaScript水平吃紧,所以需要充点电咯!我个人对JavaScript这语言的看法是,既简单有复杂。简单在语言特性少,复杂在灵活性太大。花了几天看大致看完了《JavaScript语言精粹》。这本书也大致定位为JavaScript的进阶读物,所以还是有一些收获的。当然书中也还是有一些不清楚甚至不正确的东西。

    一切都还是要从proto变量开始,这是JavaScript很多语言特性的基础。

  1. 对象是“名/值”对的集合,JavaScript中的对象都有一个proto变量。

  2. 对象字面量的proto连接到Object.prototype;函数对象的proto连接到Function.prototype。

  3. Function.prototype.proto连接到Object.prototype。

  4. Object.prototype本身是一个对象,但是它不存在proto域。

    下面是验证上述结论的实验代码:

[code lang=JavaScript]
var print = function(string) {
document.writeln(string);
}

var student = {
name:'lshw',
id:123
};

var testFunction = function() {
}

//结论2
print(student.__proto__ === Object.prototype);
print(testFunction.__proto__ === Function.prototype);
//结论3
print(Function.prototype.__proto__ === Object.prototype);
print(typeof Object.prototype);
//结论4
print(Object.prototype.__proto__);
print(typeof Object.prototype);
[/code]

    我不知道作者是出于什么目的,对proto绝口不提。proto确实属于实现层面上的东西,然而个人觉得要真正理解JavaScript,proto是回避不了的。proto的作用体现在函数调用和对象值检索时,JavaScript引擎会沿着proto链上一直去寻找,直到终点Object.prototype。prototype内没有proto,所以这里就是搜索的终点。用伪代码表示就是:

[code lang=JavaScript]
function search(obj, key) {
if(obj.hasOwnProperty(key))
return obj[key];
if(obj.hasOwnProperty('__proto__'))
return search(obj[__proto__], key);
return undefine;
}
[/code]

    了解了proto之后,就要说到new关键字。

[code lang=JavaScript]
var func = function(){};

var p = new func();
[/code]

    对于上述的第二句代码,等价于如下代码:

[code lang=JavaScript]
p = {};
p.__proto__ = func.prototype;
func.call(p);
[/code]

    JavaScript本来是没有类型的,但是顺应OOP的潮流,JavaScript还是创造了伪类模式。伪类模式的
工作流程如下:

  • 1.定义一个伪类并扩充它的原型

    [code lang=JavaScript]
    var Mammal = function (name) {
    this.name = name;
    }

    Mammal.prototype.get_name = function() {
    return this.name;
    }
    [/code]

  • 2.构造一个实例,并调用构造器的方法

[code lang=JavaScript]
var myMammal = new Mammal('Herb the Mammal');
// 相当于myMammal.__proto__ = Mammal.prototype;
var name = myMammal.get_name();

var Cat = function(name) {
this.name = name;
this.saying = 'meow';
};
[/code]

  • 3.构造另一个伪类来继承Mammal,通过它自己的构造函数并替换它的prototype为另一个Mammal的实例来实现:

[code lang=JavaScript]
Cat.prototype = new Mammal();
//Cat.prototype.__proto__ = Mammal.prototype;
Cat.prototype.purr = function (n) {
var i, s = '';
for(i = 0; i < n; i+= 1) {
if(s) {
s += '-';
}
s += 'r';
}
return s;
};
[/code]

  • 4.构造一个实例,可以调用伪基类的方法。

[code lang=JavaScript]
var myCat = new Cat('Henrietta');
//myCat.__proto__ = Cat.prototype;
//所以有myCat.__proto__.__proto__ = Mammal.prototype;
var purr = myCat.purr(5);
[/code]

    这本书的作者其实一直在诟病这种伪类的设计模式,他更推崇的是原型模式。原型模式的核心就是在Object上添加create方法,实现代码如下。

[code lang=JavaScript]
Object.create = function (o) {
var F = function() {};
F.prototype = o;
return new F();
//p1.__proto__ = F.prototype;
//所以p1.__proto__等于o;
//return p1;
}
[/code]

    说实话,JS的设计者为了掩盖proto,也是煞费苦心呀!我倒觉得显式地操作proto其实更容易理解。目前觉得重要的东西大概就这么多了。

仅有1条评论 发表评论

  1. shuwei /

    没有其他的,just a test comment for Akismet!

发表评论