JavaScript对象及函数机制

= 2981

    看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域。

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

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);

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

function search(obj, key) {
    if(obj.hasOwnProperty(key))
        return  obj[key];
    if(obj.hasOwnProperty('__proto__'))
        return search(obj[__proto__], key);
    return undefine;
}

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

var func = function(){};

var p = new func();

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

p = {};
p.__proto__ = func.prototype;
func.call(p);

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

  • 1.定义一个伪类并扩充它的原型
    var Mammal = function (name) {
        this.name = name;
    }
    
    Mammal.prototype.get_name = function() {
        return this.name;
    }
    
  • 2.构造一个实例,并调用构造器的方法

    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';
    };
  • 3.构造另一个伪类来继承Mammal,通过它自己的构造函数并替换它的prototype为另一个Mammal的实例来实现:
    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;
    };
  • 4.构造一个实例,可以调用伪基类的方法。
    var myCat = new Cat('Henrietta');
    //myCat.__proto__ = Cat.prototype;
    //所以有myCat.__proto__.__proto__ = Mammal.prototype;
    var purr = myCat.purr(5);

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

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

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

仅有1条评论 发表评论

  1. shuwei /

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

发表评论